package odin_ast import "core:mem" import "core:fmt" import "core:odin/tokenizer" new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T { n := mem.new(T); n.pos = pos; n.end = end; n.derived = n^; base: ^Node = n; // dummy check _ = base; // "Use" type to make -vet happy return n; } clone :: proc{ clone_node, clone_expr, clone_stmt, clone_decl, clone_array, clone_dynamic_array, }; clone_array :: proc(array: $A/[]^$T) -> A { if len(array) == 0 { return nil; } res := make(A, len(array)); for elem, i in array { res[i] = auto_cast clone(elem); } return res; } clone_dynamic_array :: proc(array: $A/[dynamic]^$T) -> A { if len(array) == 0 { return nil; } res := make(A, len(array)); for elem, i in array { res[i] = auto_cast clone(elem); } return res; } clone_expr :: proc(node: ^Expr) -> ^Expr { return cast(^Expr)clone_node(node); } clone_stmt :: proc(node: ^Stmt) -> ^Stmt { return cast(^Stmt)clone_node(node); } clone_decl :: proc(node: ^Decl) -> ^Decl { return cast(^Decl)clone_node(node); } clone_node :: proc(node: ^Node) -> ^Node { if node == nil { return nil; } size := size_of(Node); align := align_of(Node); ti := type_info_of(node.derived.id); if ti != nil { size = ti.size; align = ti.align; } switch in node.derived { case Package, File: panic("Cannot clone this node type"); } res := cast(^Node)mem.alloc(size, align); src: rawptr = node; if node.derived != nil { src = node.derived.data; } mem.copy(res, src, size); res.derived.data = rawptr(res); res.derived.id = node.derived.id; switch r in &res.derived { case Bad_Expr: case Ident: case Implicit: case Undef: case Basic_Lit: case Ellipsis: r.expr = clone(r.expr); case Proc_Lit: r.type = auto_cast clone(r.type); r.body = clone(r.body); case Comp_Lit: r.type = clone(r.type); r.elems = clone(r.elems); case Tag_Expr: r.expr = clone(r.expr); case Unary_Expr: r.expr = clone(r.expr); case Binary_Expr: r.left = clone(r.left); r.right = clone(r.right); case Paren_Expr: r.expr = clone(r.expr); case Selector_Expr: r.expr = clone(r.expr); r.field = auto_cast clone(r.field); case Implicit_Selector_Expr: r.field = auto_cast clone(r.field); case Selector_Call_Expr: r.expr = clone(r.expr); r.call = auto_cast clone(r.call); case Index_Expr: r.expr = clone(r.expr); r.index = clone(r.index); case Deref_Expr: r.expr = clone(r.expr); case Slice_Expr: r.expr = clone(r.expr); r.low = clone(r.low); r.high = clone(r.high); case Call_Expr: r.expr = clone(r.expr); r.args = clone(r.args); case Field_Value: r.field = clone(r.field); r.value = clone(r.value); case Ternary_Expr: r.cond = clone(r.cond); r.x = clone(r.x); r.y = clone(r.y); case Ternary_If_Expr: r.x = clone(r.x); r.cond = clone(r.cond); r.y = clone(r.y); case Ternary_When_Expr: r.x = clone(r.x); r.cond = clone(r.cond); r.y = clone(r.y); case Type_Assertion: r.expr = clone(r.expr); r.type = clone(r.type); case Type_Cast: r.type = clone(r.type); r.expr = clone(r.expr); case Auto_Cast: r.expr = clone(r.expr); case Inline_Asm_Expr: r.param_types = clone(r.param_types); r.return_type = clone(r.return_type); r.constraints_string = clone(r.constraints_string); r.asm_string = clone(r.asm_string); case Bad_Stmt: // empty case Empty_Stmt: // empty case Expr_Stmt: r.expr = clone(r.expr); case Tag_Stmt: r.stmt = clone(r.stmt); case Assign_Stmt: r.lhs = clone(r.lhs); r.rhs = clone(r.rhs); case Block_Stmt: r.label = auto_cast clone(r.label); r.stmts = clone(r.stmts); case If_Stmt: r.label = auto_cast clone(r.label); r.init = clone(r.init); r.cond = clone(r.cond); r.body = clone(r.body); r.else_stmt = clone(r.else_stmt); case When_Stmt: r.cond = clone(r.cond); r.body = clone(r.body); r.else_stmt = clone(r.else_stmt); case Return_Stmt: r.results = clone(r.results); case Defer_Stmt: r.stmt = clone(r.stmt); case For_Stmt: r.label = auto_cast clone(r.label); r.init = clone(r.init); r.cond = clone(r.cond); r.post = clone(r.post); r.body = clone(r.body); case Range_Stmt: r.label = auto_cast clone(r.label); r.vals = clone(r.vals); r.expr = clone(r.expr); r.body = clone(r.body); case Case_Clause: r.list = clone(r.list); r.body = clone(r.body); case Switch_Stmt: r.label = auto_cast clone(r.label); r.init = clone(r.init); r.cond = clone(r.cond); r.body = clone(r.body); case Type_Switch_Stmt: r.label = auto_cast clone(r.label); r.tag = clone(r.tag); r.expr = clone(r.expr); r.body = clone(r.body); case Branch_Stmt: r.label = auto_cast clone(r.label); case Using_Stmt: r.list = clone(r.list); case Bad_Decl: case Value_Decl: r.attributes = clone(r.attributes); r.names = clone(r.names); r.type = clone(r.type); r.values = clone(r.values); case Package_Decl: case Import_Decl: case Foreign_Block_Decl: r.attributes = clone(r.attributes); r.foreign_library = clone(r.foreign_library); r.body = clone(r.body); case Foreign_Import_Decl: r.name = auto_cast clone(r.name); case Proc_Group: r.args = clone(r.args); case Attribute: r.elems = clone(r.elems); case Field: r.names = clone(r.names); r.type = clone(r.type); r.default_value = clone(r.default_value); case Field_List: r.list = clone(r.list); case Typeid_Type: r.specialization = clone(r.specialization); case Helper_Type: r.type = clone(r.type); case Distinct_Type: r.type = clone(r.type); case Poly_Type: r.type = auto_cast clone(r.type); r.specialization = clone(r.specialization); case Proc_Type: r.params = auto_cast clone(r.params); r.results = auto_cast clone(r.results); case Pointer_Type: r.elem = clone(r.elem); case Array_Type: r.len = clone(r.len); r.elem = clone(r.elem); case Dynamic_Array_Type: r.elem = clone(r.elem); case Struct_Type: r.poly_params = auto_cast clone(r.poly_params); r.align = clone(r.align); r.fields = auto_cast clone(r.fields); case Union_Type: r.poly_params = auto_cast clone(r.poly_params); r.align = clone(r.align); r.variants = clone(r.variants); case Enum_Type: r.base_type = clone(r.base_type); r.fields = clone(r.fields); case Bit_Set_Type: r.elem = clone(r.elem); r.underlying = clone(r.underlying); case Map_Type: r.key = clone(r.key); r.value = clone(r.value); case: fmt.panicf("Unhandled node kind: %T", r); } return res; }