Skip to content

Commit e9b69b4

Browse files
committed
Reduce number of externs
1 parent 507e4a8 commit e9b69b4

3 files changed

Lines changed: 78 additions & 31 deletions

File tree

src/ifcopenshell-python/ifcopenshell/express/implementation.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ def __init__(self, mapping):
4141

4242
write = lambda str, **kwargs: enumeration_functions.append(str % kwargs)
4343

44+
collections_by_type = (
45+
("entity", mapping.schema.entities),
46+
("type_declaration", mapping.schema.simpletypes),
47+
("select_type", mapping.schema.selects),
48+
("enumeration_type", mapping.schema.enumerations),
49+
)
50+
self.names = []
51+
for _, collection in collections_by_type:
52+
self.names.extend(collection.keys())
53+
self.names.sort(key=str.lower)
54+
4455
for name, enum in mapping.schema.enumerations.items():
4556
short_name = name[:-4] if name.endswith("Enum") else name
4657
context = locals()
@@ -50,6 +61,7 @@ def __init__(self, mapping):
5061
name=name,
5162
schema_name=schema_name,
5263
schema_name_upper=schema_name_upper,
64+
index_in_schema=self.names.index(str(name)),
5365
values=catc(map(stringify, enum.values)),
5466
from_string_statements=catnl(
5567
templates.enum_from_string_stmt % dict(context, **locals()) for value in enum.values
@@ -61,7 +73,8 @@ def __init__(self, mapping):
6173
templates.select_function,
6274
name=name,
6375
schema_name=schema_name,
64-
schema_name_upper=schema_name_upper
76+
schema_name_upper=schema_name_upper,
77+
index_in_schema=self.names.index(str(name)),
6578
)
6679

6780
write = lambda str, **kwargs: entity_implementations.append(str % kwargs)
@@ -208,6 +221,7 @@ def get_attribute_index(entity, attr_name):
208221
"body": templates.get_inverse
209222
% {
210223
"type": i.entity,
224+
"type_index": self.names.index(i.entity),
211225
"index": get_attribute_index(i.entity, i.attribute),
212226
"schema_name": schema_name,
213227
"schema_name_upper": schema_name_upper,
@@ -233,6 +247,7 @@ def get_attribute_index(entity, attr_name):
233247
superclass=superclass,
234248
schema_name=schema_name,
235249
schema_name_upper=schema_name_upper,
250+
index_in_schema=self.names.index(str(name)),
236251
)
237252

238253
selectable_simple_types = sorted(
@@ -306,6 +321,7 @@ def get_parent_id(s):
306321

307322
def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper):
308323
class_name, attr_type, superclass, superclass_init, name, tmpl, return_type, args, body = params
324+
index_in_schema = self.names.index(str(class_name))
309325
underlying_type = mapping.list_instance_type(type)
310326
arguments = ",".join(args)
311327
body = body % locals()
@@ -347,6 +363,7 @@ def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper
347363
)
348364
simple_type_impl.append("")
349365

366+
"""
350367
external_definitions = (
351368
[("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys()]
352369
+ [
@@ -362,6 +379,8 @@ def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper
362379
for n in mapping.schema.selects.keys()
363380
]
364381
)
382+
"""
383+
external_definitions = ["extern declaration* %s_types[%d];" % (schema_name_upper, len(self.names))]
365384

366385
self.str = templates.implementation % {
367386
"schema_name_upper": schema_name_upper,

src/ifcopenshell-python/ifcopenshell/express/schema_class.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919

2020
import operator
21+
import re
2122

2223
import nodes
2324
import codegen
@@ -146,11 +147,14 @@ def named_type(self, type):
146147

147148
def declare(self, definition_type, name):
148149
schema_name = self.schema_name
149-
self.statements.append("%(definition_type)s* %(schema_name)s_%(name)s_type = 0;" % locals())
150+
# self.statements.append("%(definition_type)s* %(schema_name)s_%(name)s_type = 0;" % locals())
150151
self.names.append(name)
151152

152153
def begin_schema(self):
153154
self.names.sort(key=str.lower)
155+
schema_name = self.schema_name
156+
num_names = len(self.names)
157+
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
154158

155159
self.statements.append("{factory_placeholder}")
156160

@@ -172,7 +176,7 @@ def typedef(self, name, declared_type):
172176
schema_name = self.schema_name
173177
index_in_schema = self.names.index(name)
174178
self.statements.append(
175-
' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
179+
' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
176180
% locals()
177181
)
178182

@@ -183,18 +187,18 @@ def enumeration(self, name, enum):
183187
self.statements.append(" std::vector<std::string> items; items.reserve(%d);" % len(enum.values))
184188
self.statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
185189
self.statements.append(
186-
' %(schema_name)s_%(name)s_type = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
190+
' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
187191
% locals()
188192
)
189193
self.statements.append(" }")
190194

191195
def entity(self, name, type):
192196
schema_name = self.schema_name
193197
index_in_schema = self.names.index(name)
194-
supertype = "0" if len(type.supertypes) == 0 else "%s_%s_type" % (self.schema_name, type.supertypes[0])
198+
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0]))
195199
is_abstract = "true" if type.abstract else "false"
196200
self.statements.append(
197-
' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, %(supertype)s);'
201+
' %(schema_name)s_types[%(index_in_schema)d] = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);'
198202
% locals()
199203
)
200204

