diff --git a/src/ifcopenshell-python/ifcopenshell/express/header.py b/src/ifcopenshell-python/ifcopenshell/express/header.py index 6541aae3e9..cc403c8f70 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/header.py +++ b/src/ifcopenshell-python/ifcopenshell/express/header.py @@ -77,13 +77,10 @@ class Header(codegen.Base): 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)))] ) - type_str = mapping.get_parameter_type(attr, allow_optional=False, allow_entities=False) + type_str = mapping.get_parameter_type(attr) 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)) diff --git a/src/ifcopenshell-python/ifcopenshell/express/implementation.py b/src/ifcopenshell-python/ifcopenshell/express/implementation.py index e4f2522883..a27cb1aa21 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/implementation.py +++ b/src/ifcopenshell-python/ifcopenshell/express/implementation.py @@ -74,17 +74,6 @@ class Implementation(codegen.Base): 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"]: - 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}, - ) def find_template(arg): simple = mapping.schema.is_simpletype(arg["list_instance_type"]) @@ -111,11 +100,12 @@ class Implementation(codegen.Base): arguments="", schema_name=schema_name, schema_name_upper=schema_name_upper, - return_type=arg["non_optional_type"], + return_type=arg["full_type"], body=tmpl % { "index": arg["index"] - 1, - "type": arg["non_optional_type"].replace("::Value", ""), + "type": arg["full_type"].replace("::Value", ""), + "non_optional_type": arg["non_optional_type"].replace("::Value", ""), "list_instance_type": arg["list_instance_type"], }, ) @@ -136,12 +126,17 @@ class Implementation(codegen.Base): templates.function, class_name=name, name="set%s" % arg["name"], - arguments="%s v" % arg["non_optional_type"], + arguments="%s v" % arg["full_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", "")}, + % { + "index": arg["index"] - 1, + "type": arg["full_type"].replace("::Value", ""), + "non_optional_type": arg["non_optional_type"].replace("::Value", ""), + "star_if_optional": "*" if arg["is_optional"] else "" + }, ) if arg["is_derived"]: diff --git a/src/ifcopenshell-python/ifcopenshell/express/mapping.py b/src/ifcopenshell-python/ifcopenshell/express/mapping.py index 0c05413a2c..0a6814a652 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/mapping.py +++ b/src/ifcopenshell-python/ifcopenshell/express/mapping.py @@ -28,7 +28,7 @@ class Mapping: express_to_cpp_typemapping = { "boolean": "bool", - "logical": "bool", + "logical": "boost::logic::tribool", "integer": "int", "real": "double", "number": "double", @@ -40,6 +40,7 @@ class Mapping: [ "INT", "BOOL", + "LOGICAL", "DOUBLE", "STRING", "BINARY", @@ -141,7 +142,10 @@ class Mapping: raise ValueError("Unable to map type %r for attribute %r" % (type, attr)) ty = _make_argument_type(attr.type if hasattr(attr, "type") else attr) + if ty == "TRIBOOL": ty = "LOGICAL" + if ty not in self.supported_argument_types: + import pdb; pdb.set_trace() print("Attribute %r mapped as 'unknown'" % (attr), file=sys.stderr) ty = "UNKNOWN" return "IfcUtil::Argument_%s" % ty @@ -152,7 +156,7 @@ 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=True): attr_type = self.flatten_type(attr.type) if (isinstance(attr_type, nodes.SimpleType) and isinstance(attr_type.type, nodes.StringType)) or isinstance( @@ -168,7 +172,7 @@ class Mapping: 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) + ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type) if self.schema.is_select(attr_type.type): type_str = templates.untyped_list elif self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values(): @@ -179,14 +183,10 @@ class Mapping: 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) - if allow_pointer: - type_str += "*" - is_ptr = True - elif not allow_pointer and self.schema.is_select(type_str): - type_str = "IfcUtil::IfcBaseClass*" + type_str = "::%s::%s*" % (self.schema.name.capitalize(), attr_type) is_ptr = True if allow_optional and attr.optional and not is_ptr: + # pointers are still handled with nullptr for the time being type_str = "boost::optional< %s >" % type_str return type_str @@ -262,9 +262,9 @@ class Mapping: { "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), + "full_type": self.get_parameter_type(attr), + "specialized_type": self.get_parameter_type(attr), + "non_optional_type": self.get_parameter_type(attr, allow_optional=False), "list_instance_type": self.list_instance_type(attr), "is_optional": attr.optional, "is_inherited": i < num_inherited, diff --git a/src/ifcopenshell-python/ifcopenshell/express/templates.py b/src/ifcopenshell-python/ifcopenshell/express/templates.py index 4341c7957b..c326bd17f7 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/templates.py +++ b/src/ifcopenshell-python/ifcopenshell/express/templates.py @@ -239,9 +239,9 @@ parent_type_test = " || %s::is(v)" 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 = "return (%(non_optional_type)s) *data_->getArgument(%(index)d);" +get_attr_stmt_enum = "return %(non_optional_type)s::FromString(*data_->getArgument(%(index)d));" +get_attr_stmt_entity = "return (%(non_optional_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 >();" ) @@ -255,7 +255,7 @@ 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_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(%(star_if_optional)sv,%(non_optional_type)s::ToString(%(star_if_optional)sv)));data_->setArgument(%(index)d,attr);}" set_attr_stmt_array = ( "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()" + ");data_->setArgument(%(index)d,attr);}" diff --git a/src/ifcparse/Argument.h b/src/ifcparse/Argument.h index 864a991373..7ced5b6f97 100644 --- a/src/ifcparse/Argument.h +++ b/src/ifcparse/Argument.h @@ -32,6 +32,7 @@ #include #include +#include class Argument; class IfcEntityList; @@ -54,6 +55,7 @@ public: virtual operator int() const; virtual operator bool() const; virtual operator double() const; + virtual operator boost::logic::tribool() const; virtual operator std::string() const; virtual operator boost::dynamic_bitset<>() const; virtual operator IfcUtil::IfcBaseClass*() const; diff --git a/src/ifcparse/ArgumentType.h b/src/ifcparse/ArgumentType.h index c56a2d257e..91c89f05c4 100644 --- a/src/ifcparse/ArgumentType.h +++ b/src/ifcparse/ArgumentType.h @@ -29,6 +29,7 @@ namespace IfcUtil { Argument_DERIVED, Argument_INT, Argument_BOOL, + Argument_LOGICAL, Argument_DOUBLE, Argument_STRING, Argument_BINARY,