codeparser_C #192

Merged
peri4 merged 3 commits from codeparser_C into master 2025-09-18 20:19:11 +03:00
17 changed files with 395 additions and 178 deletions

View File

@@ -5,8 +5,8 @@ if (POLICY CMP0177)
endif() endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 2) set(PIP_MINOR 3)
set(PIP_REVISION 1) set(PIP_REVISION 0)
set(PIP_SUFFIX ) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS) set(PIP_DOMAIN org.SHS)

View File

@@ -59,6 +59,7 @@ PICodeInfo::__Storage__::__Storage__() {
enumsInfo = new PIMap<PIConstChars, EnumInfo *>; enumsInfo = new PIMap<PIConstChars, EnumInfo *>;
accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>; accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>;
accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>; accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>;
accessOffsetFunctions = new PIMap<PIConstChars, AccessOffsetFunction>;
(*enumsInfo)[""] = new EnumInfo(); (*enumsInfo)[""] = new EnumInfo();
} }
@@ -70,6 +71,7 @@ PICodeInfo::__Storage__::~__Storage__() {
piDeleteSafety(enumsInfo); piDeleteSafety(enumsInfo);
piDeleteSafety(accessValueFunctions); piDeleteSafety(accessValueFunctions);
piDeleteSafety(accessTypeFunctions); piDeleteSafety(accessTypeFunctions);
piDeleteSafety(accessOffsetFunctions);
} }

View File

@@ -58,6 +58,7 @@ typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
typedef PIByteArray (*AccessValueFunction)(const void *, const char *); typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
typedef const char * (*AccessTypeFunction)(const char *); typedef const char * (*AccessTypeFunction)(const char *);
typedef int (*AccessOffsetFunction)(const char *);
//! \~english Type information //! \~english Type information
@@ -120,15 +121,15 @@ struct PIP_EXPORT FunctionInfo {
//! \~english Class or struct information //! \~english Class or struct information
//! \~russian Информация о классе или структуре //! \~russian Информация о классе или структуре
struct PIP_EXPORT ClassInfo { struct PIP_EXPORT ClassInfo {
ClassInfo() { has_name = true; } ClassInfo() { is_anonymous = false; }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA //! \~russian Произвольное содержимое PIMETA
MetaMap meta; MetaMap meta;
//! \~english Has name or not //! \~english Anonymous or not
//! \~russian Имеет или нет имя //! \~russian Анонимный или нет
bool has_name; bool is_anonymous;
//! \~english Type //! \~english Type
//! \~russian Тип //! \~russian Тип
@@ -289,20 +290,24 @@ public:
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo; PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions; PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> * accessOffsetFunctions;
private: private:
NO_COPY_CLASS(__Storage__) NO_COPY_CLASS(__Storage__)
}; };
class PIP_EXPORT __StorageAccess__ { class PIP_EXPORT
public: __StorageAccess__{public:
//! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name //! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name
//! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени //! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() { return *(__Storage__::instance()->classesInfo); } static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes(){return *(__Storage__::instance()->classesInfo);
} // namespace PICodeInfo
//! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name //! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени //! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); } static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() {
return *(__Storage__::instance()->enumsInfo);
}
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
return *(__Storage__::instance()->accessValueFunctions); return *(__Storage__::instance()->accessValueFunctions);
@@ -311,44 +316,51 @@ public:
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
return *(__Storage__::instance()->accessTypeFunctions); return *(__Storage__::instance()->accessTypeFunctions);
} }
};
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
return *(__Storage__::instance()->accessOffsetFunctions);
}
}
;
#define PICODEINFO PICodeInfo::__StorageAccess__ #define PICODEINFO PICodeInfo::__StorageAccess__
class PIP_EXPORT ClassInfoInterface { class PIP_EXPORT
public: ClassInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()"){
const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") {
return __Storage__::instance() -> classesInfo; return __Storage__::instance() -> classesInfo;
} }
}; }
;
static ClassInfoInterface classesInfo; static ClassInfoInterface classesInfo;
class PIP_EXPORT EnumsInfoInterface { class PIP_EXPORT
public: EnumsInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()"){
const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") {
return __Storage__::instance() -> enumsInfo; return __Storage__::instance() -> enumsInfo;
} }
}; }
;
static EnumsInfoInterface enumsInfo; static EnumsInfoInterface enumsInfo;
class PIP_EXPORT AccessValueFunctionInterface{ class PIP_EXPORT AccessValueFunctionInterface{
public: public: const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->()
const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") { const DEPRECATEDM("use PICODEINFO::accessValueFunctions()"){
return __Storage__::instance() -> accessValueFunctions; return __Storage__::instance() -> accessValueFunctions;
} }
}; }
;
static AccessValueFunctionInterface accessValueFunctions; static AccessValueFunctionInterface accessValueFunctions;
class PIP_EXPORT AccessTypeFunctionInterface{ class PIP_EXPORT AccessTypeFunctionInterface{
public: public: const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->()
const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") { const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()"){
return __Storage__::instance() -> accessTypeFunctions; return __Storage__::instance() -> accessTypeFunctions;
} }
}; }
;
static AccessTypeFunctionInterface accessTypeFunctions; static AccessTypeFunctionInterface accessTypeFunctions;

