black ifcopenshell-python

This commit is contained in:
htlcnn
2020-11-01 20:08:27 +07:00
committed by Dion Moult
parent 2c9d6a47f4
commit 286c77e3b0
27 changed files with 1502 additions and 979 deletions
@@ -10,11 +10,12 @@ exp_parser_fn = os.path.join(d, "express_parser.py")
if not os.path.exists(exp_parser_fn):
with open(exp_parser_fn, "w") as f:
subprocess.call([sys.executable, "bootstrap.py"], cwd=d, stdout=f)
import express_parser
import schema_class
import ifcopenshell.ifcopenshell_wrapper
def parse(fn):
mapping = express_parser.parse(fn)
return schema_class.SchemaClass(mapping, schema_class.LateBoundSchemaInstantiator).code
@@ -25,47 +25,63 @@ import itertools
from pyparsing import *
try: from functools import reduce
except: pass
try:
from functools import reduce
except:
pass
class Expression:
def __init__(self, contents):
self.contents = contents[0]
def __repr__(self):
if self.op is None: return repr(self.contents)
c = [isinstance(c,str) and c or str(c) for c in self.contents]
if "%s" in self.op: return self.op % (" ".join(c))
else: return "(%s)" % (" %s "%self.op).join(c)
if self.op is None:
return repr(self.contents)
c = [isinstance(c, str) and c or str(c) for c in self.contents]
if "%s" in self.op:
return self.op % (" ".join(c))
else:
return "(%s)" % (" %s " % self.op).join(c)
def __iter__(self):
return self.contents.__iter__()
class Union(Expression):
op = "|"
class Concat(Expression):
op = "+"
class Optional(Expression):
op = "Optional(%s)"
class Repeated(Expression):
op = "ZeroOrMore(%s)"
class Term(Expression):
op = None
class Keyword:
def __init__(self, contents):
self.contents = contents[0]
def __repr__(self):
return self.contents
class Terminal:
def __init__(self, contents):
self.contents = contents[0]
s = self.contents
self.is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \
all(c in alphanums+"_" for c in s[1:-1])
self.is_keyword = len(s) >= 4 and s[0 :: len(s) - 1] == '""' and all(c in alphanums + "_" for c in s[1:-1])
def __repr__(self):
ty = "CaselessKeyword" if self.is_keyword else "CaselessLiteral"
return "%s(%s)" % (ty, self.contents)
@@ -78,31 +94,33 @@ RBRACK = Suppress("]")
LBRACE = Suppress("{")
RBRACE = Suppress("}")
EQUALS = Suppress("=")
VBAR = Suppress("|")
VBAR = Suppress("|")
PERIOD = Suppress(".")
HASH = Suppress("#")
HASH = Suppress("#")
identifier = Word(alphanums+"_")
keyword = Word(alphanums+"_").setParseAction(Keyword)
identifier = Word(alphanums + "_")
keyword = Word(alphanums + "_").setParseAction(Keyword)
expression = Forward()
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
terminal = quotedString.setParseAction(Terminal)
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
factor = concat | term
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
rule = identifier + EQUALS + expression + PERIOD
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
terminal = quotedString.setParseAction(Terminal)
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
factor = concat | term
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
rule = identifier + EQUALS + expression + PERIOD
expression << (union | factor)
grammar = OneOrMore(Group(rule))
grammar.ignore(HASH + restOfLine)
express = grammar.parseFile(os.path.join(os.path.dirname(__file__), 'express.bnf'))
express = grammar.parseFile(os.path.join(os.path.dirname(__file__), "express.bnf"))
def find_bytype(expr, ty, li = None):
if li is None: li = []
def find_bytype(expr, ty, li=None):
if li is None:
li = []
if isinstance(expr, Term):
expr = expr.contents
if isinstance(expr, ty):
@@ -113,34 +131,35 @@ def find_bytype(expr, ty, li = None):
find_bytype(term, ty, li)
return set(li)
actions = {
'type_decl' : "TypeDeclaration",
'entity_decl' : "EntityDeclaration",
'enumeration_type' : "EnumerationType",
'aggregation_types' : "AggregationType",
'general_aggregation_types' : "AggregationType",
'select_type' : "SelectType",
'binary_type' : "BinaryType",
'subtype_declaration' : "SubTypeExpression",
'supertype_constraint' : "SuperTypeExpression",
'derive_clause' : "AttributeList",
'inverse_clause' : "AttributeList",
'inverse_attr' : "InverseAttribute",
'bound_spec' : "BoundSpecification",
'explicit_attr' : "ExplicitAttribute",
'width_spec' : "WidthSpec",
'string_type' : "StringType",
'named_types' : "NamedType",
'simple_types' : "SimpleType",
"type_decl": "TypeDeclaration",
"entity_decl": "EntityDeclaration",
"enumeration_type": "EnumerationType",
"aggregation_types": "AggregationType",
"general_aggregation_types": "AggregationType",
"select_type": "SelectType",
"binary_type": "BinaryType",
"subtype_declaration": "SubTypeExpression",
"supertype_constraint": "SuperTypeExpression",
"derive_clause": "AttributeList",
"inverse_clause": "AttributeList",
"inverse_attr": "InverseAttribute",
"bound_spec": "BoundSpecification",
"explicit_attr": "ExplicitAttribute",
"width_spec": "WidthSpec",
"string_type": "StringType",
"named_types": "NamedType",
"simple_types": "SimpleType",
}
to_emit = set(id for id, expr in express)
emitted = set()
to_combine = set(["simple_id"])
statements = []
terminals = reduce(lambda x,y: x | y, (find_bytype(e, Terminal) for id, e in express))
keywords = list(filter(operator.attrgetter('is_keyword'), terminals))
terminals = reduce(lambda x, y: x | y, (find_bytype(e, Terminal) for id, e in express))
keywords = list(filter(operator.attrgetter("is_keyword"), terminals))
negated_keywords = map(lambda s: "~%s" % s, keywords)
no_action = {"letter", "digit", "digits", "real_literal", "integer_literal"}
@@ -157,14 +176,15 @@ while True:
stmt = " + ".join(itertools.chain(negated_keywords, ("originalTextFor(Combine%s)" % stmt,)))
if id not in no_action and not isinstance(expr.contents, Keyword) and not id in to_combine:
node_type = "ListNode" if "ZeroOrMore" in stmt else "Node"
action = actions.get(id, "lambda s, loc, t: %s(s, loc, t, rule=\"%s\")" % (node_type, id))
action = actions.get(id, 'lambda s, loc, t: %s(s, loc, t, rule="%s")' % (node_type, id))
stmt = "%s.setParseAction(%s)" % (stmt, action)
statements.append("%s = %s(\"%s\")" % (id, stmt, id))
statements.append('%s = %s("%s")' % (id, stmt, id))
to_emit -= emitted_in_loop
if not emitted_in_loop: break
if not emitted_in_loop:
break
for id in to_emit:
statements.append("%s = Forward()(\"%s\")" % (id, id))
statements.append('%s = Forward()("%s")' % (id, id))
for id in to_emit:
expr = [e for k, e in express if k == id][0]
@@ -173,11 +193,14 @@ for id in to_emit:
stmt = "Suppress%s" % stmt
if id not in no_action and not isinstance(expr.contents, Keyword):
node_type = "ListNode" if "ZeroOrMore" in stmt else "Node"
action = ".setParseAction(%s)" % (actions[id] if id in actions else "lambda s, loc, t: %s(s, loc, t, rule=\"%s\")" % (node_type, id))
action = ".setParseAction(%s)" % (
actions[id] if id in actions else 'lambda s, loc, t: %s(s, loc, t, rule="%s")' % (node_type, id)
)
stmt = "(%s)%s" % (stmt, action)
statements.append("%s << %s" % (id, stmt))
print ("""
print(
"""
# This file is generated by IfcOpenShell ifcexpressparser bootstrap.py
import os
@@ -215,4 +238,6 @@ if __name__ == "__main__":
mdl = importlib.import_module(output)
mdl.Generator(m).emit()
sys.stdout.write(m.schema.name)
"""%('\n '.join(statements)))
"""
% ("\n ".join(statements))
)
@@ -17,19 +17,23 @@
# #
###############################################################################
class Base(object):
"""
A base class for all code generation classes. Currently only working around
some python 2/3 incompatibilities in terms of unicode file handling.
"""
def emit(self):
import platform
if tuple(map(int, platform.python_version_tuple())) < (2, 8):
from io import open as unicode_open
unicode_type = unicode
else:
unicode_open = open
unicode_type = lambda x, *args, **kwargs: x
f = unicode_open(self.file_name, 'w', encoding='utf-8')
f.write(unicode_type(repr(self), encoding='utf-8', errors='ignore'))
f = unicode_open(self.file_name, "w", encoding="utf-8")
f.write(unicode_type(repr(self), encoding="utf-8", errors="ignore"))
f.close()
@@ -24,45 +24,47 @@ import codegen
from collections import defaultdict
class Definitions(codegen.Base):
def __init__(self, mapping):
schema_name = mapping.schema.name
self.schema_name = schema_name_title = schema_name.capitalize()
statements = ['']
statements = [""]
def write_entity(schema_name, name, type):
attribute_names = list(map(lambda t: (t.name, t.optional), type.attributes))
for attr, is_optional in attribute_names:
statements.append("#define SCHEMA_%(name)s_HAS_%(attr)s" % locals())
if is_optional:
statements.append("#define SCHEMA_%(name)s_%(attr)s_IS_OPTIONAL" % locals())
inverse_attribute_names = list(map(operator.attrgetter('name'), type.inverse))
inverse_attribute_names = list(map(operator.attrgetter("name"), type.inverse))
for attr in inverse_attribute_names:
statements.append("#define SCHEMA_%(name)s_HAS_%(attr)s" % locals())
def write(name):
statements.append("#define SCHEMA_HAS_%(name)s" % locals())
fn = None
if mapping.schema.is_entity(name):
fn = write_entity
if fn is not None:
decl = mapping.schema[name]
if isinstance(decl, nodes.TypeDeclaration):
decl = decl.type.type
fn(schema_name, name, decl) is not False
for name in mapping.schema:
write(name)
self.str = "\n".join(statements) + "\n"
self.file_name = '%s-definitions.h' % self.schema_name
self.file_name = "%s-definitions.h" % self.schema_name
def __repr__(self):
return self.str
Generator = Definitions
@@ -31,10 +31,12 @@ import re
import os
import csv
from schema import OrderedCaseInsensitiveDict
from schema import OrderedCaseInsensitiveDict
try: from html.entities import entitydefs
except: from htmlentitydefs import entitydefs
try:
from html.entities import entitydefs
except:
from htmlentitydefs import entitydefs
make_absolute = lambda fn: os.path.join(os.path.dirname(os.path.realpath(__file__)), fn)
@@ -42,36 +44,45 @@ name_to_oid = OrderedCaseInsensitiveDict()
oid_to_desc = {}
oid_to_name = {}
oid_to_pid = {}
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' ']))
regices = list(
zip(
[re.compile(s, re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>', r"(\n[\t ]*){2,}", r"^[\t ]+"]],
["", "\n\n", " "],
)
)
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
definition_files = ["DocEntity.csv", "DocEnumeration.csv", "DocDefined.csv", "DocSelect.csv"]
definition_files = map(make_absolute, definition_files)
for fn in definition_files:
with open(fn, encoding="utf8", errors='ignore') as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
with open(fn, encoding="utf8", errors="ignore") as f:
for oid, name, desc in csv.reader(f, delimiter=";", quotechar='"'):
name_to_oid[name] = oid
oid_to_name[oid] = name
oid_to_desc[oid] = desc
with open(make_absolute('DocEntityAttributes.csv')) as f:
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
with open(make_absolute("DocEntityAttributes.csv")) as f:
for pid, x, oid in csv.reader(f, delimiter=";", quotechar='"'):
oid_to_pid[oid] = pid
with open(make_absolute('DocAttribute.csv')) as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
with open(make_absolute("DocAttribute.csv")) as f:
for oid, name, desc in csv.reader(f, delimiter=";", quotechar='"'):
pid = oid_to_pid[oid]
pname = oid_to_name[pid]
name_to_oid[".".join((pname, name))] = oid
oid_to_desc[oid] = desc
def description(item):
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
oid = name_to_oid.get(item,0)
oid = name_to_oid.get(item, 0)
desc = oid_to_desc.get(oid, None)
if desc:
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
desc = desc.replace("\r","")
for r,s in regices: desc = r.sub(s,desc)
for a, b in entitydefs.items():
desc = desc.replace("&%s;" % a, b)
desc = desc.replace("\r", "")
for r, s in regices:
desc = r.sub(s, desc)
desc = desc.strip()
return desc.split("\n")
else: return []
else:
return []
@@ -23,31 +23,35 @@ import codegen
import templates
import documentation
class Header(codegen.Base):
def __init__(self, mapping):
declarations = []
write = lambda str, **kwargs: declarations.append(str%dict({
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
write = lambda str, **kwargs: declarations.append(
str
% dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs)
)
forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys())
forward_definitions = "".join(["class %s; "%n for n in forward_names])
forward_definitions = "".join(["class %s; " % n for n in forward_names])
for name, type in mapping.schema.selects.items():
write(templates.select, name=name)
for name, type in mapping.schema.enumerations.items():
short_name = name[:-4] if name.endswith("Enum") else name
write(templates.enumeration, name=name, values=", ".join(["%s_%s"%(short_name, v) for v in type.values]))
write(templates.enumeration, name=name, values=", ".join(["%s_%s" % (short_name, v) for v in type.values]))
emitted_simpletypes = set()
while len(emitted_simpletypes) < len(mapping.schema.simpletypes):
for name, type in mapping.schema.simpletypes.items():
if name.lower() in emitted_simpletypes: continue
if name.lower() in emitted_simpletypes:
continue
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
attr_type = mapping.make_argument_type(type)
superclass = mapping.simple_type_parent(name)
if superclass is None:
if superclass is None:
superclass = "IfcUtil::IfcBaseType"
elif superclass.lower() not in emitted_simpletypes:
continue
@@ -59,91 +63,154 @@ class Header(codegen.Base):
class_definitions = []
write = lambda str, **kwargs: class_definitions.append(str%dict({
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
write = lambda str, **kwargs: class_definitions.append(
str
% dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs)
)
emitted_entities = set()
while len(emitted_entities) < len(mapping.schema.entities):
for name, type in mapping.schema.entities.items():
if name.lower() in emitted_entities: continue
if name.lower() in emitted_entities:
continue
if len(type.supertypes) == 0 or set(map(str.lower, type.supertypes)) <= emitted_entities:
attr_lines = []
def write_method(attr):
if attr.optional:
attr_lines.append(templates.optional_attribute_description % (attr.name, name))
attr_lines.append("bool has%s() const;"%(attr.name))
attr_lines.extend(["/// %s"%d for d in documentation.description(".".join((name, attr.name)))])
attr_lines.append("bool has%s() const;" % (attr.name))
attr_lines.extend(
["/// %s" % d for d in documentation.description(".".join((name, attr.name)))]
)
type_str = mapping.get_parameter_type(attr, allow_optional=False, allow_entities=False)
if mapping.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN":
attr_lines.append("%s %s() const;"%(type_str, attr.name))
attr_lines.append("void set%s(%s v);"%(attr.name, type_str))
attr_lines.append("%s %s() const;" % (type_str, attr.name))
attr_lines.append("void set%s(%s v);" % (attr.name, type_str))
[write_method(attr) for attr in type.attributes]
inv_lines = []
def write_inverse(attr):
inv_lines.append(templates.inverse_attr%{'name':attr.name, 'entity':attr.entity, 'attribute':attr.attribute})
inv_lines.append(
templates.inverse_attr
% {"name": attr.name, "entity": attr.entity, "attribute": attr.attribute}
)
if type.inverse:
[write_inverse(attr) for attr in type.inverse]
attributes = "\n".join(["%s%s"%(' '*4, a) for a in attr_lines])
if len(attributes): attributes += '\n'
attributes = "\n".join(["%s%s" % (" " * 4, a) for a in attr_lines])
if len(attributes):
attributes += "\n"
inverse = "\n".join(["%s%s"%(' '*4, a) for a in inv_lines])
if len(inverse): inverse += '\n'
inverse = "\n".join(["%s%s" % (" " * 4, a) for a in inv_lines])
if len(inverse):
inverse += "\n"
def case_norm(n):
n = n.lower()
return [k for k in mapping.schema.entities.keys() if k.lower() == n][0]
supertypes = map(case_norm, type.supertypes) if len(type.supertypes) else ['IfcUtil::IfcBaseEntity']
superclass = ": %s "%(", ".join(["public %s"%c for c in supertypes]))
supertypes = map(case_norm, type.supertypes) if len(type.supertypes) else ["IfcUtil::IfcBaseEntity"]
superclass = ": %s " % (", ".join(["public %s" % c for c in supertypes]))
argument_count = mapping.argument_count(type)
argument_start = argument_count - len(type.attributes)
argument_name_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return "%s"; '%(i+argument_start, attr.name) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
argument_name_function_body_tail = (" return %s::getArgumentName(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
argument_name_function_body_switch_stmt = (
" switch (i) {%s}"
% (
"".join(
[
'case %d: return "%s"; ' % (i + argument_start, attr.name)
for i, attr in enumerate(type.attributes)
]
)
)
if len(type.attributes)
else ""
)
argument_name_function_body_tail = (
(" return %s::getArgumentName(i); " % type.supertypes[0])
if len(type.supertypes) == 1
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
)
argument_name_function_body = (
argument_name_function_body_switch_stmt + argument_name_function_body_tail
)
argument_name_function_body = argument_name_function_body_switch_stmt + argument_name_function_body_tail
derived = mapping.derived_in_supertype(type)
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
attribute_names = list(map(operator.attrgetter("name"), mapping.arguments(type)))
derived_in_supertype = set(derived) & set(attribute_names)
derived_in_supertype_indices = sorted(attribute_names.index(nm) for nm in derived_in_supertype)
attribute_type_cases = ['case %d: return IfcUtil::Argument_DERIVED; ' % idx for idx in derived_in_supertype_indices]
attribute_type_cases += ['case %d: return %s; '%(i+argument_start, mapping.make_argument_type(attr)) for i, attr in enumerate(type.attributes)]
argument_type_function_body_switch_stmt = " switch (i) {%s}"%("".join(attribute_type_cases)) if len(type.attributes) else ""
argument_type_function_body_tail = (" return %s::getArgumentType(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
attribute_type_cases = [
"case %d: return IfcUtil::Argument_DERIVED; " % idx for idx in derived_in_supertype_indices
]
attribute_type_cases += [
"case %d: return %s; " % (i + argument_start, mapping.make_argument_type(attr))
for i, attr in enumerate(type.attributes)
]
argument_type_function_body_switch_stmt = (
" switch (i) {%s}" % ("".join(attribute_type_cases)) if len(type.attributes) else ""
)
argument_type_function_body_tail = (
(" return %s::getArgumentType(i); " % type.supertypes[0])
if len(type.supertypes) == 1
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
)
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
argument_entity_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_entity(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
argument_entity_function_body_tail = (" return %s::getArgumentEntity(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
argument_type_function_body = (
argument_type_function_body_switch_stmt + argument_type_function_body_tail
)
argument_entity_function_body = argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
argument_entity_function_body_switch_stmt = (
" switch (i) {%s}"
% (
"".join(
[
"case %d: return %s; " % (i + argument_start, mapping.make_argument_entity(attr))
for i, attr in enumerate(type.attributes)
]
)
)
if len(type.attributes)
else ""
)
argument_entity_function_body_tail = (
(" return %s::getArgumentEntity(i); " % type.supertypes[0])
if len(type.supertypes) == 1
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
)
constructor_arguments = ", ".join("%(full_type)s v%(index)d_%(name)s"%a for a in mapping.get_assignable_arguments(type))
argument_entity_function_body = (
argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
)
constructor_arguments = ", ".join(
"%(full_type)s v%(index)d_%(name)s" % a for a in mapping.get_assignable_arguments(type)
)
write(templates.entity, **locals())
emitted_entities.add(name)
self.str = templates.header % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize(),
'declarations' : ''.join(declarations),
'forward_definitions' : forward_definitions,
'class_definitions' : ''.join(class_definitions)
"schema_name_upper": mapping.schema.name.upper(),
"schema_name": mapping.schema.name.capitalize(),
"declarations": "".join(declarations),
"forward_definitions": forward_definitions,
"class_definitions": "".join(class_definitions),
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s.h'%self.schema_name
self.file_name = "%s.h" % self.schema_name
def __repr__(self):
return self.str
Generator = Header
@@ -22,6 +22,7 @@ import templates
from schema import OrderedCaseInsensitiveDict
class Implementation(codegen.Base):
def __init__(self, mapping):
enumeration_functions = []
@@ -31,230 +32,324 @@ class Implementation(codegen.Base):
schema_name = mapping.schema.name.capitalize()
schema_name_upper = mapping.schema.name.upper()
stringify = lambda s: '"%s"'%s
stringify = lambda s: '"%s"' % s
cat = lambda vs: "".join(vs)
catc = lambda vs: ", ".join(vs)
catnl = lambda vs: "\n".join(vs)
cator = lambda vs: " || ".join(vs)
nl = lambda s: "%s\n"%s if len(s) else s
nl = lambda s: "%s\n" % s if len(s) else s
write = lambda str, **kwargs: enumeration_functions.append(str%kwargs)
write = lambda str, **kwargs: enumeration_functions.append(str % kwargs)
for name, enum in mapping.schema.enumerations.items():
short_name = name[:-4] if name.endswith("Enum") else name
context = locals()
write(
templates.enumeration_function,
max_id = len(enum.values),
name = name,
schema_name = schema_name,
schema_name_upper = schema_name_upper,
values = catc(map(stringify, enum.values)),
from_string_statements = catnl(templates.enum_from_string_stmt%dict(context,**locals()) for value in enum.values)
max_id=len(enum.values),
name=name,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
values=catc(map(stringify, enum.values)),
from_string_statements=catnl(
templates.enum_from_string_stmt % dict(context, **locals()) for value in enum.values
),
)
write = lambda str, **kwargs: entity_implementations.append(str%kwargs)
write = lambda str, **kwargs: entity_implementations.append(str % kwargs)
for name, type in mapping.schema.entities.items():
parent_type_test = "" if not type.supertypes or len(type.supertypes) != 1 \
else templates.parent_type_test%(type.supertypes[0])
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
constructor_arguments_str = catc("%(full_type)s v%(index)d_%(name)s"%a for a in constructor_arguments if not a['is_derived'])
for name, type in mapping.schema.entities.items():
parent_type_test = (
""
if not type.supertypes or len(type.supertypes) != 1
else templates.parent_type_test % (type.supertypes[0])
)
constructor_arguments = mapping.get_assignable_arguments(type, include_derived=True)
constructor_arguments_str = catc(
"%(full_type)s v%(index)d_%(name)s" % a for a in constructor_arguments if not a["is_derived"]
)
attributes = []
constructor_implementations = []
write_attr = lambda str, **kwargs: attributes.append(str%kwargs)
write_attr = lambda str, **kwargs: attributes.append(str % kwargs)
for arg in constructor_arguments:
if not arg['is_inherited'] and not arg['is_derived']:
if arg['is_optional']:
if not arg["is_inherited"] and not arg["is_derived"]:
if arg["is_optional"]:
write_attr(
templates.const_function,
class_name = name,
schema_name = schema_name,
schema_name_upper = schema_name_upper,
name = 'has%s'%arg['name'],
arguments = '',
return_type = 'bool',
body = templates.optional_attr_stmt % {'index':arg['index']-1}
class_name=name,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
name="has%s" % arg["name"],
arguments="",
return_type="bool",
body=templates.optional_attr_stmt % {"index": arg["index"] - 1},
)
def find_template(arg):
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
express = mapping.flatten_type_string(arg['list_instance_type']) in mapping.express_to_cpp_typemapping
if arg['is_enum']: return templates.get_attr_stmt_enum
elif arg['is_nested'] and arg['is_templated_list']: return templates.get_attr_stmt_nested_array
elif arg['is_templated_list'] and not (select or simple or express): return templates.get_attr_stmt_array
elif arg['non_optional_type'].endswith('*'): return templates.get_attr_stmt_entity
else: return templates.get_attr_stmt
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
express = (
mapping.flatten_type_string(arg["list_instance_type"]) in mapping.express_to_cpp_typemapping
)
if arg["is_enum"]:
return templates.get_attr_stmt_enum
elif arg["is_nested"] and arg["is_templated_list"]:
return templates.get_attr_stmt_nested_array
elif arg["is_templated_list"] and not (select or simple or express):
return templates.get_attr_stmt_array
elif arg["non_optional_type"].endswith("*"):
return templates.get_attr_stmt_entity
else:
return templates.get_attr_stmt
tmpl = find_template(arg)
write_attr(
templates.const_function,
class_name = name,
name = arg['name'],
arguments = '',
schema_name = schema_name,
schema_name_upper = schema_name_upper,
return_type = arg['non_optional_type'],
body = tmpl % {'index': arg['index']-1,
'type' : arg['non_optional_type'].replace('::Value', ''),
'list_instance_type' : arg['list_instance_type']}
class_name=name,
name=arg["name"],
arguments="",
schema_name=schema_name,
schema_name_upper=schema_name_upper,
return_type=arg["non_optional_type"],
body=tmpl
% {
"index": arg["index"] - 1,
"type": arg["non_optional_type"].replace("::Value", ""),
"list_instance_type": arg["list_instance_type"],
},
)
def find_template(arg):
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
express = arg['list_instance_type'] in mapping.express_to_cpp_typemapping
if arg['is_enum']: return templates.set_attr_stmt_enum
elif arg['is_templated_list'] and not (select or simple or express): return templates.set_attr_stmt_array
else: return templates.set_attr_stmt
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
express = arg["list_instance_type"] in mapping.express_to_cpp_typemapping
if arg["is_enum"]:
return templates.set_attr_stmt_enum
elif arg["is_templated_list"] and not (select or simple or express):
return templates.set_attr_stmt_array
else:
return templates.set_attr_stmt
tmpl = find_template(arg)
write_attr(
templates.function,
class_name = name,
name = 'set%s'%arg['name'],
arguments = '%s v'%arg['non_optional_type'],
return_type = 'void',
schema_name = schema_name,
schema_name_upper = schema_name_upper,
body = tmpl % {'index': arg['index']-1,
'type' : arg['non_optional_type'].replace('::Value', '')}
class_name=name,
name="set%s" % arg["name"],
arguments="%s v" % arg["non_optional_type"],
return_type="void",
schema_name=schema_name,
schema_name_upper=schema_name_upper,
body=tmpl
% {"index": arg["index"] - 1, "type": arg["non_optional_type"].replace("::Value", "")},
)
if arg['is_derived']:
constructor_implementations.append(templates.constructor_stmt_derived % {'index' : arg['index']-1})
if arg["is_derived"]:
constructor_implementations.append(templates.constructor_stmt_derived % {"index": arg["index"] - 1})
else:
is_optional_non_naked_ptr = arg['is_optional'] and not arg['non_optional_type'].endswith('*')
arg_name = "v%(index)d_%(name)s"%arg
deref_name = ("*%s"%arg_name) if is_optional_non_naked_ptr else arg_name
is_optional_non_naked_ptr = arg["is_optional"] and not arg["non_optional_type"].endswith("*")
arg_name = "v%(index)d_%(name)s" % arg
deref_name = ("*%s" % arg_name) if is_optional_non_naked_ptr else arg_name
tmpl = templates.constructor_stmt_array if arg['is_templated_list'] \
else templates.constructor_stmt_enum if arg['is_enum'] \
tmpl = (
templates.constructor_stmt_array
if arg["is_templated_list"]
else templates.constructor_stmt_enum
if arg["is_enum"]
else templates.constructor_stmt
impl = tmpl % {'name' : deref_name,
'index' : arg['index']-1,
'type' : arg['non_optional_type'].replace('::Value', '')}
)
impl = tmpl % {
"name": deref_name,
"index": arg["index"] - 1,
"type": arg["non_optional_type"].replace("::Value", ""),
}
if is_optional_non_naked_ptr:
impl = templates.constructor_stmt_optional%{'name' : arg_name,
'index' : arg['index']-1,
'stmt' : impl}
impl = templates.constructor_stmt_optional % {
"name": arg_name,
"index": arg["index"] - 1,
"stmt": impl,
}
constructor_implementations.append(impl)
def get_attribute_index(entity, attr_name):
related_entity = mapping.schema.entities[entity]
return [a['name'].lower() for a in mapping.get_assignable_arguments(related_entity, include_derived=True)].index(attr_name.lower())
return [
a["name"].lower() for a in mapping.get_assignable_arguments(related_entity, include_derived=True)
].index(attr_name.lower())
inverse = [templates.const_function % {
'class_name' : name,
'schema_name' : schema_name,
'schema_name_upper' : schema_name_upper,
'name' : i.name,
'arguments' : '',
'return_type' : '::%s::%s::list::ptr' % (schema_name, i.entity),
'body' : templates.get_inverse % {'type': i.entity, 'index':get_attribute_index(i.entity, i.attribute), 'schema_name' : schema_name, 'schema_name_upper': schema_name_upper}
} for i in type.inverse]
inverse = [
templates.const_function
% {
"class_name": name,
"schema_name": schema_name,
"schema_name_upper": schema_name_upper,
"name": i.name,
"arguments": "",
"return_type": "::%s::%s::list::ptr" % (schema_name, i.entity),
"body": templates.get_inverse
% {
"type": i.entity,
"index": get_attribute_index(i.entity, i.attribute),
"schema_name": schema_name,
"schema_name_upper": schema_name_upper,
},
}
for i in type.inverse
]
superclass = "%s((IfcEntityInstanceData*)0)" % type.supertypes[0] if len(type.supertypes) == 1 else 'IfcUtil::IfcBaseEntity()'
superclass = (
"%s((IfcEntityInstanceData*)0)" % type.supertypes[0]
if len(type.supertypes) == 1
else "IfcUtil::IfcBaseEntity()"
)
write(
templates.entity_implementation,
name = name,
parent_type_test = parent_type_test,
constructor_arguments = constructor_arguments_str,
constructor_implementation = cat(constructor_implementations),
attributes = nl(catnl(attributes)),
inverse = nl(catnl(inverse)),
superclass = superclass,
schema_name = schema_name,
schema_name_upper = schema_name_upper
name=name,
parent_type_test=parent_type_test,
constructor_arguments=constructor_arguments_str,
constructor_implementation=cat(constructor_implementations),
attributes=nl(catnl(attributes)),
inverse=nl(catnl(inverse)),
superclass=superclass,
schema_name=schema_name,
schema_name_upper=schema_name_upper,
)
selectable_simple_types = sorted(set(sum([b.values for a,b in mapping.schema.selects.items()], [])) & set(map(str, mapping.schema.types.keys())))
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.simpletypes.items()]
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.entities.items()]
selectable_simple_types = sorted(
set(sum([b.values for a, b in mapping.schema.selects.items()], []))
& set(map(str, mapping.schema.types.keys()))
)
schema_entity_statements += [
templates.schema_entity_stmt % locals() for name, type in mapping.schema.simpletypes.items()
]
schema_entity_statements += [
templates.schema_entity_stmt % locals() for name, type in mapping.schema.entities.items()
]
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
enumerable_types = sorted(
set(
[name for name, type in mapping.schema.types.items()]
+ [name for name, type in mapping.schema.entities.items()]
)
)
max_len = max(map(len, enumerable_types))
type_name_strings = catc(map(stringify, enumerable_types))
string_map_statements = [templates.string_map_statement % {
'uppercase_name' : name.upper(),
'name' : name,
'padding' : ' ' * (max_len - len(name))
} for name in enumerable_types]
enumeration_index_by_str = OrderedCaseInsensitiveDict((j,i) for i,j in enumerate(enumerable_types))
string_map_statements = [
templates.string_map_statement
% {"uppercase_name": name.upper(), "name": name, "padding": " " * (max_len - len(name))}
for name in enumerable_types
]
enumeration_index_by_str = OrderedCaseInsensitiveDict((j, i) for i, j in enumerate(enumerable_types))
def get_parent_id(s):
e = mapping.schema.entities.get(s)
if e and e.supertypes:
return enumeration_index_by_str[e.supertypes[0]]
else: return -1
else:
return -1
parent_type_statements = ",".join(map(str, map(get_parent_id, enumerable_types)))
max_id = len(enumerable_types)
simple_type_statements = cator("v == Type::%s"%name for name in selectable_simple_types)
simple_type_statements = cator("v == Type::%s" % name for name in selectable_simple_types)
simple_type_impl = []
for class_name, type in mapping.schema.simpletypes.items():
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
attr_type = mapping.make_argument_type(type)
superclass = mapping.simple_type_parent(class_name)
simpletype_impl_is = templates.simpletype_impl_is_with_supertype if superclass \
simpletype_impl_is = (
templates.simpletype_impl_is_with_supertype
if superclass
else templates.simpletype_impl_is_without_supertype
constructor = templates.constructor_single_initlist if superclass \
else templates.constructor
simpletype_impl_cast = templates.simpletype_impl_cast_templated if mapping.is_templated_list(type) \
)
constructor = templates.constructor_single_initlist if superclass else templates.constructor
simpletype_impl_cast = (
templates.simpletype_impl_cast_templated
if mapping.is_templated_list(type)
else templates.simpletype_impl_cast
simpletype_impl_constructor = templates.simpletype_impl_constructor_templated if mapping.is_templated_list(type) \
)
simpletype_impl_constructor = (
templates.simpletype_impl_constructor_templated
if mapping.is_templated_list(type)
else templates.simpletype_impl_constructor
)
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
underlying_type = mapping.list_instance_type(type)
arguments = ",".join(args)
body = body % locals()
return tmpl % locals()
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
('Class', templates.function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_class ),
('declaration', templates.const_function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_declaration ),
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
('', templates.cast_function, type_str, (), simpletype_impl_cast )
))))
simple_type_impl.append('')
external_definitions = [("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys() ] + \
[("extern type_declaration* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.simpletypes.keys()]
simple_type_impl.append(templates.simpletype_impl_comment % {"name": class_name})
simple_type_impl.extend(
map(
compose,
map(
lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0") + x,
(
(
"Class",
templates.function,
"const IfcParse::type_declaration&",
(),
templates.simpletype_impl_class,
),
(
"declaration",
templates.const_function,
"const IfcParse::type_declaration&",
(),
templates.simpletype_impl_declaration,
),
(
"",
constructor,
"",
("IfcEntityInstanceData* e",),
templates.simpletype_impl_explicit_constructor,
),
("", constructor, "", ("%s v" % type_str,), simpletype_impl_constructor),
("", templates.cast_function, type_str, (), simpletype_impl_cast),
),
),
)
)
simple_type_impl.append("")
external_definitions = [
("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys()
] + [
("extern type_declaration* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.simpletypes.keys()
]
self.str = templates.implementation % {
'schema_name_upper' : schema_name_upper,
'schema_name' : schema_name,
'max_id' : max_id,
'enumeration_functions' : cat(enumeration_functions),
'schema_entity_statements' : catnl(schema_entity_statements),
'type_name_strings' : type_name_strings,
'string_map_statements' : catnl(string_map_statements),
'simple_type_statement' : simple_type_statements,
'parent_type_statements' : parent_type_statements,
'entity_implementations' : catnl(entity_implementations),
'simple_type_impl' : catnl(simple_type_impl),
'external_definitions' : catnl(external_definitions)
"schema_name_upper": schema_name_upper,
"schema_name": schema_name,
"max_id": max_id,
"enumeration_functions": cat(enumeration_functions),
"schema_entity_statements": catnl(schema_entity_statements),
"type_name_strings": type_name_strings,
"string_map_statements": catnl(string_map_statements),
"simple_type_statement": simple_type_statements,
"parent_type_statements": parent_type_statements,
"entity_implementations": catnl(entity_implementations),
"simple_type_impl": catnl(simple_type_impl),
"external_definitions": catnl(external_definitions),
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s.cpp'%self.schema_name
self.file_name = "%s.cpp" % self.schema_name
def __repr__(self):
return self.str
@@ -23,57 +23,80 @@ import sys
import nodes
import templates
class Mapping:
express_to_cpp_typemapping = {
'boolean' : 'bool',
'logical' : 'bool',
'integer' : 'int',
'real' : 'double',
'number' : 'double',
'string' : 'std::string',
'binary' : 'boost::dynamic_bitset<>'
"boolean": "bool",
"logical": "bool",
"integer": "int",
"real": "double",
"number": "double",
"string": "std::string",
"binary": "boost::dynamic_bitset<>",
}
supported_argument_types = set([
'INT', 'BOOL', 'DOUBLE', 'STRING', 'BINARY', 'ENUMERATION', 'ENTITY_INSTANCE',
'AGGREGATE_OF_INT', 'AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_STRING', 'AGGREGATE_OF_BINARY', 'AGGREGATE_OF_ENTITY_INSTANCE',
'AGGREGATE_OF_AGGREGATE_OF_INT', 'AGGREGATE_OF_AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE',
])
supported_argument_types = set(
[
"INT",
"BOOL",
"DOUBLE",
"STRING",
"BINARY",
"ENUMERATION",
"ENTITY_INSTANCE",
"AGGREGATE_OF_INT",
"AGGREGATE_OF_DOUBLE",
"AGGREGATE_OF_STRING",
"AGGREGATE_OF_BINARY",
"AGGREGATE_OF_ENTITY_INSTANCE",
"AGGREGATE_OF_AGGREGATE_OF_INT",
"AGGREGATE_OF_AGGREGATE_OF_DOUBLE",
"AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE",
]
)
def __init__(self, schema):
self.schema = schema
def flatten_type_string(self, type):
return self.flatten_type_string(self.schema.types[type].type) if self.schema.is_simpletype(type) else type
def flatten_type(self, type):
res = self.flatten_type(self.schema.types[type].type) if self.schema.is_simpletype(type) else type
return res
def simple_type_parent(self, type):
parent = self.schema.types[type].type
if isinstance(parent, (nodes.AggregationType, nodes.StringType)) or (isinstance(parent, nodes.SimpleType) and isinstance(parent.type, nodes.StringType)):
if isinstance(parent, (nodes.AggregationType, nodes.StringType)) or (
isinstance(parent, nodes.SimpleType) and isinstance(parent.type, nodes.StringType)
):
return None
if str(parent) in self.express_to_cpp_typemapping:
return None
return str(parent)
def make_type_string(self, type):
if isinstance(type, nodes.StringType) or (isinstance(type, nodes.SimpleType) and isinstance(type.type, nodes.StringType)):
if isinstance(type, nodes.StringType) or (
isinstance(type, nodes.SimpleType) and isinstance(type.type, nodes.StringType)
):
type = "string"
if isinstance(type, (str, nodes.BinaryType, nodes.SimpleType, nodes.NamedType)):
return self.express_to_cpp_typemapping.get(str(type), "::%s::%s" % (self.schema.name.capitalize(), type))
else:
if type.bounds is None:
import pdb; pdb.set_trace()
import pdb
pdb.set_trace()
is_list = self.schema.is_entity(type.type)
is_nested_list = isinstance(type.type, nodes.AggregationType)
tmpl = templates.list_list_type if is_nested_list else templates.list_type if is_list else templates.array_type
tmpl = (
templates.list_list_type if is_nested_list else templates.list_type if is_list else templates.array_type
)
return tmpl % {
'instance_type' : self.make_type_string(self.flatten_type_string(type.type)),
'lower' : type.bounds.lower,
'upper' : type.bounds.upper,
"instance_type": self.make_type_string(self.flatten_type_string(type.type)),
"lower": type.bounds.lower,
"upper": type.bounds.upper,
}
def is_array(self, type):
@@ -83,12 +106,15 @@ class Mapping:
return self.is_array(self.schema.types[type].type)
else:
return False
def make_argument_entity(self, attr):
type = attr.type if hasattr(attr, 'type') else attr
while isinstance(type, nodes.AggregationType): type = type.type
if str(type) in self.express_to_cpp_typemapping: return "Type::UNDEFINED"
else: return "Type::%s" % type
type = attr.type if hasattr(attr, "type") else attr
while isinstance(type, nodes.AggregationType):
type = type.type
if str(type) in self.express_to_cpp_typemapping:
return "Type::UNDEFINED"
else:
return "Type::%s" % type
def make_argument_type(self, attr):
def _make_argument_type(type):
@@ -104,18 +130,20 @@ class Mapping:
return "ENUMERATION"
elif isinstance(type, nodes.AggregationType):
ty = _make_argument_type(type.type)
if ty == "UNKNOWN": return "UNKNOWN"
if ty == "UNKNOWN":
return "UNKNOWN"
return "AGGREGATE_OF_" + ty
elif str(type) in self.express_to_cpp_typemapping:
return self.express_to_cpp_typemapping.get(str(type), type).split('::')[-1].upper()
return self.express_to_cpp_typemapping.get(str(type), type).split("::")[-1].upper()
elif self.schema.is_type(type):
return _make_argument_type(self.schema.types[type].type)
else:
raise ValueError("Unable to map type %r for attribute %r" % (type, attr))
ty = _make_argument_type(attr.type if hasattr(attr, 'type') else attr)
ty = _make_argument_type(attr.type if hasattr(attr, "type") else attr)
if ty not in self.supported_argument_types:
print("Attribute %r mapped as 'unknown'" % (attr), file=sys.stderr)
ty = 'UNKNOWN'
ty = "UNKNOWN"
return "IfcUtil::Argument_%s" % ty
def get_type_dep(self, type):
@@ -124,18 +152,20 @@ class Mapping:
else:
return self.get_type_dep(type.type)
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer = True):
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer=True):
attr_type = self.flatten_type(attr.type)
if (isinstance(attr_type, nodes.SimpleType) and isinstance(attr_type.type, nodes.StringType)) or isinstance(attr_type, nodes.StringType):
if (isinstance(attr_type, nodes.SimpleType) and isinstance(attr_type.type, nodes.StringType)) or isinstance(
attr_type, nodes.StringType
):
type_str = self.express_to_cpp_typemapping["string"]
else:
type_str = self.express_to_cpp_typemapping.get(str(attr_type), attr_type)
is_ptr = False
if self.schema.is_enumeration(attr_type):
type_str = '::%s::%s::Value' % (self.schema.name.capitalize(), attr_type)
type_str = "::%s::%s::Value" % (self.schema.name.capitalize(), attr_type)
elif isinstance(type_str, nodes.AggregationType):
is_nested_list = isinstance(attr_type.type, nodes.AggregationType)
ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type, False, allow_entities, False)
@@ -144,18 +174,12 @@ class Mapping:
elif self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values():
tmpl = templates.nested_array_type if is_nested_list else templates.array_type
bounds = (attr_type.bounds.lower, attr_type.bounds.upper) if attr_type.bounds else (-1, -1)
type_str = tmpl % {
'instance_type' : ty,
'lower' : bounds[0],
'upper' : bounds[1]
}
type_str = tmpl % {"instance_type": ty, "lower": bounds[0], "upper": bounds[1]}
else:
tmpl = templates.list_list_type if is_nested_list else templates.list_type
type_str = tmpl % {
'instance_type': ty
}
elif (self.schema.is_entity(type_str) or self.schema.is_select(type_str)):
type_str = '::%s::%s' % (self.schema.name.capitalize(), attr_type)
type_str = tmpl % {"instance_type": ty}
elif self.schema.is_entity(type_str) or self.schema.is_select(type_str):
type_str = "::%s::%s" % (self.schema.name.capitalize(), attr_type)
if allow_pointer:
type_str += "*"
is_ptr = True
@@ -163,7 +187,7 @@ class Mapping:
type_str = "IfcUtil::IfcBaseClass*"
is_ptr = True
if allow_optional and attr.optional and not is_ptr:
type_str = "boost::optional< %s >"%type_str
type_str = "boost::optional< %s >" % type_str
return type_str
def argument_count(self, t):
@@ -181,39 +205,49 @@ class Mapping:
def list_instance_type(self, attr):
attr_type = attr.type if isinstance(attr, nodes.ExplicitAttribute) else attr
if isinstance(attr_type, str): return None
if isinstance(attr_type, str):
return None
def f(v):
v = self.flatten_type(v)
if isinstance(v, (nodes.AggregationType, nodes.StringType)) or (isinstance(v, nodes.SimpleType) and isinstance(v.type, nodes.StringType)):
if isinstance(v, (nodes.AggregationType, nodes.StringType)) or (
isinstance(v, nodes.SimpleType) and isinstance(v.type, nodes.StringType)
):
return "string"
if self.schema.is_select(v):
return 'IfcUtil::IfcBaseClass'
return "IfcUtil::IfcBaseClass"
elif str(v) in self.schema.types or str(v) in self.schema.entities:
return "::%s::%s" % (self.schema.name.capitalize(), v)
else: return str(v)
else:
return str(v)
if self.is_array(attr_type):
if not isinstance(attr_type, str) and self.is_array(attr_type.type):
if isinstance(attr_type.type, str):
return f(attr_type.type)
else: return f(attr_type.type.type)
else:
return f(attr_type.type.type)
else:
if isinstance(attr_type, str):
return f(attr_type)
else: return f(attr_type.type)
else:
return f(attr_type.type)
return None
def is_templated_list(self, attr):
attr_type = attr.type if isinstance(attr, nodes.ExplicitAttribute) else attr
if isinstance(attr, str): return False
if isinstance(attr, str):
return False
ty = self.list_instance_type(attr)
if ty is None: return False
if ty is None:
return False
arr = self.is_array(attr_type)
simple = self.schema.is_simpletype(ty)
express = self.flatten_type_string(ty) in self.express_to_cpp_typemapping
select = ty == 'IfcUtil::IfcBaseClass'
select = ty == "IfcUtil::IfcBaseClass"
return arr and not simple and not express and not select
def get_assignable_arguments(self, t, include_derived = False):
def get_assignable_arguments(self, t, include_derived=False):
count = self.argument_count(t)
num_inherited = count - len(t.attributes)
derived = set(self.derived_in_supertype(t))
@@ -224,22 +258,27 @@ class Mapping:
supported = self.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN"
return not_derived and supported
return [{
'index' : i+1,
'name' : attr.name,
'full_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
'specialized_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
'non_optional_type' : self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
'list_instance_type' : self.list_instance_type(attr),
'is_optional' : attr.optional,
'is_inherited' : i < num_inherited,
'is_enum' : attr.type in self.schema.enumerations,
'is_array' : self.is_array(attr.type),
'is_nested' : self.is_array(attr.type) and not isinstance(attr.type, str) and self.is_array(attr.type.type),
'is_derived' : attr.name in derived,
'is_templated_list' : self.is_templated_list(attr),
'argument_type_enum' : self.make_argument_type(attr),
'argument_entity' : self.make_argument_entity(attr),
'argument_type' : attr.type
} for i, attr in attrs if include(attr)]
return [
{
"index": i + 1,
"name": attr.name,
"full_type": self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
"specialized_type": self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
"non_optional_type": self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
"list_instance_type": self.list_instance_type(attr),
"is_optional": attr.optional,
"is_inherited": i < num_inherited,
"is_enum": attr.type in self.schema.enumerations,
"is_array": self.is_array(attr.type),
"is_nested": self.is_array(attr.type)
and not isinstance(attr.type, str)
and self.is_array(attr.type.type),
"is_derived": attr.name in derived,
"is_templated_list": self.is_templated_list(attr),
"argument_type_enum": self.make_argument_type(attr),
"argument_entity": self.make_argument_entity(attr),
"argument_type": attr.type,
}
for i, attr in attrs
if include(attr)
]
@@ -23,61 +23,77 @@ import io
import string
import collections
class Node:
def __init__(self, s, loc, tokens, rule=None):
self.rule = rule or (type(self).__name__)
self.tokens = tokens.asDict()
self.flat = sum([getattr(t, 'flat', [t]) for t in tokens.asList()], [])
self.flat = sum([getattr(t, "flat", [t]) for t in tokens.asList()], [])
if rule is None:
self.init()
def __repr__(self):
return "%s(%s)" % (self.rule, ",".join("%s:%s" % i for i in self.tokens.items()))
def __getattr__(self, k):
return self.tokens.get(k)
def __getstate__(self): return self.__dict__
def __setstate__(self, d): self.__dict__.update(d)
def init(self): pass
def __getstate__(self):
return self.__dict__
def __setstate__(self, d):
self.__dict__.update(d)
def init(self):
pass
def any(self):
return next(iter(self.tokens.values()))
class ListNode:
def __init__(self, s, loc, tokens, rule=None):
self.rule = rule or (type(self).__name__)
self.tokens = tokens.asList()
self.flat = sum([getattr(t, 'flat', [t]) for t in self.tokens], [])
self.flat = sum([getattr(t, "flat", [t]) for t in self.tokens], [])
def __repr__(self):
return "%s[%s]" % (self.rule, ",".join("%s" % i for i in self.tokens))
def __iter__(self):
return iter(self.tokens)
def __getitem__(self, i):
return self.tokens[i]
def init(self): pass
def init(self):
pass
class SimpleType(Node):
def get_type(self):
t = self.any()
if (type(t) == Node):
if type(t) == Node:
return t.any()
else:
t = t[0]
if (type(t) == Node):
if type(t) == Node:
return t.any().any()
else:
return t
type = property(get_type)
def __repr__(self):
return str(self.type)
def format_clause(exp):
def whitespace(t):
if t in {'=', '|', '<*', 'or', 'in', '<>', 'and'}:
return ' %s ' % t
if t in {"=", "|", "<*", "or", "in", "<>", "and"}:
return " %s " % t
return t
return "".join(whitespace(term) for term in exp.flat)
@@ -85,18 +101,18 @@ class TypeDeclaration(Node):
name = property(lambda self: self.type_id[0])
utype = property(lambda self: self.underlying_type.any().any())
type = property(lambda self: self.utype[0] if isinstance(self.utype, list) else self.utype)
def init(self):
def init(self):
assert hasattr(self, "TYPE")
self.where = []
clause = self.where_clause
if clause:
clause = clause[0]
self.where = [(r.simple_id, format_clause(r.expression[0])) for r in clause[1::2]]
def __repr__(self):
s = "TYPE %s = %s;\n" % (self.name, self.type)
if self.where:
@@ -112,7 +128,7 @@ class EntityDeclaration(Node):
supertype = property(lambda self: self.entity_head[0].subsuper[0].supertype_constraint)
subtype = property(lambda self: self.entity_head[0].subsuper[0].subtype_declaration)
supertypes = property(lambda self: [self.subtype.super_type] if self.subtype else [])
def get_abstract(self):
if self.entity_head[0].subsuper[0].supertype_constraint:
return self.entity_head[0].subsuper[0].supertype_constraint.abstract
@@ -120,72 +136,71 @@ class EntityDeclaration(Node):
return False
abstract = property(get_abstract)
def init(self):
def redeclared_attribute(a):
try:
return (
a.attribute_decl.redeclared_attribute.qualified_attribute.group_qualifier.simple_id,
a.attribute_decl.redeclared_attribute.qualified_attribute.attribute_qualifier.simple_id
a.attribute_decl.redeclared_attribute.qualified_attribute.attribute_qualifier.simple_id,
)
except:
return a.attribute_decl.simple_id
assert self.flat[0] == 'entity'
assert self.flat[0] == "entity"
self.attributes = [a for a in self.entity_body[0] if isinstance(a, ExplicitAttribute)]
self.inverse = []
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == 'inverse']
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == "inverse"]
if alist:
self.inverse = alist[0]
self.inverse = alist[0]
self.derive = []
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == 'derive']
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == "derive"]
if alist:
alist = alist[0]
self.derive = [(redeclared_attribute(a), format_clause(a.expression[0])) for a in alist]
self.where = []
clause = [r for r in self.entity_body[0] if r.rule == "where_clause"]
if clause:
clause = clause[0]
self.where = [(r.simple_id, format_clause(r.expression[0])) for r in clause[1::2]]
self.unique = []
clause = [r for r in self.entity_body[0] if r.rule == "unique_clause"]
if clause:
clause = clause[0]
self.unique = [(r[0], r[2].simple_id) for r in clause[1::2]]
def __repr__(self):
strm = io.StringIO()
print("ENTITY %s" % self.name, file=strm)
if self.supertype:
print("", self.supertype, file=strm)
if self.subtype:
print("", self.subtype, file=strm)
strm.seek(strm.tell() - 1)
print(";", file=strm)
for a in self.attributes:
print(" ", a, ";", file=strm, sep='')
print(" ", a, ";", file=strm, sep="")
if self.derive:
print(" DERIVE", file=strm)
for nm, exp in self.derive:
if isinstance(nm, tuple):
nm = "SELF\\%s.%s" % nm
print(" %s : %s;" % (nm, exp), file=strm)
if self.inverse:
print(" INVERSE", file=strm)
print(self.inverse, file=strm)
if self.where:
print(" WHERE", file=strm)
for nm_exp in self.where:
@@ -195,19 +210,21 @@ class EntityDeclaration(Node):
print(" UNIQUE", file=strm)
for nm_exp in self.unique:
print(" %s : %s;" % nm_exp, file=strm)
print("END_ENTITY;", file=strm)
return strm.getvalue()
class EnumerationType(Node):
values = property(lambda self: self.enumeration_type[2][1::2])
def __repr__(self):
return "ENUMERATION OF (" + ",".join(self.values) + ")"
return "ENUMERATION OF (" + ",".join(self.values) + ")"
class NamedType(Node):
type = property(lambda self: self.simple_id)
def __repr__(self):
return self.type
@@ -216,7 +233,7 @@ class AggregationType(Node):
aggregate_type = property(lambda self: self.flat[0])
bounds = property(lambda self: (list(self.tokens.values())[0][0].bound_spec or [None])[0])
unique = property(lambda self: list(self.tokens.values())[0][0].UNIQUE is not None)
def get_type(self):
v = list(self.tokens.values())[0][0]
if v.instantiable_type:
@@ -231,51 +248,61 @@ class AggregationType(Node):
elif v.parameter_type.generalized_types.general_aggregation_types:
return v.parameter_type.generalized_types.general_aggregation_types
else:
import pdb; pdb.set_trace()
import pdb
pdb.set_trace()
raise ValueError()
type = property(get_type)
def init(self):
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
def __repr__(self):
return "%s%s of %s%s"%(self.aggregate_type, self.bounds, "unique " if self.unique else "", self.type)
return "%s%s of %s%s" % (self.aggregate_type, self.bounds, "unique " if self.unique else "", self.type)
class SelectType(Node):
values = property(lambda self: self.select_type[1][1::2])
def __repr__(self):
return "SELECT (" + ",".join(map(str, self.values)) + ")"
class SuperTypeExpression(Node):
abstract = property(lambda self: self.abstract_supertype_declaration is not None)
def get_sub_types(self):
if self.abstract:
constraint = self.abstract_supertype_declaration[0]
else:
constraint = self.supertype_rule[0]
return [s[0][0].simple_id for s in constraint.subtype_constraint[0].supertype_expression[0][0][0].one_of[0][2::2]]
return [
s[0][0].simple_id for s in constraint.subtype_constraint[0].supertype_expression[0][0][0].one_of[0][2::2]
]
sub_types = property(get_sub_types)
def __repr__(self):
return "%sSUPERTYPE OF(ONEOF(%s))" % ("ABSTRACT " if self.abstract else "",",".join(self.sub_types))
return "%sSUPERTYPE OF(ONEOF(%s))" % ("ABSTRACT " if self.abstract else "", ",".join(self.sub_types))
class SubTypeExpression(Node):
super_type = property(lambda self: self.entity_ref[0])
def __repr__(self):
return "SUBTYPE OF(%s)" % self.super_type
class AttributeList(ListNode):
type = property(lambda self: self.flat[0] if self.flat[0] in {'inverse', 'derive'} else 'explicit')
type = property(lambda self: self.flat[0] if self.flat[0] in {"inverse", "derive"} else "explicit")
def __repr__(self):
return "\n".join([" %s;"%s for s in self.tokens[1:]])
return "\n".join([" %s;" % s for s in self.tokens[1:]])
def __iter__(self):
return iter(self.tokens[1:])
def __len__(self):
return len(self.tokens[1:])
@@ -286,6 +313,7 @@ class InverseAttribute(Node):
bounds = property(lambda self: self.bound_spec[0] if self.bound_spec else None)
entity = property(lambda self: self.entity_ref[0])
attribute = property(lambda self: self.attribute_ref[0])
def __repr__(self):
def _():
yield self.name
@@ -298,8 +326,10 @@ class InverseAttribute(Node):
yield self.entity
yield "FOR"
yield self.attribute
return " ".join(map(str, _()))
"""
class DerivedAttribute(Node):
def init(self):
@@ -310,6 +340,7 @@ class DerivedAttribute(Node):
return str(self.name)
"""
class BinaryType(Node):
def __repr__(self):
return "binary"
@@ -320,32 +351,32 @@ class BoundSpecification(Node):
upper = property(lambda self: self.flat[3])
def __repr__(self):
return "[%s:%s]"%(self.lower, self.upper)
return "[%s:%s]" % (self.lower, self.upper)
class ExplicitAttribute(Node):
name = property(lambda self: self.attribute_decl.simple_id)
optional = property(lambda self: self.OPTIONAL is not None)
def get_type(self):
v = next(iter(self.parameter_type.tokens.values()))
if v.general_aggregation_types:
return v.general_aggregation_types
else:
return v
type = property(get_type)
def __repr__(self):
return "%s : %s%s" % (self.name, "optional " if self.optional else "", self.type)
class WidthSpec(Node):
fixed = property(lambda self: self.FIXED is not None)
def init(self):
self.width = int(''.join(self.width[0].flat))
self.width = int("".join(self.width[0].flat))
def __repr__(self):
return "(%d)%s" % (self.width, " fixed" if self.fixed else "")
@@ -23,13 +23,15 @@ import collections
if tuple(map(int, platform.python_version_tuple())) < (2, 7):
import ordereddict
collections.OrderedDict = ordereddict.OrderedDict
# According to ISO 10303-11 7.1.2: Letters: "... The case of
# According to ISO 10303-11 7.1.2: Letters: "... The case of
# letters is significant only within explicit string literals."
class OrderedCaseInsensitiveDict_KeyObject(str):
def __eq__(self, other):
return self.lower() == other.lower()
def __hash__(self):
return hash(self.lower())
@@ -39,53 +41,73 @@ class OrderedCaseInsensitiveDict(collections.OrderedDict):
collections.OrderedDict.__init__(self)
for key, value in collections.OrderedDict(*args, **kwargs).items():
self[OrderedCaseInsensitiveDict_KeyObject(key)] = value
def __setitem__(self, key, value):
return collections.OrderedDict.__setitem__(self, OrderedCaseInsensitiveDict_KeyObject(key), value)
def __getitem__(self, key):
return collections.OrderedDict.__getitem__(self, OrderedCaseInsensitiveDict_KeyObject(key))
def get(self, key, *args, **kwargs):
return collections.OrderedDict.get(self, OrderedCaseInsensitiveDict_KeyObject(key), *args, **kwargs)
def __contains__(self, key):
return collections.OrderedDict.__contains__(self, OrderedCaseInsensitiveDict_KeyObject(key))
def __delitem__(self, key):
return collections.OrderedDict.__delitem__(self, OrderedCaseInsensitiveDict_KeyObject(key))
class Schema:
def is_enumeration(self, v):
return str(v) in self.enumerations
def is_select(self, v):
return str(v) in self.selects
def is_simpletype(self, v):
return str(v) in self.simpletypes
def is_type(self, v):
return str(v) in self.types
def is_entity(self, v):
return str(v) in self.entities
def __len__(self):
return len(self.types) + len(self.entities)
def __iter__(self):
return iter(self.keys)
def __getitem__(self, key):
return self.types_entities[key]
def __init__(self, parsetree):
self.name = parsetree.syntax[0][0].simple_id
sort = lambda d: OrderedCaseInsensitiveDict(sorted(d))
declarations = [d.any()[0] for d in parsetree.syntax[0][0].schema_body[0] if d.rule == 'declaration' and d.any()[0].rule != 'function_decl']
self.types = sort([(t.name,t) for t in declarations if isinstance(t, nodes.TypeDeclaration)])
self.entities = sort([(t.name,t) for t in declarations if isinstance(t, nodes.EntityDeclaration)])
sort = lambda d: OrderedCaseInsensitiveDict(sorted(d))
declarations = [
d.any()[0]
for d in parsetree.syntax[0][0].schema_body[0]
if d.rule == "declaration" and d.any()[0].rule != "function_decl"
]
self.types = sort([(t.name, t) for t in declarations if isinstance(t, nodes.TypeDeclaration)])
self.entities = sort([(t.name, t) for t in declarations if isinstance(t, nodes.EntityDeclaration)])
self.keys = list(self.types.keys()) + list(self.entities.keys())
self.types_entities = {k: v for d in (self.types, self.entities) for k, v in d.items()}
of_type = lambda *types: sort([(a, b.type) for a,b in self.types.items() if any(isinstance(b.type, ty) for ty in types)])
of_type = lambda *types: sort(
[(a, b.type) for a, b in self.types.items() if any(isinstance(b.type, ty) for ty in types)]
)
self.enumerations = of_type(nodes.EnumerationType)
self.selects = of_type(nodes.SelectType)
self.simpletypes = of_type(str, nodes.AggregationType, nodes.BinaryType, nodes.StringType, nodes.SimpleType, nodes.NamedType)
self.simpletypes = of_type(
str, nodes.AggregationType, nodes.BinaryType, nodes.StringType, nodes.SimpleType, nodes.NamedType
)
assert len(self.enumerations) + len(self.selects) + len(self.simpletypes) == len(self.types)
@@ -27,109 +27,127 @@ from collections import defaultdict
import ifcopenshell.ifcopenshell_wrapper as w
class LateBoundSchemaInstantiator:
def __init__(self, schema_name):
self.schema_name = schema_name
self.schema_name_title = schema_name.capitalize()
self.schema_name_title = schema_name.capitalize()
self.declarations = {}
self.names = []
# We need to make sure anonymous types are not gc'ed.
self.cache = []
def aggregation_type(self, aggr_type, bound1, bound2, decl_type):
self.cache.append(w.aggregation_type(getattr(w.aggregation_type, aggr_type + "_type"), bound1, bound2, decl_type))
self.cache.append(
w.aggregation_type(getattr(w.aggregation_type, aggr_type + "_type"), bound1, bound2, decl_type)
)
return self.cache[-1]
def simple_type(self, type):
self.cache.append(w.simple_type(getattr(w.simple_type, type + "_type")))
return self.cache[-1]
def named_type(self, type):
self.cache.append(w.named_type(self.declarations[str(type)]))
return self.cache[-1]
def declare(self, definition_type, name):
self.names.append(str(name))
def begin_schema(self):
self.names.sort(key=str.lower)
def typedef(self, name, declared_type):
index_in_schema = self.names.index(str(name))
self.declarations[str(name)] = w.type_declaration(name, index_in_schema, declared_type)
def enumeration(self, name, enum):
schema_name = self.schema_name
index_in_schema = self.names.index(str(name))
self.declarations[str(name)] = w.enumeration_type(name, index_in_schema, sorted(enum.values))
def entity(self, name, type):
index_in_schema = self.names.index(str(name))
supertype = None if len(type.supertypes) == 0 else self.declarations[str(type.supertypes[0])]
self.declarations[str(name)] = w.entity(name, type.abstract, index_in_schema, supertype)
def select(self, name, type):
index_in_schema = self.names.index(str(name))
children = [self.declarations[str(v)] for v in type.values]
self.declarations[str(name)] = w.select_type(name, index_in_schema, children)
def entity_attributes(self, name, attribute_definitions, is_derived):
attributes = []
for attr_name, decl_type, optional in attribute_definitions:
attributes.append(w.attribute(attr_name, decl_type, optional))
self.declarations[str(name)].set_attributes(attributes, is_derived)
self.cache.append(attributes)
def inverse_attributes(self, name, inv_attrs):
attributes = []
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
en = self.declarations[str(entity_ref)]
attributes.append(w.inverse_attribute(attr_name, getattr(w.inverse_attribute, aggr_type + "_type"), bound1, bound2, en, en.attributes()[attribute_entity_index]))
attributes.append(
w.inverse_attribute(
attr_name,
getattr(w.inverse_attribute, aggr_type + "_type"),
bound1,
bound2,
en,
en.attributes()[attribute_entity_index],
)
)
self.declarations[str(name)].set_inverse_attributes(attributes)
def entity_subtypes(self, name, tys):
self.declarations[str(name)].set_subtypes([self.declarations[str(v)] for v in tys])
def finalize(self, can_be_instantiated_set, override_schema_name = None):
self.schema = w.schema_definition(override_schema_name or self.schema_name, list(self.declarations.values()), None)
def finalize(self, can_be_instantiated_set, override_schema_name=None):
self.schema = w.schema_definition(
override_schema_name or self.schema_name, list(self.declarations.values()), None
)
class EarlyBoundCodeWriter:
def __init__(self, schema_name):
self.schema_name = schema_name
self.schema_name_title = schema_name.capitalize()
self.statements = ['',
'#include "../ifcparse/IfcSchema.h"',
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
'',
'using namespace IfcParse;',
'']
self.statements = [
"",
'#include "../ifcparse/IfcSchema.h"',
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
"",
"using namespace IfcParse;",
"",
]
self.names = []
def aggregation_type(self, aggr_type, bound1, bound2, decl_type):
return "new aggregation_type(aggregation_type::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(decl_type)s)" % locals()
return (
"new aggregation_type(aggregation_type::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(decl_type)s)"
% locals()
)
def simple_type(self, type):
return "new simple_type(simple_type::%s_type)" % type
def named_type(self, type):
return "new named_type(%s_%s_type)" % (self.schema_name, type)
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)
self.statements.append("{factory_placeholder}")
self.statements.append("""
self.statements.append(
"""
#if defined(__clang__)
__attribute__((optnone))
#elif defined(__GNUC__) || defined(__GNUG__)
@@ -138,132 +156,182 @@ __attribute__((optnone))
#elif defined(_MSC_VER)
#pragma optimize("", off)
#endif
""")
self.statements.append('IfcParse::schema_definition* %s_populate_schema() {' % self.schema_name)
"""
)
self.statements.append("IfcParse::schema_definition* %s_populate_schema() {" % self.schema_name)
def typedef(self, name, declared_type):
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);' % locals())
self.statements.append(
' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
% locals()
)
def enumeration(self, name, enum):
schema_name = self.schema_name
index_in_schema = self.names.index(name)
self.statements.append(' {')
self.statements.append(' std::vector<std::string> items; items.reserve(%d);' % len(enum.values))
self.statements.append(" {")
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);' % locals())
self.statements.append(' }')
self.statements.append(
' %(schema_name)s_%(name)s_type = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
% locals()
)
self.statements.append(" }")
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_%s_type" % (self.schema_name, 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);' % locals())
self.statements.append(
' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, %(supertype)s);'
% locals()
)
def select(self, name, type):
schema_name = self.schema_name
index_in_schema = self.names.index(name)
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))))
self.statements.append(' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);' % locals())
self.statements.append(' }')
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)))
)
self.statements.append(
' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);'
% locals()
)
self.statements.append(" }")
def entity_attributes(self, name, attribute_definitions, is_derived):
schema_name = self.schema_name
self.statements.append(' {')
self.statements.append(' std::vector<const attribute*> attributes; attributes.reserve(%d);' % len(attribute_definitions))
self.statements.append(" {")
self.statements.append(
" std::vector<const attribute*> attributes; attributes.reserve(%d);" % len(attribute_definitions)
)
for attr_name, decl_type, optional in attribute_definitions:
optional_cpp = str(optional).lower()
self.statements.append(' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));' % locals())
self.statements.append(' std::vector<bool> derived; derived.reserve(%d);' % len(is_derived))
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(' }')
self.statements.append(
' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));'
% locals()
)
self.statements.append(" std::vector<bool> derived; derived.reserve(%d);" % len(is_derived))
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(" }")
def inverse_attributes(self, name, inv_attrs):
schema_name = self.schema_name
self.statements.append(' {')
self.statements.append(' std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);' % len(inv_attrs))
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:
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]));' % locals())
self.statements.append(' %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);' % locals())
self.statements.append(' }')
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]));'
% locals()
)
self.statements.append(" %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);" % locals())
self.statements.append(" }")
def entity_subtypes(self, name, tys):
schema_name = self.schema_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())
self.statements.append(' %(schema_name)s_%(name)s_type->set_subtypes(defs);' % locals())
self.statements.append(' }')
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()
)
self.statements.append(" %(schema_name)s_%(name)s_type->set_subtypes(defs);" % locals())
self.statements.append(" }")
def finalize(self, can_be_instantiated_set):
schema_name = self.schema_name
schema_name_title = self.schema_name.capitalize()
num_declarations = len(self.names)
self.statements.append('')
self.statements.append(' std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);' % locals())
self.statements.append("")
self.statements.append(
" 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())
self.statements.append(' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());' % locals())
self.statements.extend(('}',''))
self.statements.append("""
self.statements.append(" declarations.push_back(%(schema_name)s_%(type_name)s_type);" % locals())
self.statements.append(
' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());'
% locals()
)
self.statements.extend(("}", ""))
self.statements.append(
"""
#if defined(__clang__)
#elif defined(__GNUC__) || defined(__GNUG__)
#pragma GCC pop_options
#elif defined(_MSC_VER)
#pragma optimize("", on)
#endif
""")
self.statements.extend(('const schema_definition& %s::get_schema() {' % schema_name_title,
'',
' static const schema_definition* s = %(schema_name)s_populate_schema();' % locals(),
' return *s;',
'}','',''))
"""
)
self.statements.extend(
(
"const schema_definition& %s::get_schema() {" % schema_name_title,
"",
" static const schema_definition* s = %(schema_name)s_populate_schema();" % locals(),
" return *s;",
"}",
"",
"",
)
)
def can_be_instantiated(idx_name):
name = idx_name[1]
return name in can_be_instantiated_set
instance_mapping = """switch(data->type()->index_in_schema()) {
%s
default: throw IfcParse::IfcException(data->type()->name() + " cannot be instantiated");
}
""" % "\n ".join(map(lambda tup: ("case %%d: return new ::%s::%%s(data);" % schema_name_title) % tup, filter(can_be_instantiated, enumerate(self.names))))
""" % "\n ".join(
map(
lambda tup: ("case %%d: return new ::%s::%%s(data);" % schema_name_title) % tup,
filter(can_be_instantiated, enumerate(self.names)),
)
)
self.statements[self.statements.index("{factory_placeholder}")] = """
self.statements[self.statements.index("{factory_placeholder}")] = (
"""
class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const {
%(instance_mapping)s
}
};
""" % locals()
"""
% locals()
)
def __str__(self):
return "\n".join(self.statements)
return "\n".join(self.statements)
class SchemaClass(codegen.Base):
def __init__(self, mapping, code=EarlyBoundCodeWriter):
class UnmetDependenciesException(Exception): pass
class UnmetDependenciesException(Exception):
pass
schema_name = mapping.schema.name
self.schema_name = schema_name_title = schema_name.capitalize()
declared_types = []
x = code(schema_name)
def get_declared_type(type, emitted_names=None):
if isinstance(type, nodes.SimpleType):
type = type.type
@@ -272,7 +340,7 @@ class SchemaClass(codegen.Base):
if isinstance(type, nodes.AggregationType):
aggr_type = type.aggregate_type
make_bound = lambda b: -1 if b == '?' else int(b)
make_bound = lambda b: -1 if b == "?" else int(b)
bound1, bound2 = map(make_bound, (type.bounds.lower, type.bounds.upper))
decl_type = get_declared_type(type.type, emitted_names)
return x.aggregation_type(aggr_type, bound1, bound2, decl_type)
@@ -295,38 +363,41 @@ class SchemaClass(codegen.Base):
attributes_per_subtype = []
while True:
entity = mapping.schema.entities[entity_name]
attr_names = list(map(operator.attrgetter('name'), entity.attributes))
attr_names = list(map(operator.attrgetter("name"), entity.attributes))
if len(attr_names):
attributes_per_subtype.append((entity_name, attr_names))
if len(entity.supertypes) != 1: break
if len(entity.supertypes) != 1:
break
entity_name = entity.supertypes[0]
index = 0
for et, attrs in attributes_per_subtype[::-1]:
try: return et, attrs.index(attribute_name)
except: pass
try:
return et, attrs.index(attribute_name)
except:
pass
else:
raise Exception("No declared type for <%r>" % type)
collections_by_type = (('entity', mapping.schema.entities ),
('type_declaration', mapping.schema.simpletypes ),
('select_type', mapping.schema.selects ),
('enumeration_type', mapping.schema.enumerations))
collections_by_type = (
("entity", mapping.schema.entities),
("type_declaration", mapping.schema.simpletypes),
("select_type", mapping.schema.selects),
("enumeration_type", mapping.schema.enumerations),
)
for definition_type, collection in collections_by_type:
for name in collection.keys():
x.declare(definition_type, name)
declarations_by_index = []
x.begin_schema()
emitted = set()
len_to_emit = len(mapping.schema)
def write_simpletype(schema_name, name, type):
def write_simpletype(schema_name, name, type):
try:
declared_type = get_declared_type(type, emitted)
except UnmetDependenciesException:
@@ -335,20 +406,22 @@ class SchemaClass(codegen.Base):
return False
x.typedef(name, declared_type)
def write_enumeration(schema_name, name, enum):
x.enumeration(name, enum)
def write_entity(schema_name, name, type):
if len(type.supertypes) == 0 or set(map(lambda s: s.lower(), type.supertypes)) < emitted:
x.entity(name, type)
else: return False
else:
return False
def write_select(schema_name, name, type):
if set(map(lambda s: str(s).lower(), type.values)) < emitted:
x.select(name, type)
else: return False
else:
return False
def write(name):
if mapping.schema.is_simpletype(name):
fn = write_simpletype
@@ -358,64 +431,69 @@ class SchemaClass(codegen.Base):
fn = write_entity
elif mapping.schema.is_select(name):
fn = write_select
decl = mapping.schema[name]
if isinstance(decl, nodes.TypeDeclaration):
decl = decl.type
return fn(schema_name, name, decl) is not False
while len(emitted) < len_to_emit:
for name in mapping.schema:
if name.lower() in emitted: continue
if name.lower() in emitted:
continue
if write(name):
emitted.add(name.lower())
declarations_by_index.append(name)
declared_types.append('%(schema_name)s_%(name)s_type' % locals())
declared_types.append("%(schema_name)s_%(name)s_type" % locals())
num_declarations = len(declared_types)
for name, type in mapping.schema.entities.items():
derived = set(mapping.derived_in_supertype(type))
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
attribute_names = list(map(operator.attrgetter("name"), mapping.arguments(type)))
is_derived = [b in derived for b in attribute_names]
attribute_definitions = []
for attr in type.attributes:
decl_type = get_declared_type(attr.type)
attribute_definitions.append((attr.name, decl_type, attr.optional))
x.entity_attributes(name, attribute_definitions, is_derived)
for name, type in mapping.schema.entities.items():
if type.inverse:
inv_attrs = []
for attr in type.inverse:
if attr.bounds:
make_bound = lambda b: -1 if b == '?' else int(b)
make_bound = lambda b: -1 if b == "?" else int(b)
bound1, bound2 = map(make_bound, (attr.bounds.lower, attr.bounds.upper))
else:
bound1, bound2 = -1, -1
attr_name, aggr_type, entity_ref = attr.name, attr.type, attr.entity
if aggr_type is None: aggr_type = 'unspecified'
if aggr_type is None:
aggr_type = "unspecified"
attribute_entity, attribute_entity_index = find_inverse_name_and_index(entity_ref, attr.attribute)
inv_attrs.append((attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index))
inv_attrs.append(
(attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index)
)
x.inverse_attributes(name, inv_attrs)
subtypes = defaultdict(list)
for name, type in mapping.schema.entities.items():
for ty in type.supertypes:
subtypes[ty].append(name)
for name, tys in subtypes.items():
x.entity_subtypes(name, tys)
can_be_instantiated_set = set(list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys()))
x.finalize(can_be_instantiated_set)
self.str = str(x)
self.file_name = '%s-schema.cpp' % self.schema_name
self.file_name = "%s-schema.cpp" % self.schema_name
self.code = x
def __repr__(self):
return self.str
Generator = SchemaClass
@@ -65,7 +65,7 @@ enum_header = """
lb_header = """"""
implementation= """
implementation = """
#include "../ifcparse/%(schema_name)s.h"
#include "../ifcparse/IfcSchema.h"
#include "../ifcparse/IfcException.h"
@@ -103,8 +103,8 @@ enumeration_descriptor = """ values.clear(); values.reserve(128);
enumeration_descriptor_value = ' values.push_back("%(name)s");'
derived_field_statement = ' {std::set<int> idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}';
derived_field_statement_attrs = 'idxs.insert(%d); '
derived_field_statement = " {std::set<int> idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}"
derived_field_statement_attrs = "idxs.insert(%d); "
simpletype = """%(documentation)s
class IFC_PARSE_API %(name)s : public %(superclass)s {
@@ -118,19 +118,24 @@ public:
"""
simpletype_impl_comment = "// Function implementations for %(name)s"
simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException(\"Argument index out of range\"); }"
simpletype_impl_argument_type = 'if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); }'
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_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_->setArgument(0, attr);}"
simpletype_impl_constructor = (
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {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_cast = "return *data_->getArgument(0);"
simpletype_impl_cast_templated = "IfcEntityList::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
simpletype_impl_cast_templated = (
"IfcEntityList::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
)
simpletype_impl_declaration = "return *%(schema_name_upper)s_%(class_name)s_type;"
select = """%(documentation)s
typedef IfcUtil::IfcBaseClass %(name)s;
"""
@@ -154,7 +159,7 @@ public:
};
"""
enumeration_function="""
enumeration_function = """
const char* %(schema_name)s::%(name)s::ToString(Value v) {
if ( v < 0 || v >= %(max_id)d ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { %(values)s };
@@ -181,7 +186,9 @@ optional_attribute_description = "/// Whether the optional attribute %s is defin
function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) { %(body)s }"
const_function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) const { %(body)s }"
constructor = "%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) { %(body)s }"
constructor_single_initlist = "%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }"
constructor_single_initlist = (
"%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }"
)
cast_function = "%(schema_name)s::%(class_name)s::operator %(return_type)s() const { %(body)s }"
array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/"
@@ -193,9 +200,9 @@ inverse_attr = "IfcTemplatedEntityList< %(entity)s >::ptr %(name)s() const; // I
enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;'
schema_entity_stmt = ' case Type::%(name)s: return new %(name)s(e); break;'
schema_entity_stmt = " case Type::%(name)s: return new %(name)s(e); break;"
string_map_statement = ' string_map["%(uppercase_name)s"%(padding)s] = Type::%(name)s;'
parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }'
parent_type_stmt = " if(v==%(name)s%(padding)s) { return %(parent)s; }"
parent_type_test = " || %s::is(v)"
@@ -204,24 +211,46 @@ optional_attr_stmt = "return !data_->getArgument(%(index)d)->isNull();"
get_attr_stmt = "return *data_->getArgument(%(index)d);"
get_attr_stmt_enum = "return %(type)s::FromString(*data_->getArgument(%(index)d));"
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*data_->getArgument(%(index)d)));"
get_attr_stmt_array = "IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
get_attr_stmt_array = (
"IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
)
get_attr_stmt_nested_array = (
"IfcEntityListList::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>();"
set_attr_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v" +");data_->setArgument(%(index)d,attr);}"
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));data_->setArgument(%(index)d,attr);}"
set_attr_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()" +");data_->setArgument(%(index)d,attr);}"
set_attr_stmt = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v"
+ ");data_->setArgument(%(index)d,attr);}"
)
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));data_->setArgument(%(index)d,attr);}"
set_attr_stmt_array = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()"
+ ");data_->setArgument(%(index)d,attr);}"
)
constructor_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)" +");data_->setArgument(%(index)d,attr);}"
constructor_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))" +");data_->setArgument(%(index)d,attr);}"
constructor_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()" +");data_->setArgument(%(index)d,attr);}"
constructor_stmt_derived = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()" +");data_->setArgument(%(index)d,attr);}"
constructor_stmt = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)"
+ ");data_->setArgument(%(index)d,attr);}"
)
constructor_stmt_enum = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))"
+ ");data_->setArgument(%(index)d,attr);}"
)
constructor_stmt_array = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()"
+ ");data_->setArgument(%(index)d,attr);}"
)
constructor_stmt_derived = (
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()"
+ ");data_->setArgument(%(index)d,attr);}"
)
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(%(index)d, attr); }"
inverse_implementation = " inverse_map[Type::%(type)s].insert(std::make_pair(\"%(name)s\", std::make_pair(Type::%(related_type)s, %(index)d)));"
inverse_implementation = ' inverse_map[Type::%(type)s].insert(std::make_pair("%(name)s", std::make_pair(Type::%(related_type)s, %(index)d)));'
def multi_line_comment(li):
return ("/// %s"%("\n/// ".join(li))) if len(li) else ""
return ("/// %s" % ("\n/// ".join(li))) if len(li) else ""