{! root_node_name = root_node.name def gen_cpp_unref(expr, ty): if isinstance(ty, NodeType): return f'{expr}->unref();\n' elif isinstance(ty, ListType): dtor = gen_cpp_unref('Element', ty.element_type) if dtor: out = '' out += f'for (auto& Element: {expr})' out += '{\n' out += dtor out += '}\n' return out elif isinstance(ty, OptionalType): if is_type_optional_by_default(ty.element_type): element_expr = expr else: element_expr = f'(*{expr})' dtor = gen_cpp_unref(element_expr, ty.element_type) if dtor: out = '' out += 'if (' out += expr out += ') {\n' out += dtor out += '}\n' return out elif isinstance(ty, RawType): pass # field should be destroyed by class else: raise RuntimeError(f'unexpected {ty}') !} #include "{{include_path}}/{{name}}.hpp" {% for namespace in namespaces %} namespace {{namespace}} { {! indent() !} {% endfor %} {{root_node_name}}:~{{root_node_name}}() {} SourceFile* {root_node.name}::getSourceFile() { auto CurrNode = this; for (;;) { if (CurrNode->Type == NodeType::SourceFile) { return static_cast(this); } CurrNode = CurrNode->Parent; ZEN_ASSERT(CurrNode != nullptr); } } {% for node in nodes %} {{node.name}}::~{{node.name}}() { {% for name, ty in node.fields %} {{gen_cpp_unref(name, ty)} {% endfor %} } {% endfor %} {% for namespace in namespaces %} } {! dedent() !} {% endfor %}