package odin_ast import "base:intrinsics" import "core:mem" import "core:fmt" import "core:reflect" import "core:odin/tokenizer" _ :: intrinsics new_from_positions :: 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 when intrinsics.type_has_field(T, "derived_expr") { n.derived_expr = n } when intrinsics.type_has_field(T, "derived_stmt") { n.derived_stmt = n } return n } new_from_pos_and_end_node :: proc($T: typeid, pos: tokenizer.Pos, end: ^Node) -> ^T { return new(T, pos, end != nil ? end.end : pos) } new :: proc { new_from_positions, new_from_pos_and_end_node, } 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] = (^T)(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] = (^T)(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 := reflect.union_variant_type_info(node.derived) if ti != nil { elem := ti.variant.(reflect.Type_Info_Pointer).elem size = elem.size align = elem.align } #partial switch _ in node.derived { case ^Package, ^File: panic("Cannot clone this node type") } res := cast(^Node)(mem.alloc(size, align) or_else nil) if res == nil { // allocation failure return nil } src: rawptr = node if node.derived != nil { src = (^rawptr)(&node.derived)^ } mem.copy(res, src, size) res_ptr_any: any res_ptr_any.data = &res res_ptr_any.id = ti.id reflect.set_union_value(res.derived, res_ptr_any) res_ptr := reflect.deref(res_ptr_any) if de := reflect.struct_field_value_by_name(res_ptr, "derived_expr", true); de != nil { reflect.set_union_value(de, res_ptr_any) } if ds := reflect.struct_field_value_by_name(res_ptr, "derived_stmt", true); ds != nil { reflect.set_union_value(ds, res_ptr_any) } if res.derived != nil { switch r in res.derived { case ^Package, ^File: case ^Bad_Expr: case ^Ident: case ^Implicit: case ^Undef: case ^Basic_Lit: case ^Basic_Directive: case ^Comment_Group: 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 ^Matrix_Index_Expr: r.expr = clone(r.expr) r.row_index = clone(r.row_index) r.column_index = clone(r.column_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_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 ^Or_Else_Expr: r.x = clone(r.x) r.y = clone(r.y) case ^Or_Return_Expr: r.expr = clone(r.expr) case ^Or_Branch_Expr: r.expr = clone(r.expr) r.label = clone(r.label) 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 = clone(r.label) r.stmts = clone(r.stmts) case ^If_Stmt: r.label = 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 = 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 = clone(r.label) r.init = clone(r.init) r.vals = clone(r.vals) r.expr = clone(r.expr) r.body = clone(r.body) case ^Unroll_Range_Stmt: r.label = clone(r.label) r.args = clone(r.args) r.val0 = clone(r.val0) r.val1 = clone(r.val1) 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 = clone(r.label) r.init = clone(r.init) r.cond = clone(r.cond) r.body = clone(r.body) case ^Type_Switch_Stmt: r.label = 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.attributes = clone_dynamic_array(r.attributes) r.name = auto_cast clone(r.name) r.fullpaths = clone_array(r.fullpaths) 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) r.tag = clone(r.tag) case ^Multi_Pointer_Type: r.elem = clone(r.elem) case ^Array_Type: r.tag = clone(r.tag) r.len = clone(r.len) r.elem = clone(r.elem) case ^Dynamic_Array_Type: r.tag = clone(r.tag) r.elem = clone(r.elem) case ^Fixed_Capacity_Dynamic_Array_Type: r.tag = clone(r.tag) r.capacity = clone(r.capacity) r.elem = clone(r.elem) case ^Struct_Type: r.poly_params = auto_cast clone(r.poly_params) r.align = clone(r.align) r.min_field_align = clone(r.min_field_align) r.max_field_align = clone(r.max_field_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 ^Matrix_Type: r.row_count = clone(r.row_count) r.column_count = clone(r.column_count) r.elem = clone(r.elem) case ^Relative_Type: r.tag = clone(r.tag) r.type = clone(r.type) case ^Bit_Field_Type: r.backing_type = clone(r.backing_type) r.fields = auto_cast clone(r.fields) case ^Bit_Field_Field: r.name = clone(r.name) r.type = clone(r.type) r.bit_size = clone(r.bit_size) case: fmt.panicf("Unhandled node kind: %v", r) } } return res }