def test_archive_member_schemas_references_dependent_types(): root = _build_node_tree("""namespace n{ struct T { t : u8 : 7; } struct U { u : u8 : 7; } struct V { v : u8 : 7; } archive A { a : T; b : vector< V >; c : multivector< 17, U, V >; } } """) resolve_references(root) assert_equal( SyntaxTree.schema(root.find(".n.A.a")), "namespace n { struct T { t : u8 : 7; } }\n" "namespace n { a : T; }") assert_equal( SyntaxTree.schema(root.find(".n.A.b")), "namespace n { struct V { v : u8 : 7; } }\n" "namespace n { b : vector< V >; }") assert_equal( SyntaxTree.schema(root.find(".n.A.c")), "namespace n { struct U { u : u8 : 7; } }\n" "namespace n { struct V { v : u8 : 7; } }\n" "namespace n { c : multivector< 17, U, V >; }")
def test_schemas_are_not_duplicated_if_several_type_references_occur(): root = _build_node_tree("""namespace foo{ /// T Comment struct T { /* fieldA comment*/ fieldA : u8 : 7; } /** * Archive comment */ archive A { resourceA : T; resourceB : T; } } """) resolve_references(root) expected = """namespace foo { struct T { fieldA : u8 : 7; } } namespace foo { archive A { resourceA : .foo.T; resourceB : .foo.T; } } """ actual = SyntaxTree.schema(root.find(".foo.A")) assert_equal(actual, expected)
def test_archive_schemas_include_constants(): root = build_ast("""namespace foo{ const u8 C = 42; struct T { f : u8 : 7; } archive A { resourceA : T; } } """) resolve_references(root) expected = """namespace foo { struct T { f : u8 : 7; } } namespace foo { const u8 C = 42; } namespace foo { archive A { resourceA : .foo.T; } } """ actual = SyntaxTree.schema(root.find(".foo.A")) assert_equal(actual, expected)
def test_archive_schema_preserves_references(): root = _build_node_tree("""namespace foo{ /// T Comment struct T { /* fieldA comment*/ fieldA : u8 : 7; } /** * Archive comment */ archive A { /// resource comment resourceA : T; } } """) resolve_references(root) expected = """namespace foo { struct T { fieldA : u8 : 7; } } namespace foo { archive A { resourceA : .foo.T; } } """ assert_equal(SyntaxTree.schema(root.find(".foo.A")), expected)
def create_tree_with_topological_ordering(): return SyntaxTree( Node("ns").insert( Node("S0"), Node("A0").insert( Node("R0").insert(refs.TypeReference("ns.A1")), Node("R1").insert(refs.TypeReference("ns.S0"))), Node("A1")))
def _create_tree_resource_to_archive(): root = Root().insert( nodes.Namespace(name="ns").insert( Archive(name="RefArchive"), Archive(name="Archive").insert( res.Archive(name="resource").insert( refs.ArchiveReference(name="RefArchive"))))) return SyntaxTree(root)
def _create_tree_resource_to_struct_with_extra_folding(actual, reference): root = Root().insert( nodes.Namespace(name="ns").insert( nodes.Namespace(name="fold").insert(nodes.Structure(name=actual)), Archive(name="Archive").insert( res.Vector(name="resource").insert( refs.StructureReference(name=reference))))) return SyntaxTree(root)
def _create_tree_with_two_struct_references(): root = Root().insert( nodes.Namespace(name="ns").insert( nodes.Structure(name="S1"), nodes.Structure(name="S2"), Archive(name="Archive").insert( res.Multivector(name="resource").insert( refs.StructureReference(name="S1"), refs.StructureReference(name="S2"))))) return SyntaxTree(root)
def build(definition): root = _build_node_tree(definition=definition) _append_builtin_structures(root) _append_constant_references(root) resolve_references(root) #now compute data based on resolved references _update_field_type_references(root) _compute_structure_sizes(root) return SyntaxTree(root)
def build_ast(definition): """Build the Flatdata syntax tree from a definition""" root = _build_node_tree(definition=definition) _append_builtin_structures(root) _append_constant_references(root) resolve_references(root) # now compute data based on resolved references _update_field_type_references(root) _compute_structure_sizes(root) return SyntaxTree(root)
def _create_tree_with_explicit_reference(name): root = Root().insert( nodes.Namespace(name="ns").insert( nodes.Structure(name="Struct").insert(nodes.Field(name="Field")), Archive(name="Archive").insert( res.Vector(name="resource").insert( refs.FieldReference(name="Struct.Field"), refs.ResourceReference(name=name)), res.Vector(name="resource2")))) return SyntaxTree(root)
def render(self, tree): env = Environment(loader=PackageLoader('generator', 'templates'), lstrip_blocks=True, trim_blocks=True, autoescape=False, extensions=[RaiseExtension]) env.filters['is_archive'] = lambda n: isinstance(n, Archive) env.filters['is_instance'] = lambda n: isinstance(n, Instance) env.filters['is_raw_data'] = lambda n: isinstance(n, RawData) env.filters['is_archive_resource'] = lambda n: isinstance(n, ArchiveResource) env.filters['is_structure'] = lambda n: isinstance(n, Structure) env.filters['is_enumeration'] = lambda n: isinstance(n, Enumeration) env.filters['is_constant'] = lambda n: isinstance(n, Constant) env.filters['is_namespace'] = lambda n: isinstance(n, Namespace) env.filters['is_resource'] = lambda n: isinstance(n, ResourceBase) env.filters['is_bound_resource'] = lambda n: isinstance(n, BoundResource) env.filters['is_vector'] = lambda n: isinstance(n, Vector) env.filters['is_multivector'] = lambda n: isinstance(n, Multivector) env.filters['is_multivector_index'] = lambda n: (isinstance(n, Structure) and "_builtin.multivector" in SyntaxTree.namespace_path(n)) env.filters['namespaces'] = SyntaxTree.namespaces self._populate_environment(env) template = env.get_template(self._template) nodes = [n for n, _ in DfsTraversal(tree).dependency_order() if any([isinstance(n, t) for t in self._supported_nodes()])] return template.render(nodes=nodes, tree=tree)
def create_tree_with_cycle(): return SyntaxTree( Node("a").insert( Node("b").insert(Structure("c").insert(refs.TypeReference("a.d"))), Node("d").insert(refs.TypeReference("a.b"))))
def create_tree_with_type_refs(): return SyntaxTree( Node("a").insert( Node("b").insert(Node("d"), refs.TypeReference("a.c.e")), Node("c").insert(Node("e"), refs.TypeReference("a.b.d"))))
def create_basic_tree(): return SyntaxTree( Node("a").insert( Node("b").insert(Node("c"), Node("d"), Node("e")), Node("f").insert(Node("g").insert(Node("h")))))
def _is_builtin(node): for x in SyntaxTree.namespaces(node): if x.name == "_builtin": return True return False
def build(definition): root = _build_node_tree(definition=definition) _append_builtin_structures(root) _append_constant_references(root) resolve_references(root) return SyntaxTree(root)
def _populate_environment(self, env): def _camel_to_snake_case(expr): step1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', expr) return re.sub('([a-z0-9])(A-Z)', r'\1_\2', step1).lower() env.filters["camel_to_snake_case"] = _camel_to_snake_case def _snake_to_upper_camel_case(expr): return ''.join(p.title() for p in expr.split('_')) env.filters["snake_to_upper_camel_case"] = _snake_to_upper_camel_case def _rust_doc(expr): lines = [ re.sub(r'^[ \t]*(/\*\*|/\*|\*/|\*)\s*(.*?)\s*(\*/)?$', r"/// \2", line).strip() for line in expr.split('\n') ] start = 0 end = len(lines) if lines[0] == "///": start = 1 if lines[-1] == "///": end = -1 return "\n".join(lines[start:end]) env.filters["rust_doc"] = _rust_doc def _escape_rust_keywords(expr): if expr in self.RESERVED_KEYWORDS: return "{}_".format(expr) return expr def _field_type(field): if isinstance(field.type, EnumType): return "{}, {}".format( _fully_qualified_name(field.parent, field.type_reference.node), field.type_reference.node.type.name) return "{}, {}".format(field.type.name, field.type.name) def _fully_qualified_name(current, node): return "::".join( (current.path_depth() - 1) * ["super"]) + node.path_with("::") env.globals["fully_qualified_name"] = _fully_qualified_name env.filters["escape_rust_keywords"] = _escape_rust_keywords env.filters["field_type"] = _field_type env.filters['structure_references'] = lambda ls: [ x for x in ls if (isinstance(x.node, Structure) and "_builtin.multivector" not in SyntaxTree.namespace_path(x.node)) ] env.filters['instance_resources'] = lambda ls: [ x for x in ls if isinstance(x, Instance) ] env.filters['vector_resources'] = lambda ls: [ x for x in ls if isinstance(x, Vector) ] env.filters['multivector_resources'] = lambda ls: [ x for x in ls if isinstance(x, Multivector) ] env.filters['rawdata_resources'] = lambda ls: [ x for x in ls if isinstance(x, RawData) ] env.filters['subarchive_resources'] = lambda ls: [ x for x in ls if isinstance(x, ArchiveResource) ] env.filters["supported_resources"] = lambda l: [ x for x in l if not isinstance(x, BoundResource) ] env.filters[ "format_numeric_literal"] = RustGenerator._format_numeric_literal