Reduce number of externs

This commit is contained in:
Thomas Krijnen
2024-05-12 11:39:03 +02:00
parent 507e4a8211
commit e9b69b4b26
3 changed files with 78 additions and 31 deletions
@@ -41,6 +41,17 @@ class Implementation(codegen.Base):
write = lambda str, **kwargs: enumeration_functions.append(str % kwargs)
collections_by_type = (
("entity", mapping.schema.entities),
("type_declaration", mapping.schema.simpletypes),
("select_type", mapping.schema.selects),
("enumeration_type", mapping.schema.enumerations),
)
self.names = []
for _, collection in collections_by_type:
self.names.extend(collection.keys())
self.names.sort(key=str.lower)
for name, enum in mapping.schema.enumerations.items():
short_name = name[:-4] if name.endswith("Enum") else name
context = locals()
@@ -50,6 +61,7 @@ class Implementation(codegen.Base):
name=name,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
index_in_schema=self.names.index(str(name)),
values=catc(map(stringify, enum.values)),
from_string_statements=catnl(
templates.enum_from_string_stmt % dict(context, **locals()) for value in enum.values
@@ -61,7 +73,8 @@ class Implementation(codegen.Base):
templates.select_function,
name=name,
schema_name=schema_name,
schema_name_upper=schema_name_upper
schema_name_upper=schema_name_upper,
index_in_schema=self.names.index(str(name)),
)
write = lambda str, **kwargs: entity_implementations.append(str % kwargs)
@@ -208,6 +221,7 @@ class Implementation(codegen.Base):
"body": templates.get_inverse
% {
"type": i.entity,
"type_index": self.names.index(i.entity),
"index": get_attribute_index(i.entity, i.attribute),
"schema_name": schema_name,
"schema_name_upper": schema_name_upper,
@@ -233,6 +247,7 @@ class Implementation(codegen.Base):
superclass=superclass,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
index_in_schema=self.names.index(str(name)),
)
selectable_simple_types = sorted(
@@ -306,6 +321,7 @@ class Implementation(codegen.Base):
def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper):
class_name, attr_type, superclass, superclass_init, name, tmpl, return_type, args, body = params
index_in_schema = self.names.index(str(class_name))
underlying_type = mapping.list_instance_type(type)
arguments = ",".join(args)
body = body % locals()
@@ -347,6 +363,7 @@ class Implementation(codegen.Base):
)
simple_type_impl.append("")
"""
external_definitions = (
[("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys()]
+ [
@@ -362,6 +379,8 @@ class Implementation(codegen.Base):
for n in mapping.schema.selects.keys()
]
)
"""
external_definitions = ["extern declaration* %s_types[%d];" % (schema_name_upper, len(self.names))]
self.str = templates.implementation % {
"schema_name_upper": schema_name_upper,
@@ -18,6 +18,7 @@
import operator
import re
import nodes
import codegen
@@ -146,11 +147,14 @@ class EarlyBoundCodeWriter:
def declare(self, definition_type, name):
schema_name = self.schema_name
self.statements.append("%(definition_type)s* %(schema_name)s_%(name)s_type = 0;" % locals())
# self.statements.append("%(definition_type)s* %(schema_name)s_%(name)s_type = 0;" % locals())
self.names.append(name)
def begin_schema(self):
self.names.sort(key=str.lower)
schema_name = self.schema_name
num_names = len(self.names)
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
self.statements.append("{factory_placeholder}")
@@ -172,7 +176,7 @@ __attribute__((optnone))
schema_name = self.schema_name
index_in_schema = self.names.index(name)
self.statements.append(
' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
% locals()
)
@@ -183,7 +187,7 @@ __attribute__((optnone))
self.statements.append(" std::vector<std::string> items; items.reserve(%d);" % len(enum.values))
self.statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
self.statements.append(
' %(schema_name)s_%(name)s_type = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
% locals()
)
self.statements.append(" }")
@@ -191,10 +195,10 @@ __attribute__((optnone))
def entity(self, name, type):
schema_name = self.schema_name
index_in_schema = self.names.index(name)
supertype = "0" if len(type.supertypes) == 0 else "%s_%s_type" % (self.schema_name, type.supertypes[0])
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0]))
is_abstract = "true" if type.abstract else "false"
self.statements.append(
' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, %(supertype)s);'
' %(schema_name)s_types[%(index_in_schema)d] = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);'
% locals()
)
@@ -204,15 +208,16 @@ __attribute__((optnone))
self.statements.append(" {")
self.statements.append(" std::vector<const declaration*> items; items.reserve(%d);" % len(type.values))
self.statements.extend(
map(lambda v: " items.push_back(%s_%s_type);" % (self.schema_name, v), sorted(map(str, type.values)))
map(lambda v: " items.push_back(%s_types[%d]);" % (self.schema_name, self.names.index(v)), sorted(map(str, type.values)))
)
self.statements.append(
' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);'
' %(schema_name)s_types[%(index_in_schema)d] = new select_type("%(name)s", %(index_in_schema)d, items);'
% locals()
)
self.statements.append(" }")
def entity_attributes(self, name, attribute_definitions, is_derived):
index_in_schema = self.names.index(name)
schema_name = self.schema_name
self.statements.append(" {")
self.statements.append(
@@ -228,31 +233,37 @@ __attribute__((optnone))
self.statements.append(
" " + " ".join(map(lambda b: "derived.push_back(%s);" % str(b).lower(), is_derived))
)
self.statements.append(" %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);" % locals())
self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes(attributes, derived);" % locals())
self.statements.append(" }")
def inverse_attributes(self, name, inv_attrs):
schema_name = self.schema_name
index_in_schema = self.names.index(name)
self.statements.append(" {")
self.statements.append(
" std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);" % len(inv_attrs)
)
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
opposite_index_in_schema = self.names.index(entity_ref)
opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
opposite_index_in_schema = self.names.index(attribute_entity)
opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
self.statements.append(
' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));'
' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d]));'
% locals()
)
self.statements.append(" %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);" % locals())
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes(attributes);" % locals())
self.statements.append(" }")
def entity_subtypes(self, name, tys):
schema_name = self.schema_name
index_in_schema = self.names.index(name)
self.statements.append(" {")
self.statements.append(" std::vector<const entity*> defs; defs.reserve(%d);" % len(tys))
self.statements.append(
(" " + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals()
(" " + "".join(map(lambda t: ("defs.push_back(((entity*) %%(schema_name)s_types[%d]));" % self.names.index(t)), tys))) % locals()
)
self.statements.append(" %(schema_name)s_%(name)s_type->set_subtypes(defs);" % locals())
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes(defs);" % locals())
self.statements.append(" }")
def finalize(self, can_be_instantiated_set):
@@ -266,7 +277,8 @@ __attribute__((optnone))
" std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);" % locals()
)
for type_name in self.names:
self.statements.append(" declarations.push_back(%(schema_name)s_%(type_name)s_type);" % locals())
index_in_schema = self.names.index(type_name)
self.statements.append(" declarations.push_back(%(schema_name)s_types[%(index_in_schema)d]);" % locals())
self.statements.append(
' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());'
@@ -352,6 +364,23 @@ class SchemaClass(codegen.Base):
x = code(schema_name)
def transform_to_indexed(fn):
def wrapper(*args, **kwargs):
declared_type = fn(*args, **kwargs)
if 'simple_type' in declared_type:
pass
else:
match = re.search(r'\((\w+?_[\w+]+?_\w+?)\)', declared_type)
if match:
old_decl = match.group(1)
tn = old_decl.rsplit('_', 2)[1]
idx = x.names.index(tn)
snu = schema_name.upper()
declared_type = declared_type.replace(old_decl, '%(snu)s_types[%(idx)d]' % locals())
return declared_type
return wrapper if code == EarlyBoundCodeWriter else fn
@transform_to_indexed
def get_declared_type(type, emitted_names=None):
if isinstance(type, nodes.SimpleType):
type = type.type
@@ -469,9 +498,8 @@ class SchemaClass(codegen.Base):
if write(name):
emitted.add(name.lower())
declarations_by_index.append(name)
declared_types.append("%(schema_name)s_%(name)s_type" % locals())
num_declarations = len(declared_types)
num_declarations = len(emitted)
for name, type in mapping.schema.entities.items():
derived = set(mapping.derived_in_supertype(type))
@@ -124,19 +124,19 @@ simpletype_impl_argument_type = 'if (i == 0) { return %(attr_type)s; } else { th
simpletype_impl_argument = "return data_->getArgument(i);"
simpletype_impl_is_with_supertype = "return v == %(class_name)s_type || %(superclass)s::is(v);"
simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;"
simpletype_impl_type = "return *%(schema_name_upper)s_%(class_name)s_type;"
simpletype_impl_class = "return *%(schema_name_upper)s_%(class_name)s_type;"
simpletype_impl_type = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
simpletype_impl_class = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
simpletype_impl_explicit_constructor = "data_ = e;"
simpletype_impl_constructor = (
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v"
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v"
+ "); data_->setArgument(0, attr);}"
)
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
simpletype_impl_cast = "return *data_->getArgument(0);"
simpletype_impl_cast_templated = (
"aggregate_of_instance::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
)
simpletype_impl_declaration = "return *%(schema_name_upper)s_%(class_name)s_type;"
simpletype_impl_declaration = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
select = """%(documentation)s
class IFC_PARSE_API %(name)s : public virtual IfcUtil::IfcBaseInterface {
@@ -174,26 +174,26 @@ public:
"""
select_function = """
const IfcParse::select_type& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
const IfcParse::select_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::select_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
"""
enumeration_function = """
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *%(schema_name_upper)s_%(name)s_type; }
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) {
data_ = e;
}
%(schema_name)s::%(name)s::%(name)s(Value v) {
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(name)s_type);
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,ToString(v)));
data_->setArgument(0,attr);
}
%(schema_name)s::%(name)s::%(name)s(const std::string& v) {
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(name)s_type);
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(FromString(v),ToString(FromString(v))));
data_->setArgument(0,attr);
@@ -218,10 +218,10 @@ const char* %(schema_name)s::%(name)s::ToString(Value v) {
entity_implementation = """// Function implementations for %(name)s
%(attributes)s
%(inverse)s
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *%(schema_name_upper)s_%(name)s_type; }
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (e->type() != %(schema_name_upper)s_%(name)s_type) throw IfcException("Unable to find keyword in schema"); data_ = e; }
%(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(name)s_type); %(constructor_implementation)s }
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (e->type() != %(schema_name_upper)s_types[%(index_in_schema)d]) throw IfcException("Unable to find keyword in schema"); data_ = e; }
%(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); %(constructor_implementation)s }
"""
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
@@ -257,7 +257,7 @@ get_attr_stmt_entity = "%(null_check)s return ((IfcUtil::IfcBaseClass*)(*data_->
get_attr_stmt_array = "%(null_check)s aggregate_of_instance::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt_nested_array = "%(null_check)s aggregate_of_aggregate_of_instance::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_inverse = "return data_->getInverse(%(schema_name_upper)s_%(type)s_type, %(index)d)->as<%(type)s>();"
get_inverse = "return data_->getInverse(%(schema_name_upper)s_types[%(type_index)d], %(index)d)->as<%(type)s>();"
set_attr_stmt = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();%(check_optional_set_begin)sattr->set(%(star_if_optional)sv"