@@ -204,15 +208,16 @@ def select(self, name, type):
204208
self.statements.append(" {")
205209
self.statements.append(" std::vector<const declaration*> items; items.reserve(%d);" % len(type.values))
206210
self.statements.extend(
207-
map(lambda v: " items.push_back(%s_%s_type);" % (self.schema_name, v), sorted(map(str, type.values)))
211+
map(lambda v: " items.push_back(%s_types[%d]);" % (self.schema_name, self.names.index(v)), sorted(map(str, type.values)))
208212
)
209213
self.statements.append(
210-
' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);'
214+
' %(schema_name)s_types[%(index_in_schema)d] = new select_type("%(name)s", %(index_in_schema)d, items);'
211215
% locals()
212216
)
213217
self.statements.append(" }")
214218

215219
def entity_attributes(self, name, attribute_definitions, is_derived):
220+
index_in_schema = self.names.index(name)
216221
schema_name = self.schema_name
217222
self.statements.append(" {")
218223
self.statements.append(
@@ -228,31 +233,37 @@ def entity_attributes(self, name, attribute_definitions, is_derived):
228233
self.statements.append(
229234
" " + " ".join(map(lambda b: "derived.push_back(%s);" % str(b).lower(), is_derived))
230235
)
231-
self.statements.append(" %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);" % locals())
236+
self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes(attributes, derived);" % locals())
232237
self.statements.append(" }")
233238

234239
def inverse_attributes(self, name, inv_attrs):
235240
schema_name = self.schema_name
241+
index_in_schema = self.names.index(name)
236242
self.statements.append(" {")
237243
self.statements.append(
238244
" std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);" % len(inv_attrs)
239245
)
240246
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
247+
opposite_index_in_schema = self.names.index(entity_ref)
248+
opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
249+
opposite_index_in_schema = self.names.index(attribute_entity)
250+
opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
241251
self.statements.append(
242-
' 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]));'
252+
' 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]));'
243253
% locals()
244254
)
245-
self.statements.append(" %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);" % locals())
255+
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes(attributes);" % locals())
246256
self.statements.append(" }")
247257

248258
def entity_subtypes(self, name, tys):
249259
schema_name = self.schema_name
260+
index_in_schema = self.names.index(name)
250261
self.statements.append(" {")
251262
self.statements.append(" std::vector<const entity*> defs; defs.reserve(%d);" % len(tys))
252263
self.statements.append(
253-
(" " + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals()
264+
(" " + "".join(map(lambda t: ("defs.push_back(((entity*) %%(schema_name)s_types[%d]));" % self.names.index(t)), tys))) % locals()
254265
)
255-
self.statements.append(" %(schema_name)s_%(name)s_type->set_subtypes(defs);" % locals())
266+
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes(defs);" % locals())
256267
self.statements.append(" }")
257268

258269
def finalize(self, can_be_instantiated_set):
@@ -266,7 +277,8 @@ def finalize(self, can_be_instantiated_set):
266277
" std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);" % locals()
267278
)
268279
for type_name in self.names:
269-
self.statements.append(" declarations.push_back(%(schema_name)s_%(type_name)s_type);" % locals())
280+
index_in_schema = self.names.index(type_name)
281+
self.statements.append(" declarations.push_back(%(schema_name)s_types[%(index_in_schema)d]);" % locals())
270282

271283
self.statements.append(
272284
' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());'
@@ -352,6 +364,23 @@ class UnmetDependenciesException(Exception):
352364

353365
x = code(schema_name)
354366

367+
def transform_to_indexed(fn):
368+
def wrapper(*args, **kwargs):
369+
declared_type = fn(*args, **kwargs)
370+
if 'simple_type' in declared_type:
371+
pass
372+
else:
373+
match = re.search(r'\((\w+?_[\w+]+?_\w+?)\)', declared_type)
374+
if match:
375+
old_decl = match.group(1)
376+
tn = old_decl.rsplit('_', 2)[1]
377+
idx = x.names.index(tn)
378+
snu = schema_name.upper()
379+
declared_type = declared_type.replace(old_decl, '%(snu)s_types[%(idx)d]' % locals())
380+
return declared_type
381+
return wrapper if code == EarlyBoundCodeWriter else fn
382+
383+
@transform_to_indexed
355384
def get_declared_type(type, emitted_names=None):
356385
if isinstance(type, nodes.SimpleType):
357386
type = type.type
@@ -469,9 +498,8 @@ def write(name):
469498
if write(name):
470499
emitted.add(name.lower())
471500
declarations_by_index.append(name)
472-
declared_types.append("%(schema_name)s_%(name)s_type" % locals())
473501

474-
num_declarations = len(declared_types)
502+
num_declarations = len(emitted)
475503

476504
for name, type in mapping.schema.entities.items():
477505
derived = set(mapping.derived_in_supertype(type))

src/ifcopenshell-python/ifcopenshell/express/templates.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,19 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
124124
simpletype_impl_argument = "return data_->getArgument(i);"
125125
simpletype_impl_is_with_supertype = "return v == %(class_name)s_type || %(superclass)s::is(v);"
126126
simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;"
127-
simpletype_impl_type = "return *%(schema_name_upper)s_%(class_name)s_type;"
128-
simpletype_impl_class = "return *%(schema_name_upper)s_%(class_name)s_type;"
127+
simpletype_impl_type = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
128+
simpletype_impl_class = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
129129
simpletype_impl_explicit_constructor = "data_ = e;"
130130
simpletype_impl_constructor = (
131-
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v"
131+
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v"
132132
+ "); data_->setArgument(0, attr);}"
133133
)
134-
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);}"
134+
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);}"
135135
simpletype_impl_cast = "return *data_->getArgument(0);"
136136
simpletype_impl_cast_templated = (
137137
"aggregate_of_instance::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
138138
)
139-
simpletype_impl_declaration = "return *%(schema_name_upper)s_%(class_name)s_type;"
139+
simpletype_impl_declaration = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
140140