View File

@@ -19,6 +19,8 @@
#include "picodeparser.h" #include "picodeparser.h"
#include "piliterals_string.h"
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const { PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
PIStringList arg_vals; PIStringList arg_vals;
@@ -454,7 +456,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
cur_namespace += pfc.takeCWord() + s_ns; cur_namespace += pfc.takeCWord() + s_ns;
ccmn = pfc.takeRange('{', '}'); ccmn = pfc.takeRange('{', '}');
// piCout << "namespace" << cur_namespace; // piCout << "namespace" << cur_namespace;
parseClass(0, ccmn, true); parseClass(nullptr, ccmn, true);
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
continue; continue;
} }
@@ -483,8 +485,8 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
continue; continue;
} }
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc; ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size()); pfc.remove(0, ccmn.size() - 2);
parseClass(0, ccmn, false); parseClass(nullptr, ccmn, false);
continue; continue;
} }
if (pfc.left(4) == s_enum) { if (pfc.left(4) == s_enum) {
@@ -499,17 +501,59 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
meta << smeta; meta << smeta;
} }
// piCout << "pfc E" << cur_namespace << "," << tmp; // piCout << "pfc E" << cur_namespace << "," << tmp;
parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta); parseEnum(nullptr, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
if (pfc.left(7) == s_typedef) { if (pfc.left(7) == s_typedef) {
pfc.cutLeft(7); pfc.cutLeft(7);
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';'))); PIString typedef_type = pfc.takeCWord();
if (typedef_type == s_class || typedef_type == s_struct || typedef_type == s_union) {
int dind = pfc.find('{', 0), find = pfc.find(';', 0);
if (dind < 0 && find < 0) {
pfc.cutLeft(6);
continue;
}
if (dind < 0 || find < dind) {
pfc.cutLeft(find + 1);
continue;
}
PIString cname = pfc.left(dind);
ccmn = cname + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size() - 3);
if (cname.trimmed().isEmpty()) {
cname = pfc.takeCWord();
ccmn.prepend(cname);
}
ccmn.prepend(typedef_type + " "_a);
parseClass(nullptr, ccmn, false);
} else if (typedef_type == s_enum) {
tmp = pfc.takeCWord();
pfc.trim();
MetaMap meta = maybeMeta(pfc);
if (tmp == s_class || tmp == s_struct) {
tmp = pfc.takeCWord();
pfc.trim();
MetaMap smeta = maybeMeta(pfc);
meta << smeta;
}
ccmn = pfc.takeRange('{', '}');
if (tmp.isEmpty()) {
tmp = pfc.takeCWord();
}
// piCout << "pfc E" << cur_namespace << "," << tmp;
parseEnum(nullptr, cur_namespace + tmp, ccmn, meta);
} else {
pfc.prepend(typedef_type);
}
PIString last = pfc.takeLeft(pfc.find(';')).trim();
if (last.isNotEmpty()) {
typedefs << parseTypedef(last);
if (typedefs.back().first.isEmpty()) if (typedefs.back().first.isEmpty())
typedefs.pop_back(); typedefs.pop_back();
else else
root_.typedefs << typedefs.back(); root_.typedefs << typedefs.back();
}
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
@@ -567,15 +611,14 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
Visibility vis = cur_def_vis; Visibility vis = cur_def_vis;
cur_def_vis = (is_class ? Private : Public); cur_def_vis = (is_class ? Private : Public);
PIString cn = cd.mid(6).trim(); PIString cn = cd.mid(6).trim();
bool has_name = !cn.isEmpty(); bool is_anonymous = cn.isEmpty();
if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>'; if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>';
// piCout << "found " << typename_ << cn; // piCout << "found " << typename_ << cn;
if (cn.isEmpty()) return nullptr;
Entity * e = new Entity(); Entity * e = new Entity();
e->meta = meta; e->meta = meta;
e->name = cur_namespace + cn; e->name = cur_namespace + cn;
e->type = typename_; e->type = typename_;
e->has_name = has_name; e->is_anonymous = is_anonymous;
e->parents = parents; e->parents = parents;
e->visibility = vis; e->visibility = vis;
e->file = cur_file; e->file = cur_file;
@@ -584,7 +627,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
} }
void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) { PICodeParser::Entity * PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) {
static const PIString s_ns = PIStringAscii("::"); static const PIString s_ns = PIStringAscii("::");
static const PIString s_public = PIStringAscii("public"); static const PIString s_public = PIStringAscii("public");
static const PIString s_protected = PIStringAscii("protected"); static const PIString s_protected = PIStringAscii("protected");
@@ -599,7 +642,7 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
static const PIString s_template = PIStringAscii("template"); static const PIString s_template = PIStringAscii("template");
Visibility prev_vis = cur_def_vis; Visibility prev_vis = cur_def_vis;
int dind = fc.find('{'), find = fc.find(';'), end = 0; int dind = fc.find('{'), find = fc.find(';'), end = 0;
if (dind < 0 && find < 0) return; if (dind < 0 && find < 0) return nullptr;
// piCout << "parse class <****\n" << fc << "\n****>"; // piCout << "parse class <****\n" << fc << "\n****>";
Entity * ce = parent; Entity * ce = parent;
if (!is_namespace) { if (!is_namespace) {
@@ -608,7 +651,6 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
} }
// piCout << "found class <****\n" << fc << "\n****>"; // piCout << "found class <****\n" << fc << "\n****>";
if (ce) { if (ce) {
if (parent) parent->children << ce;
ce->parent_scope = parent; ce->parent_scope = parent;
} }
int ps = -1; int ps = -1;
@@ -650,11 +692,29 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
fc.takeSymbol(); fc.takeSymbol();
continue; continue;
} }
tmp = fc.takeLeft(fc.find('{')); tmp = fc.takeLeft(fc.find('{')).trim();
stmp = fc.takeRange('{', '}'); stmp = fc.takeRange('{', '}');
fc.takeSymbol();
stmp = cw + ' ' + tmp + '{' + stmp + '}'; stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp, false); auto new_entity = parseClass(ce, stmp, false);
// piCout << "!!! > \"" << fc << "\"";
PIStringList vars;
PIString var;
do {
var = fc.takeCWord();
if (var.isNotEmpty()) vars << var;
if (fc.takeSymbol() == ";") break;
} while (var.isNotEmpty());
if (new_entity) {
Member me;
me.visibility = cur_def_vis;
me.type = new_entity->name;
if (tmp.isEmpty() && vars.isEmpty()) vars = {""};
for (const auto & v: vars) {
me.name = v;
ce->members << me;
}
}
// piCout << "!!! <" << vars;
continue; continue;
} }
if (cw == s_enum) { if (cw == s_enum) {
@@ -710,6 +770,7 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
} }
cur_def_vis = prev_vis; cur_def_vis = prev_vis;
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
return ce;
} }
@@ -766,7 +827,7 @@ bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc
PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
// piCout << "parse typedef" << fc; // piCout << "parse typedef \"" << fc << "\"";
Typedef td; Typedef td;
fc.replaceAll('\t', ' '); fc.replaceAll('\t', ' ');
@@ -1197,7 +1258,7 @@ void PICodeParser::replaceMeta(PIString & dn) {
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) { PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
for (auto * e: entities) for (auto * e: entities)
if (e->name == en) return e; if (e->name == en) return e;
return 0; return nullptr;
} }

