diff --git a/misc/codegen/generators/cppgen.py b/misc/codegen/generators/cppgen.py index f6a7f8d792c..1cd6cc36450 100644 --- a/misc/codegen/generators/cppgen.py +++ b/misc/codegen/generators/cppgen.py @@ -49,6 +49,7 @@ def _get_field(cls: schema.Class, p: schema.Property, add_or_none_except: typing is_optional=p.is_optional, is_repeated=p.is_repeated, is_predicate=p.is_predicate, + is_unordered=p.is_unordered, trap_name=trap_name, ) args.update(cpp.get_field_override(p.name)) diff --git a/misc/codegen/lib/cpp.py b/misc/codegen/lib/cpp.py index 9ca2d8e2ebc..eed7aba045c 100644 --- a/misc/codegen/lib/cpp.py +++ b/misc/codegen/lib/cpp.py @@ -36,6 +36,7 @@ class Field: base_type: str is_optional: bool = False is_repeated: bool = False + is_unordered: bool = False is_predicate: bool = False trap_name: str = None first: bool = False diff --git a/misc/codegen/templates/cpp_classes_cpp.mustache b/misc/codegen/templates/cpp_classes_cpp.mustache index d78c89fc3c7..725fc10c6ef 100644 --- a/misc/codegen/templates/cpp_classes_cpp.mustache +++ b/misc/codegen/templates/cpp_classes_cpp.mustache @@ -24,7 +24,7 @@ void {{name}}::emit({{^final}}TrapLabel<{{name}}Tag> id, {{/final}}std::ostream& {{#is_repeated}} for (auto i = 0u; i < {{field_name}}.size(); ++i) { {{^is_optional}} - out << {{trap_name}}Trap{id, i, {{field_name}}[i]} << '\n'; + out << {{trap_name}}Trap{id, {{^is_unordered}}i, {{/is_unordered}}{{field_name}}[i]} << '\n'; {{/is_optional}} {{#is_optional}} if ({{field_name}}[i]) out << {{trap_name}}Trap{id, i, *{{field_name}}[i]} << '\n'; diff --git a/misc/codegen/test/test_cppgen.py b/misc/codegen/test/test_cppgen.py index 278f184fcbc..840a163995c 100644 --- a/misc/codegen/test/test_cppgen.py +++ b/misc/codegen/test/test_cppgen.py @@ -41,8 +41,8 @@ def test_empty_class(generate): assert generate([ schema.Class(name="MyClass"), ]) == [ - cpp.Class(name="MyClass", final=True, trap_name="MyClasses") - ] + cpp.Class(name="MyClass", final=True, trap_name="MyClasses") + ] def test_two_class_hierarchy(generate): @@ -51,9 +51,9 @@ def test_two_class_hierarchy(generate): schema.Class(name="A", derived={"B"}), schema.Class(name="B", bases=["A"]), ]) == [ - base, - cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), - ] + base, + cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), + ] @pytest.mark.parametrize("type,expected", [ @@ -62,22 +62,23 @@ def test_two_class_hierarchy(generate): ("boolean", "bool"), ("MyClass", "TrapLabel"), ]) -@pytest.mark.parametrize("property_cls,optional,repeated,trap_name", [ - (schema.SingleProperty, False, False, None), - (schema.OptionalProperty, True, False, "MyClassProps"), - (schema.RepeatedProperty, False, True, "MyClassProps"), - (schema.RepeatedOptionalProperty, True, True, "MyClassProps"), +@pytest.mark.parametrize("property_cls,optional,repeated,unordered,trap_name", [ + (schema.SingleProperty, False, False, False, None), + (schema.OptionalProperty, True, False, False, "MyClassProps"), + (schema.RepeatedProperty, False, True, False, "MyClassProps"), + (schema.RepeatedOptionalProperty, True, True, False, "MyClassProps"), + (schema.RepeatedUnorderedProperty, False, True, True, "MyClassProps"), ]) -def test_class_with_field(generate, type, expected, property_cls, optional, repeated, trap_name): +def test_class_with_field(generate, type, expected, property_cls, optional, repeated, unordered, trap_name): assert generate([ schema.Class(name="MyClass", properties=[property_cls("prop", type)]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("prop", expected, is_optional=optional, - is_repeated=repeated, trap_name=trap_name)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("prop", expected, is_optional=optional, + is_repeated=repeated, is_unordered=unordered, trap_name=trap_name)], + trap_name="MyClasses", + final=True) + ] def test_class_field_with_null(generate, input): @@ -90,13 +91,13 @@ def test_class_field_with_null(generate, input): schema.SingleProperty("y", "B"), ]) ]) == [ - a, - cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", - fields=[ - cpp.Field("x", "TrapLabel"), - cpp.Field("y", "TrapLabel"), - ]), - ] + a, + cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", + fields=[ + cpp.Field("x", "TrapLabel"), + cpp.Field("y", "TrapLabel"), + ]), + ] def test_class_with_predicate(generate): @@ -104,12 +105,12 @@ def test_class_with_predicate(generate): schema.Class(name="MyClass", properties=[ schema.PredicateProperty("prop")]), ]) == [ - cpp.Class(name="MyClass", - fields=[ - cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[ + cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", @@ -119,11 +120,11 @@ def test_class_with_overridden_unsigned_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name, "unsigned")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name, "unsigned")], + trap_name="MyClasses", + final=True) + ] def test_class_with_overridden_underscore_field(generate): @@ -131,11 +132,11 @@ def test_class_with_overridden_underscore_field(generate): schema.Class(name="MyClass", properties=[ schema.SingleProperty("something_", "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("something", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("something", "bar")], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", cpp.cpp_keywords) @@ -144,11 +145,11 @@ def test_class_with_keyword_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name + "_", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name + "_", "bar")], + trap_name="MyClasses", + final=True) + ] def test_classes_with_dirs(generate_grouped): @@ -160,11 +161,11 @@ def test_classes_with_dirs(generate_grouped): schema.Class(name="C", bases=["CBase"], group="bar"), schema.Class(name="D", group="foo/bar/baz"), ]) == { - ".": [cpp.Class(name="A", trap_name="As", final=True)], - "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], - "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], - "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], - } + ".": [cpp.Class(name="A", trap_name="As", final=True)], + "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], + "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], + "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], + } def test_cpp_skip_pragma(generate): @@ -174,10 +175,10 @@ def test_cpp_skip_pragma(generate): schema.SingleProperty("y", "bar", pragmas=["x", "cpp_skip", "y"]), ]) ]) == [ - cpp.Class(name="A", final=True, trap_name="As", fields=[ - cpp.Field("x", "foo"), - ]), - ] + cpp.Class(name="A", final=True, trap_name="As", fields=[ + cpp.Field("x", "foo"), + ]), + ] def test_ipa_classes_ignored(generate): @@ -198,8 +199,8 @@ def test_ipa_classes_ignored(generate): name="Z", ), ]) == [ - cpp.Class(name="Z", final=True, trap_name="Zs"), - ] + cpp.Class(name="Z", final=True, trap_name="Zs"), + ] if __name__ == '__main__':