String pooling and modern initialization in schema

This commit is contained in:
Thomas Krijnen
2024-05-12 14:37:09 +02:00
parent 69afcce8e5
commit fb72fdca9c
@@ -117,8 +117,26 @@ class LateBoundSchemaInstantiator:
elem.this.disown() elem.this.disown()
class string_pool:
def __init__(self, fn):
self.di = {}
self.fn = fn
def append(self, v):
def _():
if i := self.di.get(v):
return i
else:
i = len(self.di)
self.di[v] = i
return i
return self.fn(_())
def __iter__(self):
return iter(self.di.keys())
class EarlyBoundCodeWriter: class EarlyBoundCodeWriter:
def __init__(self, schema_name): def __init__(self, schema_name):
self.strings = string_pool(lambda i: "strings[%d]" % i)
self.schema_name = schema_name self.schema_name = schema_name
self.schema_name_title = schema_name.capitalize() self.schema_name_title = schema_name.capitalize()
@@ -126,7 +144,9 @@ class EarlyBoundCodeWriter:
"", "",
'#include "../ifcparse/IfcSchema.h"', '#include "../ifcparse/IfcSchema.h"',
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__, '#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
'#include <string>',
"", "",
'using namespace std::string_literals;',
"using namespace IfcParse;", "using namespace IfcParse;",
"", "",
] ]
@@ -156,6 +176,8 @@ class EarlyBoundCodeWriter:
num_names = len(self.names) num_names = len(self.names)
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals()) self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
self.statements.append("{string_pool_placeholder}")
self.statements.append("{factory_placeholder}") self.statements.append("{factory_placeholder}")
self.statements.append( self.statements.append(
@@ -175,117 +197,97 @@ __attribute__((optnone))
def typedef(self, name, declared_type): def typedef(self, name, declared_type):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
ref = self.strings.append(name)
self.statements.append( self.statements.append(
' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);' ' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration(%(ref)s, %(index_in_schema)d, %(declared_type)s);'
% locals() % locals()
) )
def enumeration(self, name, enum): def enumeration(self, name, enum):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
self.statements.append(" {") ref = self.strings.append(name)
self.statements.append(" std::vector<std::string> items; items.reserve(%d);" % len(enum.values)) items = ",".join(self.strings.append(v) for v in sorted(enum.values))
self.statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
self.statements.append( self.statements.append(
' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type("%(name)s", %(index_in_schema)d, items);' ' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type(%(ref)s, %(index_in_schema)d, {%(items)s});'
% locals() % locals()
) )
self.statements.append(" }")
def entity(self, name, type): def entity(self, name, type):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
ref = self.strings.append(name)
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(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" is_abstract = "true" if type.abstract else "false"
self.statements.append( self.statements.append(
' %(schema_name)s_types[%(index_in_schema)d] = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);' ' %(schema_name)s_types[%(index_in_schema)d] = new entity(%(ref)s, %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);'
% locals() % locals()
) )
def select(self, name, type): def select(self, name, type):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
self.statements.append(" {") ref = self.strings.append(name)
self.statements.append(" std::vector<const declaration*> items; items.reserve(%d);" % len(type.values)) items = ",".join(
self.statements.extend( map(lambda v: "%s_types[%d]" % (self.schema_name, self.names.index(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( self.statements.append(
' %(schema_name)s_types[%(index_in_schema)d] = new select_type("%(name)s", %(index_in_schema)d, items);' ' %(schema_name)s_types[%(index_in_schema)d] = new select_type(%(ref)s, %(index_in_schema)d, {%(items)s});'
% locals() % locals()
) )
self.statements.append(" }")
def entity_attributes(self, name, attribute_definitions, is_derived): def entity_attributes(self, name, attribute_definitions, is_derived):
index_in_schema = self.names.index(name)
schema_name = self.schema_name schema_name = self.schema_name
self.statements.append(" {") index_in_schema = self.names.index(name)
self.statements.append( def _():
" std::vector<const attribute*> attributes; attributes.reserve(%d);" % len(attribute_definitions) index_in_schema = self.names.index(name)
) schema_name = self.schema_name
for attr_name, decl_type, optional in attribute_definitions: for attr_name, decl_type, optional in attribute_definitions:
optional_cpp = str(optional).lower() attr_name_ref = self.strings.append(attr_name)
self.statements.append( optional_cpp = str(optional).lower()
' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));' yield 'new attribute(%(attr_name_ref)s, %(decl_type)s, %(optional_cpp)s)' % locals()
% locals() attributes = ",".join(_())
) derived = ",".join(map(lambda b: str(b).lower(), is_derived))
self.statements.append(" std::vector<bool> derived; derived.reserve(%d);" % len(is_derived)) self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes({%(attributes)s}, {%(derived)s});" % locals())
self.statements.append(
" " + " ".join(map(lambda b: "derived.push_back(%s);" % str(b).lower(), is_derived))
)
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): def inverse_attributes(self, name, inv_attrs):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
self.statements.append(" {") def _():
self.statements.append( schema_name = self.schema_name
" std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);" % len(inv_attrs) index_in_schema = self.names.index(name)
) for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs: attr_name_ref = self.strings.append(attr_name)
opposite_index_in_schema = self.names.index(entity_ref) opposite_index_in_schema = self.names.index(entity_ref)
opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals() opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
opposite_index_in_schema = self.names.index(attribute_entity) opposite_index_in_schema = self.names.index(attribute_entity)
opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals() opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
self.statements.append( yield 'new inverse_attribute(%(attr_name_ref)s, inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d])' % locals()
' 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]));' attributes = ",".join(_())
% locals() self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes({%(attributes)s});" % 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): def entity_subtypes(self, name, tys):
schema_name = self.schema_name schema_name = self.schema_name
index_in_schema = self.names.index(name) index_in_schema = self.names.index(name)
self.statements.append(" {") subtypes = ",".join(map(lambda t: ("((entity*) %%(schema_name)s_types[%d])" % self.names.index(t)), tys)) % locals()
self.statements.append(" std::vector<const entity*> defs; defs.reserve(%d);" % len(tys)) self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes({%(subtypes)s});" % locals())
self.statements.append(
(" " + "".join(map(lambda t: ("defs.push_back(((entity*) %%(schema_name)s_types[%d]));" % self.names.index(t)), tys))) % 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): def finalize(self, can_be_instantiated_set):
schema_name = self.schema_name schema_name = self.schema_name
schema_name_title = self.schema_name.capitalize() schema_name_title = self.schema_name.capitalize()
def _():
num_declarations = len(self.names) schema_name = self.schema_name
schema_name_title = self.schema_name.capitalize()
self.statements.append("") for type_name in self.names:
index_in_schema = self.names.index(type_name)
yield "%(schema_name)s_types[%(index_in_schema)d]" % locals()
declarations = ",".join(_())
schema_name_ref = self.strings.append(schema_name)
self.statements.append( self.statements.append(
" std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);" % locals() ' return new schema_definition(%(schema_name_ref)s, {%(declarations)s}, new %(schema_name)s_instance_factory());'
)
for type_name in self.names:
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());'
% locals() % locals()
) )
self.statements.append("}");
self.statements.extend(("}", ""))
self.statements.append( self.statements.append(
""" """
@@ -348,6 +350,14 @@ class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
% locals() % locals()
) )
""
self.statements[self.statements.index("{string_pool_placeholder}")] = (
"""
const std::string strings[] = {%s};
"""
% ",".join(map(lambda s: '"%s"s' % s, self.strings))
)
def __str__(self): def __str__(self):
return "\n".join(self.statements) return "\n".join(self.statements)