View File

@@ -100,7 +100,7 @@ public:
struct PIP_EXPORT Entity { struct PIP_EXPORT Entity {
Entity() { Entity() {
visibility = Global; visibility = Global;
has_name = true; is_anonymous = false;
size = 0; size = 0;
parent_scope = 0; parent_scope = 0;
} }
@@ -110,10 +110,9 @@ public:
PIString file; PIString file;
Visibility visibility; Visibility visibility;
int size; int size;
bool has_name; bool is_anonymous;
Entity * parent_scope; Entity * parent_scope;
PIVector<Entity *> parents; PIVector<Entity *> parents;
PIVector<Entity *> children;
PIVector<Member> functions; PIVector<Member> functions;
PIVector<Member> members; PIVector<Member> members;
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
@@ -164,7 +163,7 @@ private:
bool parseFileContent(PIString & fc, bool main); bool parseFileContent(PIString & fc, bool main);
bool parseDirective(PIString d); bool parseDirective(PIString d);
Entity * parseClassDeclaration(const PIString & fc); Entity * parseClassDeclaration(const PIString & fc);
void parseClass(Entity * parent, PIString & fc, bool is_namespace); Entity * parseClass(Entity * parent, PIString & fc, bool is_namespace);
MetaMap parseMeta(PIString & fc); MetaMap parseMeta(PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta); bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
Typedef parseTypedef(PIString fc); Typedef parseTypedef(PIString fc);

View File

@@ -225,17 +225,20 @@ bool PIVariant::operator==(const PIVariant & v) const {
PIVariant::Type PIVariant::typeFromName(const PIString & tname) { PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
PIString s = tname.trimmed().toLowerCase().replaceAll(" ", ""); PIString s = tname.trimmed().toLowerCase().replaceAll(" ", "");
if (s == "bool" || s == "boolean") return PIVariant::pivBool; if (s == "bool" || s == "boolean") return PIVariant::pivBool;
if (s == "char" || s == "sbyte") return PIVariant::pivChar; if (s == "char" || s == "sbyte" || s == "int8_t") return PIVariant::pivChar;
if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword") return PIVariant::pivShort; if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword" || s == "int16_t")
if (s == "int" || s == "signed" || s == "signedint") return PIVariant::pivInt; return PIVariant::pivShort;
if (s == "int" || s == "signed" || s == "signedint" || s == "int32_t") return PIVariant::pivInt;
if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::pivInt; if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::pivInt;
if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword") if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword" ||
s == "int64_t")
return PIVariant::pivLLong; return PIVariant::pivLLong;
if (s == "uchar" || s == "byte") return PIVariant::pivUChar; if (s == "uchar" || s == "byte" || s == "uint8_t") return PIVariant::pivUChar;
if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word") return PIVariant::pivUShort; if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word" || s == "uint16_t") return PIVariant::pivUShort;
if (s == "uint" || s == "unsigned" || s == "unsignedint") return PIVariant::pivUInt; if (s == "uint" || s == "unsigned" || s == "unsignedint" || s == "uint32_t") return PIVariant::pivUInt;
if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::pivUInt; if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::pivUInt;
if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword") return PIVariant::pivULLong; if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword" || s == "uint64_t")
return PIVariant::pivULLong;
if (s == "float") return PIVariant::pivFloat; if (s == "float") return PIVariant::pivFloat;
if (s == "double" || s == "real") return PIVariant::pivDouble; if (s == "double" || s == "real") return PIVariant::pivDouble;
if (s == "ldouble" || s == "longdouble") return PIVariant::pivLDouble; if (s == "ldouble" || s == "longdouble") return PIVariant::pivLDouble;