141141
select = """%(documentation)s
142142
class IFC_PARSE_API %(name)s : public virtual IfcUtil::IfcBaseInterface {
@@ -174,26 +174,26 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
174174
"""
175175

176176
select_function = """
177-
const IfcParse::select_type& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
177+
const IfcParse::select_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::select_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
178178
"""
179179

180180
enumeration_function = """
181-
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *%(schema_name_upper)s_%(name)s_type; }
182-
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
181+
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
182+
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
183183
184184
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData* e) {
185185
data_ = e;
186186
}
187187
188188
%(schema_name)s::%(name)s::%(name)s(Value v) {
189-
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(name)s_type);
189+
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
190190
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
191191
attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,ToString(v)));
192192
data_->setArgument(0,attr);
193193
}
194194
195195
%(schema_name)s::%(name)s::%(name)s(const std::string& v) {
196-
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(name)s_type);
196+
data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
197197
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
198198
attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(FromString(v),ToString(FromString(v))));
199199
data_->setArgument(0,attr);
@@ -218,10 +218,10 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
218218
entity_implementation = """// Function implementations for %(name)s
219219
%(attributes)s
220220
%(inverse)s
221-
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *%(schema_name_upper)s_%(name)s_type; }
222-
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *%(schema_name_upper)s_%(name)s_type; }
223-
%(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; }
224-
%(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 }
221+
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
222+
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
223+
%(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; }
224+
%(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 }
225225
"""
226226

227227
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
@@ -257,7 +257,7 @@ class IFC_PARSE_API %(name)s : %(superclass)s {
257257
get_attr_stmt_array = "%(null_check)s aggregate_of_instance::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
258258
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 >();"
259259

260-
get_inverse = "return data_->getInverse(%(schema_name_upper)s_%(type)s_type, %(index)d)->as<%(type)s>();"
260+
get_inverse = "return data_->getInverse(%(schema_name_upper)s_types[%(type_index)d], %(index)d)->as<%(type)s>();"
261261

262262
set_attr_stmt = (
263263
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();%(check_optional_set_begin)sattr->set(%(star_if_optional)sv"

0 commit comments

Comments
 (0)