View File

@@ -46,8 +46,15 @@ const char help_string[] = "-M (Metainfo)\n"
"with simple << and >> operators.\n" "with simple << and >> operators.\n"
"If PIMETA(no-stream) presence, then class or struct ignored.\n" "If PIMETA(no-stream) presence, then class or struct ignored.\n"
"\n" "\n"
"-J (JSON serialization)\n"
"Generate serialize/deserialize methods for classes and structures.\n"
"These methods uses by PIJSON::serialize(T v) and PIJSON::deserialize(json)\n"
"allow automatic conversion to/from PIJSON. Use member name as key.\n"
"Member can be skipped by providing PIMETA(id=-).\n"
"If PIMETA(no-json) presence, then class or struct ignored.\n"
"\n"
"-G (Getter functions)\n" "-G (Getter functions)\n"
"Generate anonymous access methods for member typenames and values.\n" "Generate anonymous access methods for member typenames, values and offsets.\n"
"Every class or struct member typename can be obtained with:\n" "Every class or struct member typename can be obtained with:\n"
"const char * getMemberType(const char * class_name, const char * member_name)\n" "const char * getMemberType(const char * class_name, const char * member_name)\n"
"Member value can be obtained with:\n" "Member value can be obtained with:\n"
@@ -55,6 +62,7 @@ const char help_string[] = "-M (Metainfo)\n"
"where \"p\" - class or struct pointer, and returns serialized value.\n" "where \"p\" - class or struct pointer, and returns serialized value.\n"
"PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n" "PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n"
"where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n" "where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
"If PIMETA(no-getter) presence, then class or struct ignored.\n"
""; "";
@@ -126,3 +134,8 @@ PIString toCName(const PIString & s) {
ret.replaceAll("__", "_"); ret.replaceAll("__", "_");
return ret; return ret;
} }
PICodeParser::Entity * findEntity(Runtime & rt, const PIString & type) {
return rt.parser.findEntityByName(type);
}

View File

@@ -35,5 +35,6 @@ void usage();
void help(); void help();
PIString toCName(const PIString & s); PIString toCName(const PIString & s);
PICodeParser::Entity * findEntity(Runtime & rt, const PIString & type);
#endif #endif

View File

@@ -22,27 +22,100 @@
#include "stream.h" #include "stream.h"
void writeGetterTypeMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PISet<int> used_id;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeGetterTypeMembers(rt, type, var_prefix + m.name);
continue;
}
}
rt.ts << "\tif (strcmp(name, \"" << var_prefix << m.name << "\") == 0) return \"" << m.type;
// if (m.isBitfield()) rt.ts << ":" << m.bits;
rt.ts << "\";\n";
}
}
void writeGetterValueMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PISet<int> used_id;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeGetterValueMembers(rt, type, var_prefix + m.name);
continue;
}
}
rt.ts << "\tif (strcmp(name, \"" << var_prefix << m.name << "\") == 0) {";
if (m.isBitfield()) {
rt.ts << "ret = piSerialize(static_cast<" << m.type << ">(o->" << var_prefix << m.name << "));";
} else
rt.ts << "serialize(ret, o->" << var_prefix << m.name << ");";
rt.ts << " return ret;}\n";
}
}
void writeGetterOffsetMembers(Runtime & rt, const PICodeParser::Entity * e, PIString entity_name, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PISet<int> used_id;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || !m.dims.isEmpty() || m.isBitfield() || (m.visibility != PICodeParser::Public)) continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeGetterOffsetMembers(rt, type, entity_name, var_prefix + m.name);
continue;
}
}
rt.ts << "\tif (strcmp(name, \"" << var_prefix << m.name << "\") == 0) ";
rt.ts << "return PICODEINFO_OFFSET(" << entity_name << ", " << var_prefix << m.name << ");\n";
}
}
void makeGetterType(Runtime & rt, const PICodeParser::Entity * e) { void makeGetterType(Runtime & rt, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return; if (!needClassGetter(e)) return;
rt.ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n"; rt.ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
rt.ts << "\tif (!name) return \"\";\n"; rt.ts << "\tif (!name) return \"\";\n";
for (const PICodeParser::Member & m: e->members) { writeGetterTypeMembers(rt, e);
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
rt.ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) return \"" << m.type << "\";\n";
}
rt.ts << "\treturn \"\";\n}\n"; rt.ts << "\treturn \"\";\n}\n";
} }
void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e) { void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return; if (!needClassGetter(e)) return;
rt.ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n"; rt.ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
rt.ts << "\tPIByteArray ret;\n"; rt.ts << "\tPIByteArray ret;\n";
rt.ts << "\tif (!p || !name) return ret;\n"; rt.ts << "\tif (!p || !name) return ret;\n";
rt.ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n"; rt.ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n";
for (const PICodeParser::Member & m: e->members) { writeGetterValueMembers(rt, e);
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
rt.ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
}
rt.ts << "\treturn ret;\n}\n"; rt.ts << "\treturn ret;\n}\n";
} }
void makeGetterOffset(Runtime & rt, const PICodeParser::Entity * e) {
if (!needClassGetter(e)) return;
rt.ts << "\nint getterOffset" << toCName(e->name) << "(const char * name) {\n";
rt.ts << "\tif (!name) return 0;\n";
writeGetterOffsetMembers(rt, e, e->name);
rt.ts << "\treturn 0;\n}\n";
}
bool needClassGetter(const PICodeParser::Entity * e) {
if (e->meta.contains("no-getter")) return false;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
if (m.attributes[PICodeParser::Static]) continue;
return true;
}
return false;
}

View File

@@ -22,7 +22,12 @@
#include "common.h" #include "common.h"
void writeGetterTypeMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
void writeGetterValueMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
void writeGetterOffsetMembers(Runtime & rt, const PICodeParser::Entity * e, PIString entity_name, PIString var_prefix = {});
void makeGetterType(Runtime & rt, const PICodeParser::Entity * e); void makeGetterType(Runtime & rt, const PICodeParser::Entity * e);
void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e); void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e);
void makeGetterOffset(Runtime & rt, const PICodeParser::Entity * e);
bool needClassGetter(const PICodeParser::Entity * e);
#endif #endif

View File

@@ -22,7 +22,8 @@
#include "pitranslator.h" #include "pitranslator.h"
bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e) { bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PIVector<PICodeParser::Member> ml; PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) { for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue; if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
@@ -30,12 +31,19 @@ bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e) {
} }
bool is_union = e->type == "union"; bool is_union = e->type == "union";
for (const PICodeParser::Member & m: ml) { for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue; if (m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue; if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue; if (m.meta.value("id") == "-") continue;
// if (m.meta.contains("id")) cnt = m.meta.value("id").toInt(); // if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeClassJSONMembersOut(rt, type, var_prefix + m.name);
continue;
}
}
if (m.dims.isEmpty()) { if (m.dims.isEmpty()) {
rt.ts << "\tret[\"" << m.name << "\"] = piSerializeJSON(v." << m.name << ");\n"; rt.ts << "\tret[\"" << var_prefix << m.name << "\"] = piSerializeJSON(v." << var_prefix << m.name << ");\n";
} else { } else {
PIString ptype = m.type.left(m.type.find('[')).trim(); PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0]; PIString size = m.dims[0];
@@ -43,21 +51,22 @@ bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e) {
size += " * "; size += " * ";
size += m.dims[i]; size += m.dims[i];
} }
rt.ts << "\tret[\"" << m.name << "\"] = piSerializeJSON(PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name rt.ts << "\tret[\"" << var_prefix << m.name << "\"] = piSerializeJSON(PIVector<" << ptype << " >((const " << ptype << " *)(v."
<< "), " << size << "));\n"; << var_prefix << m.name << "), " << size << "));\n";
} }
if (is_union) break; if (is_union) break;
} }
if (is_union) return true; if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) { /*for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue; if (!ce->is_anonymous) continue;
if (!writeClassJSONMembersOut(rt, ce)) return false; if (!writeClassJSONMembersOut(rt, ce)) return false;
} }*/
return true; return true;
} }
bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e) { bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PIVector<PICodeParser::Member> ml; PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) { for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue; if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
@@ -66,12 +75,19 @@ bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e) {
bool is_union = e->type == "union"; bool is_union = e->type == "union";
PISet<int> used_id; PISet<int> used_id;
for (const PICodeParser::Member & m: ml) { for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue; if (m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue; if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue; if (m.meta.value("id") == "-") continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeClassJSONMembersIn(rt, type, var_prefix + m.name);
continue;
}
}
// if (m.meta.contains("id")) cnt = m.meta.value("id").toInt(); // if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (m.dims.isEmpty()) { if (m.dims.isEmpty()) {
rt.ts << "\tpiDeserializeJSON(v." << m.name << ", js[\"" << m.name << "\"]);\n"; rt.ts << "\tpiDeserializeJSON(v." << var_prefix << m.name << ", js[\"" << var_prefix << m.name << "\"]);\n";
} else { } else {
PIString ptype = m.type.left(m.type.find('[')).trim(); PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0]; PIString size = m.dims[0];
@@ -80,19 +96,19 @@ bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e) {
size += m.dims[i]; size += m.dims[i];
} }
rt.ts << "\t{\n\t\tPIVector<" << ptype << " > d;\n"; rt.ts << "\t{\n\t\tPIVector<" << ptype << " > d;\n";
rt.ts << "\t\tpiDeserializeJSON(d, js[\"" << m.name << "\"]);\n"; rt.ts << "\t\tpiDeserializeJSON(d, js[\"" << var_prefix << m.name << "\"]);\n";
rt.ts << "\t\tint cnt = piMini(d.size_s(), " << size << ");\n"; rt.ts << "\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
rt.ts << "\t\tfor (int i = 0; i < cnt; ++i)\n"; rt.ts << "\t\tfor (int i = 0; i < cnt; ++i)\n";
rt.ts << "\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n"; rt.ts << "\t\t\t((" << ptype << " *)(v." << var_prefix << m.name << "))[i] = d[i];\n";
rt.ts << "\t}\n"; rt.ts << "\t}\n";
} }
if (is_union) break; if (is_union) break;
} }
if (is_union) return true; if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) { /*for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue; if (!ce->is_anonymous) continue;
if (!writeClassJSONMembersIn(rt, ce)) return false; if (!writeClassJSONMembersIn(rt, ce)) return false;
} }*/
return true; return true;
} }

View File

@@ -22,8 +22,8 @@
#include "common.h" #include "common.h"
bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e); bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e); bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
bool needClassJSON(const PICodeParser::Entity * e); bool needClassJSON(const PICodeParser::Entity * e);
bool makeClassJSON(Runtime & rt, const PICodeParser::Entity * e); bool makeClassJSON(Runtime & rt, const PICodeParser::Entity * e);

View File

@@ -66,11 +66,15 @@ bool writeModel(PICodeParser & parser,
if (meta || enums || getters) { if (meta || enums || getters) {
if (getters) { if (getters) {
ts << "\n\n// Getter funtions\n"; ts << "\n\n// Getter funtions\n";
ts << "\n#define PICODEINFO_OFFSET(type, member) reinterpret_cast<size_t>(&reinterpret_cast<const char &>((((type "
"*)nullptr)->member)))\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
makeGetterType(rt, e); makeGetterType(rt, e);
makeGetterValue(rt, e); makeGetterValue(rt, e);
makeGetterOffset(rt, e);
} }
ts << "\n#undef PICODEINFO_OFFSET\n";
} }
ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
ts << "\tstatic __ClassInfo_" << defname << "_Initializer__::Content content;\n"; ts << "\tstatic __ClassInfo_" << defname << "_Initializer__::Content content;\n";
@@ -83,6 +87,7 @@ bool writeModel(PICodeParser & parser,
if (getters) { if (getters) {
ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n";
ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n";
ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n";
} }
if (meta) { if (meta) {
@@ -95,7 +100,7 @@ bool writeModel(PICodeParser & parser,
if (meta) { if (meta) {
ts << "\n\n// Classes\n"; ts << "\n\n// Classes\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (e->name.startsWith("_PI")) continue; if (e->name.startsWith("_PI") || e->is_anonymous) continue;
makeClassInfo(rt, e); makeClassInfo(rt, e);
} }
} }
@@ -108,9 +113,11 @@ bool writeModel(PICodeParser & parser,
ts << "\n// Getters\n"; ts << "\n// Getters\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!needClassStream(e)) continue; if (!needClassStream(e)) continue;
if (!e->has_name || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
ts << "\tci_avf[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n"; auto cname = toCName(e->name);
ts << "\tci_atf[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n"; ts << "\tci_avf[\"" << e->name << "\"] = getterValue" << cname << ";\n";
ts << "\tci_atf[\"" << e->name << "\"] = getterType" << cname << ";\n";
ts << "\tci_aof[\"" << e->name << "\"] = getterOffset" << cname << ";\n";
} }
} }
ts << "}\n\n"; ts << "}\n\n";
@@ -121,11 +128,12 @@ bool writeModel(PICodeParser & parser,
if (getters) { if (getters) {
ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n";
ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n";
ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n";
} }
if (meta) { if (meta) {
ts << "\n// Classes clean\n"; ts << "\n// Classes clean\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (e->name.startsWith("_PI")) continue; if (e->name.startsWith("_PI") || e->is_anonymous) continue;
ts << "\tpiDeleteSafety(ci_ci[\"" << e->name << "\"]);\n"; ts << "\tpiDeleteSafety(ci_ci[\"" << e->name << "\"]);\n";
ts << "\tci_ins->classesInfo->remove(\"" << e->name << "\");\n"; ts << "\tci_ins->classesInfo->remove(\"" << e->name << "\");\n";
} }
@@ -143,9 +151,10 @@ bool writeModel(PICodeParser & parser,
ts << "\n// Getters clean\n"; ts << "\n// Getters clean\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!needClassStream(e)) continue; if (!needClassStream(e)) continue;
if (!e->has_name || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
ts << "\tci_avf.remove(\"" << e->name << "\");\n"; ts << "\tci_avf.remove(\"" << e->name << "\");\n";
ts << "\tci_atf.remove(\"" << e->name << "\");\n"; ts << "\tci_atf.remove(\"" << e->name << "\");\n";
ts << "\tci_aof.remove(\"" << e->name << "\");\n";
} }
} }
ts << "}\n"; ts << "}\n";
@@ -173,7 +182,7 @@ bool writeModel(PICodeParser & parser,
if (streams) { if (streams) {
ts << "\n\n// Stream operators\n"; ts << "\n\n// Stream operators\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI") || if (e->is_anonymous || e->name.startsWith("_PI") ||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public)) !(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public))
continue; continue;
if (!makeClassStream(rt, e)) return false; if (!makeClassStream(rt, e)) return false;
@@ -182,7 +191,7 @@ bool writeModel(PICodeParser & parser,
if (json) { if (json) {
ts << "\n\n// JSON serialization\n"; ts << "\n\n// JSON serialization\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI") || if (e->is_anonymous || e->name.startsWith("_PI") ||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public)) !(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public))
continue; continue;
if (!makeClassJSON(rt, e)) return false; if (!makeClassJSON(rt, e)) return false;

View File

@@ -20,27 +20,17 @@
#include "metainfo.h" #include "metainfo.h"
void makeClassInfo(Runtime & rt, const PICodeParser::Entity * e) { void writeClassInfoMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix) {
rt.ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n"; if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
rt.ts << "\tci->type = \"" << e->type << "\";\n";
rt.ts << "\tci->name = \"" << e->name << "\";\n";
rt.ts << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
rt.ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
rt.ts << "\tci_ci[ci->name] = ci;\n";
if (e->parent_scope) {
rt.ts << "\tpci = "
<< "ci_ci.value(\"" << e->parent_scope->name << "\", 0);\n";
rt.ts << "\tif (pci) pci->children_info << ci;\n";
}
for (const PICodeParser::Entity * p: e->parents)
rt.ts << "\tci->parents << \"" << p->name << "\";\n";
if (!e->members.isEmpty()) rt.ts << "\n\tTypeInfo ti;\n";
for (const PICodeParser::Member & m: e->members) { for (const PICodeParser::Member & m: e->members) {
rt.ts << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\""; auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
writeClassInfoMembers(rt, type, var_prefix + m.name);
continue;
}
}
rt.ts << "\tti = TypeInfo(\"" << var_prefix << m.name << "\", \"" << m.type << "\"";
if (m.attributes != 0) { if (m.attributes != 0) {
bool fir = true; bool fir = true;
rt.ts << ", "; rt.ts << ", ";
@@ -97,6 +87,29 @@ void makeClassInfo(Runtime & rt, const PICodeParser::Entity * e) {
} }
rt.ts << "\tci->variables << ti;\n"; rt.ts << "\tci->variables << ti;\n";
} }
}
void makeClassInfo(Runtime & rt, const PICodeParser::Entity * e) {
rt.ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n";
rt.ts << "\tci->type = \"" << e->type << "\";\n";
rt.ts << "\tci->name = \"" << e->name << "\";\n";
// rt.ts << "\tci->is_anonymous = " << (e->is_anonymous ? "true" : "false") << ";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
rt.ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
rt.ts << "\tci_ci[ci->name] = ci;\n";
if (e->parent_scope) {
rt.ts << "\tpci = "
<< "ci_ci.value(\"" << e->parent_scope->name << "\", 0);\n";
rt.ts << "\tif (pci) pci->children_info << ci;\n";
}
for (const PICodeParser::Entity * p: e->parents)
rt.ts << "\tci->parents << \"" << p->name << "\";\n";
if (!e->members.isEmpty()) rt.ts << "\n\tTypeInfo ti;\n";
writeClassInfoMembers(rt, e);
PIString arg; PIString arg;
bool has_fi = false; bool has_fi = false;
for (const PICodeParser::Member & m: e->functions) { for (const PICodeParser::Member & m: e->functions) {

View File

@@ -22,6 +22,7 @@
#include "common.h" #include "common.h"
void writeClassInfoMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
void makeClassInfo(Runtime & rt, const PICodeParser::Entity * e); void makeClassInfo(Runtime & rt, const PICodeParser::Entity * e);
#endif #endif

View File

@@ -22,7 +22,8 @@
#include "pitranslator.h" #include "pitranslator.h"
bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple) { bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PIVector<PICodeParser::Member> ml; PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) { for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue; if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
@@ -31,9 +32,16 @@ bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, in
bool is_union = e->type == "union"; bool is_union = e->type == "union";
PISet<int> used_id; PISet<int> used_id;
for (const PICodeParser::Member & m: ml) { for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue; if (m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue; if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue; if (m.meta.value("id") == "-") continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
if (!writeClassStreamMembersOut(rt, type, cnt, simple, var_prefix + m.name)) return false;
continue;
}
}
++cnt; ++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt(); if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) { if (used_id[cnt]) {
@@ -44,11 +52,11 @@ bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, in
if (simple) { if (simple) {
rt.ts << "\ts << "; rt.ts << "\ts << ";
if (rt.parser.isEnum(m.type)) rt.ts << "(int)"; if (rt.parser.isEnum(m.type)) rt.ts << "(int)";
rt.ts << "v." << m.name << ";\n"; rt.ts << "v." << var_prefix << m.name << ";\n";
} else { } else {
rt.ts << "\tcs.add(" << cnt << ", "; rt.ts << "\tcs.add(" << cnt << ", ";
if (rt.parser.isEnum(m.type)) rt.ts << "(int)"; if (rt.parser.isEnum(m.type)) rt.ts << "(int)";
rt.ts << "v." << m.name << ");\n"; rt.ts << "v." << var_prefix << m.name << ");\n";
} }
} else { } else {
PIString ptype = m.type.left(m.type.find('[')).trim(); PIString ptype = m.type.left(m.type.find('[')).trim();
@@ -59,24 +67,22 @@ bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, in
} }
if (simple) { if (simple) {
rt.ts << "\tfor (int i = 0; i < " << size << "; ++i)\n"; rt.ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
rt.ts << "\t\ts << ((const " << ptype << " *)(v." << m.name << "))[i];\n"; rt.ts << "\t\ts << ((const " << ptype << " *)(" << "v." << var_prefix << m.name << "))[i];\n";
} else { } else {
rt.ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name << "), "; rt.ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(" << "v." << var_prefix
<< m.name << "), ";
rt.ts << size << "));\n"; rt.ts << size << "));\n";
} }
} }
if (is_union) break; if (is_union) break;
} }
if (is_union) return true; if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersOut(rt, ce, cnt, simple)) return false;
}
return true; return true;
} }
bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple) { bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple, PIString var_prefix) {
if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += ".";
PIVector<PICodeParser::Member> ml; PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) { for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue; if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
@@ -85,9 +91,16 @@ bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int
bool is_union = e->type == "union"; bool is_union = e->type == "union";
PISet<int> used_id; PISet<int> used_id;
for (const PICodeParser::Member & m: ml) { for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue; if (m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue; if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue; if (m.meta.value("id") == "-") continue;
auto type = findEntity(rt, m.type);
if (type) {
if (type->is_anonymous) {
if (!writeClassStreamMembersIn(rt, type, cnt, simple, var_prefix + m.name)) return false;
continue;
}
}
++cnt; ++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt(); if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) { if (used_id[cnt]) {
@@ -104,8 +117,8 @@ bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int
if (is_enum) if (is_enum)
rt.ts << "i;"; rt.ts << "i;";
else else
rt.ts << "v." << m.name << ";"; rt.ts << "v." << var_prefix << m.name << ";";
if (is_enum) rt.ts << " v." << m.name << " = (" << m.type << ")i;}"; if (is_enum) rt.ts << " v. << var_prefix" << m.name << " = (" << m.type << ")i;}";
rt.ts << "\n"; rt.ts << "\n";
} else { } else {
rt.ts << "\t\tcase " << cnt << ":"; rt.ts << "\t\tcase " << cnt << ":";
@@ -114,9 +127,9 @@ bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int
if (is_enum) if (is_enum)
rt.ts << "i"; rt.ts << "i";
else else
rt.ts << "v." << m.name; rt.ts << "v." << var_prefix << m.name;
rt.ts << ");"; rt.ts << ");";
if (is_enum) rt.ts << " v." << m.name << " = (" << m.type << ")i;}"; if (is_enum) rt.ts << " v." << var_prefix << m.name << " = (" << m.type << ")i;}";
rt.ts << " break;\n"; rt.ts << " break;\n";
} }
} else { } else {
@@ -128,12 +141,12 @@ bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int
} }
if (simple) { if (simple) {
rt.ts << "\tfor (int i = 0; i < " << size << "; ++i)\n"; rt.ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
rt.ts << "\t\ts >> ((" << ptype << " *)(v." << m.name << "))[i];\n"; rt.ts << "\t\ts >> ((" << ptype << " *)(" << "v." << var_prefix << m.name << "))[i];\n";
} else { } else {
rt.ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n"; rt.ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n";
rt.ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n"; rt.ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
rt.ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n"; rt.ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n";
rt.ts << "\t\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n"; rt.ts << "\t\t\t\t((" << ptype << " *)(" << "v." << var_prefix << m.name << "))[i] = d[i];\n";
rt.ts << "\t\t\t}\n"; rt.ts << "\t\t\t}\n";
rt.ts << "\t\t\tbreak;\n"; rt.ts << "\t\t\tbreak;\n";
} }
@@ -141,10 +154,6 @@ bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int
if (is_union) break; if (is_union) break;
} }
if (is_union) return true; if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersIn(rt, ce, cnt, simple)) return false;
}
return true; return true;
} }

View File

@@ -22,8 +22,8 @@
#include "common.h" #include "common.h"
bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple); bool writeClassStreamMembersOut(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple, PIString var_prefix = {});
bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple); bool writeClassStreamMembersIn(Runtime & rt, const PICodeParser::Entity * e, int & cnt, bool simple, PIString var_prefix = {});
bool needClassStream(const PICodeParser::Entity * e); bool needClassStream(const PICodeParser::Entity * e);
bool makeClassStream(Runtime & rt, const PICodeParser::Entity * e); bool makeClassStream(Runtime & rt, const PICodeParser::Entity * e);