diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-03-04 12:17:00 +0100 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-03-04 12:17:00 +0100 |
| commit | 58287455d64ab16091522bf8a358b079ef05daad (patch) | |
| tree | 7b6655d6d34b5ad6d719523e4938b8002c43d8ab /src/analysis | |
| parent | 63d0bd412a8817445d6dc18e79d5d54c94caf401 (diff) | |
strip colons and update ast to use unions
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/analysis.odin | 2836 |
1 files changed, 1415 insertions, 1421 deletions
diff --git a/src/analysis/analysis.odin b/src/analysis/analysis.odin index 34e8ac1..400bde6 100644 --- a/src/analysis/analysis.odin +++ b/src/analysis/analysis.odin @@ -104,15 +104,15 @@ make_ast_context :: proc(file: ast.File, imports: []common.Package, package_name current_package = package_name, uri = uri, allocator = allocator, - }; + } - add_local_group(&ast_context, 0); + add_local_group(&ast_context, 0) - when ODIN_OS == "windows" { - ast_context.uri = strings.to_lower(ast_context.uri, allocator); + when ODIN_OS == .Windows { + ast_context.uri = strings.to_lower(ast_context.uri, allocator) } - return ast_context; + return ast_context } tokenizer_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { @@ -126,205 +126,203 @@ resolve_poly_spec :: proc { resolve_poly_spec_node, resolve_poly_spec_array, resolve_poly_spec_dynamic_array, -}; +} resolve_poly_spec_array :: proc(ast_context: ^AstContext, call_array: $A/[]^$T, spec_array: $D/[]^$K, poly_map: ^map[string]^ast.Expr) { if len(call_array) != len(spec_array) { - return; + return } for elem, i in call_array { - resolve_poly_spec(ast_context, elem, spec_array[i], poly_map); + resolve_poly_spec(ast_context, elem, spec_array[i], poly_map) } } resolve_poly_spec_dynamic_array :: proc(ast_context: ^AstContext, call_array: $A/[dynamic]^$T, spec_array: $D/[dynamic]^$K, poly_map: ^map[string]^ast.Expr) { if len(call_array) != len(spec_array) { - return; + return } for elem, i in call_array { - resolve_poly_spec(ast_context, elem, spec_array[i], poly_map); + resolve_poly_spec(ast_context, elem, spec_array[i], poly_map) } } get_poly_node_to_expr :: proc(node: ^ast.Node) -> ^ast.Expr { - using ast; + using ast - switch v in node.derived { - case Ident: - return cast(^Expr)node; + #partial switch v in node.derived { + case ^Ident: + return cast(^Expr)node case: - log.warnf("Unhandled poly to node kind %v", v); + log.warnf("Unhandled poly to node kind %v", v) } - return nil; + return nil } resolve_poly_spec_node :: proc(ast_context: ^AstContext, call_node: ^ast.Node, spec_node: ^ast.Node, poly_map: ^map[string]^ast.Expr) { - using ast; + using ast if call_node == nil || spec_node == nil { - return; + return } - switch m in spec_node.derived { - case Bad_Expr: - case Ident: - case Implicit: - case Undef: - case Basic_Lit: - case Poly_Type: + #partial switch m in spec_node.derived { + case ^Bad_Expr: + case ^Ident: + case ^Implicit: + case ^Undef: + case ^Basic_Lit: + case ^Poly_Type: if expr := get_poly_node_to_expr(call_node); expr != nil { - poly_map[m.type.name] = expr; - } - case Ellipsis: - if n, ok := call_node.derived.(Ellipsis); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - } - case Tag_Expr: - if n, ok := call_node.derived.(Tag_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - } - case Unary_Expr: - if n, ok := call_node.derived.(Unary_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - } - case Binary_Expr: - if n, ok := call_node.derived.(Binary_Expr); ok { - resolve_poly_spec(ast_context, n.left, m.left, poly_map); - resolve_poly_spec(ast_context, n.right, m.right, poly_map); - } - case Paren_Expr: - if n, ok := call_node.derived.(Paren_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - } - case Selector_Expr: - if n, ok := call_node.derived.(Selector_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - resolve_poly_spec(ast_context, n.field, m.field, poly_map); - } - case Slice_Expr: - if n, ok := call_node.derived.(Slice_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - resolve_poly_spec(ast_context, n.low, m.low, poly_map); - resolve_poly_spec(ast_context, n.high, m.high, poly_map); - } - case Distinct_Type: - if n, ok := call_node.derived.(Distinct_Type); ok { - resolve_poly_spec(ast_context, n.type, m.type, poly_map); - } - case Proc_Type: - if n, ok := call_node.derived.(Proc_Type); ok { - resolve_poly_spec(ast_context, n.params, m.params, poly_map); - resolve_poly_spec(ast_context, n.results, m.results, poly_map); - } - case Pointer_Type: - if n, ok := call_node.derived.(Pointer_Type); ok { - resolve_poly_spec(ast_context, n.elem, m.elem, poly_map); - } - case Array_Type: - if n, ok := call_node.derived.(Array_Type); ok { - resolve_poly_spec(ast_context, n.len, m.len, poly_map); - resolve_poly_spec(ast_context, n.elem, m.elem, poly_map); - } - case Dynamic_Array_Type: - if n, ok := call_node.derived.(Dynamic_Array_Type); ok { - resolve_poly_spec(ast_context, n.elem, m.elem, poly_map); - } - case Struct_Type: - if n, ok := call_node.derived.(Struct_Type); ok { - resolve_poly_spec(ast_context, n.poly_params, m.poly_params, poly_map); - resolve_poly_spec(ast_context, n.align, m.align, poly_map); - resolve_poly_spec(ast_context, n.fields, m.fields, poly_map); - } - case Field: - if n, ok := call_node.derived.(Field); ok { - resolve_poly_spec(ast_context, n.names, m.names, poly_map); - resolve_poly_spec(ast_context, n.type, m.type, poly_map); - resolve_poly_spec(ast_context, n.default_value, m.default_value, poly_map); - } - case Field_List: - if n, ok := call_node.derived.(Field_List); ok { - resolve_poly_spec(ast_context, n.list, m.list, poly_map); - } - case Field_Value: - if n, ok := call_node.derived.(Field_Value); ok { - resolve_poly_spec(ast_context, n.field, m.field, poly_map); - resolve_poly_spec(ast_context, n.value, m.value, poly_map); - } - case Union_Type: - if n, ok := call_node.derived.(Union_Type); ok { - resolve_poly_spec(ast_context, n.poly_params, m.poly_params, poly_map); - resolve_poly_spec(ast_context, n.align, m.align, poly_map); - resolve_poly_spec(ast_context, n.variants, m.variants, poly_map); - } - case Enum_Type: - if n, ok := call_node.derived.(Enum_Type); ok { - resolve_poly_spec(ast_context, n.base_type, m.base_type, poly_map); - resolve_poly_spec(ast_context, n.fields, m.fields, poly_map); - } - case Bit_Set_Type: - if n, ok := call_node.derived.(Bit_Set_Type); ok { - resolve_poly_spec(ast_context, n.elem, m.elem, poly_map); - resolve_poly_spec(ast_context, n.underlying, m.underlying, poly_map); - } - case Map_Type: - if n, ok := call_node.derived.(Map_Type); ok { - resolve_poly_spec(ast_context, n.key, m.key, poly_map); - resolve_poly_spec(ast_context, n.value, m.value, poly_map); - } - case Call_Expr: - if n, ok := call_node.derived.(Call_Expr); ok { - resolve_poly_spec(ast_context, n.expr, m.expr, poly_map); - resolve_poly_spec(ast_context, n.args, m.args, poly_map); - } - case Typeid_Type: - if n, ok := call_node.derived.(Typeid_Type); ok { - resolve_poly_spec(ast_context, n.specialization, m.specialization, poly_map); + poly_map[m.type.name] = expr + } + case ^Ellipsis: + if n, ok := call_node.derived.(^Ellipsis); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + } + case ^Tag_Expr: + if n, ok := call_node.derived.(^Tag_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + } + case ^Unary_Expr: + if n, ok := call_node.derived.(^Unary_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + } + case ^Binary_Expr: + if n, ok := call_node.derived.(^Binary_Expr); ok { + resolve_poly_spec(ast_context, n.left, m.left, poly_map) + resolve_poly_spec(ast_context, n.right, m.right, poly_map) + } + case ^Paren_Expr: + if n, ok := call_node.derived.(^Paren_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + } + case ^Selector_Expr: + if n, ok := call_node.derived.(^Selector_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + resolve_poly_spec(ast_context, n.field, m.field, poly_map) + } + case ^Slice_Expr: + if n, ok := call_node.derived.(^Slice_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + resolve_poly_spec(ast_context, n.low, m.low, poly_map) + resolve_poly_spec(ast_context, n.high, m.high, poly_map) + } + case ^Distinct_Type: + if n, ok := call_node.derived.(^Distinct_Type); ok { + resolve_poly_spec(ast_context, n.type, m.type, poly_map) + } + case ^Proc_Type: + if n, ok := call_node.derived.(^Proc_Type); ok { + resolve_poly_spec(ast_context, n.params, m.params, poly_map) + resolve_poly_spec(ast_context, n.results, m.results, poly_map) + } + case ^Pointer_Type: + if n, ok := call_node.derived.(^Pointer_Type); ok { + resolve_poly_spec(ast_context, n.elem, m.elem, poly_map) + } + case ^Array_Type: + if n, ok := call_node.derived.(^Array_Type); ok { + resolve_poly_spec(ast_context, n.len, m.len, poly_map) + resolve_poly_spec(ast_context, n.elem, m.elem, poly_map) + } + case ^Dynamic_Array_Type: + if n, ok := call_node.derived.(^Dynamic_Array_Type); ok { + resolve_poly_spec(ast_context, n.elem, m.elem, poly_map) + } + case ^Struct_Type: + if n, ok := call_node.derived.(^Struct_Type); ok { + resolve_poly_spec(ast_context, n.poly_params, m.poly_params, poly_map) + resolve_poly_spec(ast_context, n.align, m.align, poly_map) + resolve_poly_spec(ast_context, n.fields, m.fields, poly_map) + } + case ^Field: + if n, ok := call_node.derived.(^Field); ok { + resolve_poly_spec(ast_context, n.names, m.names, poly_map) + resolve_poly_spec(ast_context, n.type, m.type, poly_map) + resolve_poly_spec(ast_context, n.default_value, m.default_value, poly_map) + } + case ^Field_List: + if n, ok := call_node.derived.(^Field_List); ok { + resolve_poly_spec(ast_context, n.list, m.list, poly_map) + } + case ^Field_Value: + if n, ok := call_node.derived.(^Field_Value); ok { + resolve_poly_spec(ast_context, n.field, m.field, poly_map) + resolve_poly_spec(ast_context, n.value, m.value, poly_map) + } + case ^Union_Type: + if n, ok := call_node.derived.(^Union_Type); ok { + resolve_poly_spec(ast_context, n.poly_params, m.poly_params, poly_map) + resolve_poly_spec(ast_context, n.align, m.align, poly_map) + resolve_poly_spec(ast_context, n.variants, m.variants, poly_map) + } + case ^Enum_Type: + if n, ok := call_node.derived.(^Enum_Type); ok { + resolve_poly_spec(ast_context, n.base_type, m.base_type, poly_map) + resolve_poly_spec(ast_context, n.fields, m.fields, poly_map) + } + case ^Bit_Set_Type: + if n, ok := call_node.derived.(^Bit_Set_Type); ok { + resolve_poly_spec(ast_context, n.elem, m.elem, poly_map) + resolve_poly_spec(ast_context, n.underlying, m.underlying, poly_map) + } + case ^Map_Type: + if n, ok := call_node.derived.(^Map_Type); ok { + resolve_poly_spec(ast_context, n.key, m.key, poly_map) + resolve_poly_spec(ast_context, n.value, m.value, poly_map) + } + case ^Call_Expr: + if n, ok := call_node.derived.(^Call_Expr); ok { + resolve_poly_spec(ast_context, n.expr, m.expr, poly_map) + resolve_poly_spec(ast_context, n.args, m.args, poly_map) + } + case ^Typeid_Type: + if n, ok := call_node.derived.(^Typeid_Type); ok { + resolve_poly_spec(ast_context, n.specialization, m.specialization, poly_map) } case: - log.error("Unhandled poly node kind: %T", m); + log.error("Unhandled poly node kind: %T", m) } } resolve_type_comp_literal :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, current_symbol: index.Symbol, current_comp_lit: ^ast.Comp_Lit) -> (index.Symbol, ^ast.Comp_Lit, bool) { - if position_context.comp_lit == current_comp_lit { - return current_symbol, current_comp_lit, true; + return current_symbol, current_comp_lit, true } else if current_comp_lit == nil { return {}, nil, false } if current_comp_lit == nil { - return {}, nil, false; + return {}, nil, false } - element_index := 0; + element_index := 0 for elem, i in current_comp_lit.elems { if position_in_node(elem, position_context.position) { - element_index = i; + element_index = i } } for elem in current_comp_lit.elems { - if !position_in_node(elem, position_context.position) { - continue; + continue } - if field_value, ok := elem.derived.(ast.Field_Value); ok { //named - if comp_lit, ok := field_value.value.derived.(ast.Comp_Lit); ok { + if field_value, ok := elem.derived.(^ast.Field_Value); ok { //named + if comp_lit, ok := field_value.value.derived.(^ast.Comp_Lit); ok { if s, ok := current_symbol.value.(index.SymbolStructValue); ok { for name, i in s.names { - if name == field_value.field.derived.(ast.Ident).name { + if name == field_value.field.derived.(^ast.Ident).name { if symbol, ok := resolve_type_expression(ast_context, s.types[i]); ok { //Stop at bitset, because we don't want to enter a comp_lit of a bitset if _, ok := symbol.value.(index.SymbolBitSetValue); ok { - return current_symbol, current_comp_lit, true; + return current_symbol, current_comp_lit, true } - return resolve_type_comp_literal(ast_context, position_context, symbol, cast(^ast.Comp_Lit)field_value.value); + return resolve_type_comp_literal(ast_context, position_context, symbol, cast(^ast.Comp_Lit)field_value.value) } } } @@ -334,166 +332,166 @@ resolve_type_comp_literal :: proc(ast_context: ^AstContext, position_context: ^D if s, ok := current_symbol.value.(index.SymbolStructValue); ok { if len(s.types) <= element_index { - return {}, {}, false; + return {}, {}, false } if symbol, ok := resolve_type_expression(ast_context, s.types[element_index]); ok { //Stop at bitset, because we don't want to enter a comp_lit of a bitset if _, ok := symbol.value.(index.SymbolBitSetValue); ok { - return current_symbol, current_comp_lit, true; + return current_symbol, current_comp_lit, true } - return resolve_type_comp_literal(ast_context, position_context, symbol, cast(^ast.Comp_Lit)field_value.value); + return resolve_type_comp_literal(ast_context, position_context, symbol, cast(^ast.Comp_Lit)field_value.value) } } } } - return current_symbol, current_comp_lit, true; + return current_symbol, current_comp_lit, true } resolve_generic_function :: proc { resolve_generic_function_ast, resolve_generic_function_symbol, -}; +} resolve_generic_function_symbol :: proc(ast_context: ^AstContext, params: []^ast.Field, results: []^ast.Field) -> (index.Symbol, bool) { - using ast; + using ast if params == nil { - return {}, false; + return {}, false } if results == nil { - return {}, false; + return {}, false } if ast_context.call == nil { - return {}, false; + return {}, false } - call_expr := ast_context.call; - poly_map := make(map[string]^Expr, 0, context.temp_allocator); - i := 0; - count_required_params := 0; + call_expr := ast_context.call + poly_map := make(map[string]^Expr, 0, context.temp_allocator) + i := 0 + count_required_params := 0 for param in params { if param.default_value == nil { - count_required_params += 1; + count_required_params += 1 } for name in param.names { if len(call_expr.args) <= i { - break; + break } - if poly, ok := name.derived.(Poly_Type); ok { - poly_map[poly.type.name] = call_expr.args[i]; + if poly, ok := name.derived.(^Poly_Type); ok { + poly_map[poly.type.name] = call_expr.args[i] } if param.type == nil { - continue; + continue } - if type_id, ok := param.type.derived.(Typeid_Type); ok { + if type_id, ok := param.type.derived.(^Typeid_Type); ok { if type_id.specialization != nil && !common.node_equal(call_expr.args[i], type_id.specialization) { - return {}, false; + return {}, false } } - resolve_poly_spec_node(ast_context, call_expr.args[i], param.type, &poly_map); + resolve_poly_spec_node(ast_context, call_expr.args[i], param.type, &poly_map) - i += 1; + i += 1 } } if count_required_params > len(call_expr.args) || count_required_params == 0 || len(call_expr.args) == 0 { - return {}, false; + return {}, false } - function_name := ""; - function_range: common.Range; + function_name := "" + function_range: common.Range - if ident, ok := call_expr.expr.derived.(Ident); ok { - function_name = ident.name; - function_range = common.get_token_range(ident, ast_context.file.src); - } else if selector, ok := call_expr.expr.derived.(Selector_Expr); ok { - function_name = selector.field.name; - function_range = common.get_token_range(selector, ast_context.file.src); + if ident, ok := call_expr.expr.derived.(^Ident); ok { + function_name = ident.name + function_range = common.get_token_range(ident, ast_context.file.src) + } else if selector, ok := call_expr.expr.derived.(^Selector_Expr); ok { + function_name = selector.field.name + function_range = common.get_token_range(selector, ast_context.file.src) } else { - return {}, false; + return {}, false } symbol := index.Symbol { range = function_range, type = .Function, name = function_name, - }; + } - return_types := make([dynamic]^ast.Field, ast_context.allocator); - argument_types := make([dynamic]^ast.Field, ast_context.allocator); + return_types := make([dynamic]^ast.Field, ast_context.allocator) + argument_types := make([dynamic]^ast.Field, ast_context.allocator) for result in results { if result.type == nil { - continue; + continue } - ident, ok := common.unwrap_pointer(result.type); + ident, ok := common.unwrap_pointer(result.type) if ok { if m, ok := poly_map[ident.name]; ok { - field := cast(^Field)index.clone_node(result, ast_context.allocator, nil); - field.type = m; - append(&return_types, field); + field := cast(^Field)index.clone_node(result, ast_context.allocator, nil) + field.type = m + append(&return_types, field) } else { - append(&return_types, result); + append(&return_types, result) } } else { - append(&return_types, result); + append(&return_types, result) } } for param in params { if len(param.names) == 0 { - continue; + continue } //check the name for poly - if poly_type, ok := param.names[0].derived.(ast.Poly_Type); ok && param.type != nil { + if poly_type, ok := param.names[0].derived.(^ast.Poly_Type); ok && param.type != nil { if m, ok := poly_map[poly_type.type.name]; ok { - field := cast(^Field)index.clone_node(param, ast_context.allocator, nil); - field.type = m; - append(&argument_types, field); + field := cast(^Field)index.clone_node(param, ast_context.allocator, nil) + field.type = m + append(&argument_types, field) } } else { - append(&argument_types, param); + append(&argument_types, param) } } symbol.value = index.SymbolProcedureValue { return_types = return_types[:], arg_types = argument_types[:], - }; + } - return symbol, true; + return symbol, true } resolve_generic_function_ast :: proc(ast_context: ^AstContext, proc_lit: ast.Proc_Lit) -> (index.Symbol, bool) { - using ast; + using ast if proc_lit.type.params == nil { - return index.Symbol {}, false; + return index.Symbol {}, false } if proc_lit.type.results == nil { - return index.Symbol {}, false; + return index.Symbol {}, false } if ast_context.call == nil { - return index.Symbol {}, false; + return index.Symbol {}, false } - return resolve_generic_function_symbol(ast_context, proc_lit.type.params.list, proc_lit.type.results.list); + return resolve_generic_function_symbol(ast_context, proc_lit.type.params.list, proc_lit.type.results.list) } is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: index.Symbol, flags: ast.Field_Flags = {}) -> bool { @@ -503,59 +501,59 @@ is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: index.Symbol, flags switch untyped.type { case .Integer: switch basic.ident.name { - case "int", "uint", "u32", "i32", "u8", "i8", "u64", "u16", "i16": return true; - case: return false; + case "int", "uint", "u32", "i32", "u8", "i8", "u64", "u16", "i16": return true + case: return false } case .Bool: switch basic.ident.name { - case "bool", "b32", "b64": return true; - case: return false; + case "bool", "b32", "b64": return true + case: return false } case .String: switch basic.ident.name { - case "string", "cstring": return true; - case: return false; + case "string", "cstring": return true + case: return false } case .Float: switch basic.ident.name { - case "f32", "f64": return true; - case: return false; + case "f32", "f64": return true + case: return false } } } } - a_id := reflect.union_variant_typeid(a.value); - b_id := reflect.union_variant_typeid(b.value); + a_id := reflect.union_variant_typeid(a.value) + b_id := reflect.union_variant_typeid(b.value) if a_id != b_id { - return false; + return false } if a.pointers != b.pointers { - return false; + return false } if .Distinct in a.flags != .Distinct in b.flags { - return false; + return false } if .Distinct in a.flags == .Distinct in b.flags && .Distinct in a.flags && a.name == b.name && a.pkg == b.pkg { - return true; + return true } #partial switch b_value in b.value { case index.SymbolBasicValue: if .Auto_Cast in flags { - return true; + return true } else if .Any_Int in flags { //Temporary - make a function that finds the base type of basic values //This code only works with non distinct ints switch a.name { - case "int", "uint", "u32", "i32", "u8", "i8", "u64", "u16", "i16": return true; + case "int", "uint", "u32", "i32", "u8", "i8", "u64", "u16", "i16": return true } } } @@ -564,211 +562,211 @@ is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: index.Symbol, flags case index.SymbolBasicValue: return a.name == b.name && a.pkg == b.pkg case index.SymbolStructValue, index.SymbolEnumValue, index.SymbolUnionValue, index.SymbolBitSetValue: - return a.name == b.name && a.pkg == b.pkg; + return a.name == b.name && a.pkg == b.pkg case index.SymbolSliceValue: - b_value := b.value.(index.SymbolSliceValue); + b_value := b.value.(index.SymbolSliceValue) - a_symbol: index.Symbol; - b_symbol: index.Symbol; - ok: bool; + a_symbol: index.Symbol + b_symbol: index.Symbol + ok: bool - a_symbol, ok = resolve_type_expression(ast_context, a_value.expr); + a_symbol, ok = resolve_type_expression(ast_context, a_value.expr) if !ok { - return false; + return false } - b_symbol, ok = resolve_type_expression(ast_context, b_value.expr); + b_symbol, ok = resolve_type_expression(ast_context, b_value.expr) if !ok { - return false; + return false } - return is_symbol_same_typed(ast_context, a_symbol, b_symbol); + return is_symbol_same_typed(ast_context, a_symbol, b_symbol) case index.SymbolFixedArrayValue: - b_value := b.value.(index.SymbolFixedArrayValue); + b_value := b.value.(index.SymbolFixedArrayValue) - a_symbol: index.Symbol; - b_symbol: index.Symbol; - ok: bool; + a_symbol: index.Symbol + b_symbol: index.Symbol + ok: bool - a_symbol, ok = resolve_type_expression(ast_context, a_value.expr); + a_symbol, ok = resolve_type_expression(ast_context, a_value.expr) if !ok { - return false; + return false } - b_symbol, ok = resolve_type_expression(ast_context, b_value.expr); + b_symbol, ok = resolve_type_expression(ast_context, b_value.expr) if !ok { - return false; + return false } - return is_symbol_same_typed(ast_context, a_symbol, b_symbol); + return is_symbol_same_typed(ast_context, a_symbol, b_symbol) case index.SymbolDynamicArrayValue: - b_value := b.value.(index.SymbolDynamicArrayValue); + b_value := b.value.(index.SymbolDynamicArrayValue) - a_symbol: index.Symbol; - b_symbol: index.Symbol; - ok: bool; + a_symbol: index.Symbol + b_symbol: index.Symbol + ok: bool - a_symbol, ok = resolve_type_expression(ast_context, a_value.expr); + a_symbol, ok = resolve_type_expression(ast_context, a_value.expr) if !ok { - return false; + return false } - b_symbol, ok = resolve_type_expression(ast_context, b_value.expr); + b_symbol, ok = resolve_type_expression(ast_context, b_value.expr) if !ok { - return false; + return false } - return is_symbol_same_typed(ast_context, a_symbol, b_symbol); + return is_symbol_same_typed(ast_context, a_symbol, b_symbol) case index.SymbolMapValue: - b_value := b.value.(index.SymbolMapValue); + b_value := b.value.(index.SymbolMapValue) - a_key_symbol: index.Symbol; - b_key_symbol: index.Symbol; - a_value_symbol: index.Symbol; - b_value_symbol: index.Symbol; - ok: bool; + a_key_symbol: index.Symbol + b_key_symbol: index.Symbol + a_value_symbol: index.Symbol + b_value_symbol: index.Symbol + ok: bool - a_key_symbol, ok = resolve_type_expression(ast_context, a_value.key); + a_key_symbol, ok = resolve_type_expression(ast_context, a_value.key) if !ok { - return false; + return false } - b_key_symbol, ok = resolve_type_expression(ast_context, b_value.key); + b_key_symbol, ok = resolve_type_expression(ast_context, b_value.key) if !ok { - return false; + return false } - a_value_symbol, ok = resolve_type_expression(ast_context, a_value.value); + a_value_symbol, ok = resolve_type_expression(ast_context, a_value.value) if !ok { - return false; + return false } - b_value_symbol, ok = resolve_type_expression(ast_context, b_value.value); + b_value_symbol, ok = resolve_type_expression(ast_context, b_value.value) if !ok { - return false; + return false } - return is_symbol_same_typed(ast_context, a_key_symbol, b_key_symbol) && is_symbol_same_typed(ast_context, a_value_symbol, b_value_symbol); + return is_symbol_same_typed(ast_context, a_key_symbol, b_key_symbol) && is_symbol_same_typed(ast_context, a_value_symbol, b_value_symbol) } - return false; + return false } get_field_list_name_index :: proc(name: string, field_list: []^ast.Field) -> (int, bool) { for field, i in field_list { for field_name in field.names { - if ident, ok := field_name.derived.(ast.Ident); ok { + if ident, ok := field_name.derived.(^ast.Ident); ok { if name == ident.name { - return i, true; + return i, true } } } } - return 0, false; + return 0, false } /* Figure out which function the call expression is using out of the list from proc group */ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Group) -> (index.Symbol, bool) { - using ast; + using ast - call_expr := ast_context.call; + call_expr := ast_context.call - candidates := make([dynamic]index.Symbol, context.temp_allocator); + candidates := make([dynamic]index.Symbol, context.temp_allocator) for arg_expr in group.args { next_fn: if f, ok := resolve_type_expression(ast_context, arg_expr); ok { if call_expr == nil || len(call_expr.args) == 0 { - append(&candidates, f); - break next_fn; + append(&candidates, f) + break next_fn } if procedure, ok := f.value.(index.SymbolProcedureValue); ok { - count_required_params := 0; + count_required_params := 0 for arg in procedure.arg_types { if arg.default_value == nil { - count_required_params += 1; + count_required_params += 1 } } if len(procedure.arg_types) < len(call_expr.args) { - continue; + continue } for arg, i in call_expr.args { - ast_context.use_locals = true; + ast_context.use_locals = true - call_symbol: index.Symbol; - arg_symbol: index.Symbol; - ok: bool; - i := i; + call_symbol: index.Symbol + arg_symbol: index.Symbol + ok: bool + i := i - if _, ok = arg.derived.(ast.Bad_Expr); ok { - continue; + if _, ok = arg.derived.(^ast.Bad_Expr); ok { + continue } //named parameter - if field, is_field := arg.derived.(ast.Field_Value); is_field { - call_symbol, ok = resolve_type_expression(ast_context, field.value); + if field, is_field := arg.derived.(^ast.Field_Value); is_field { + call_symbol, ok = resolve_type_expression(ast_context, field.value) if !ok { - break next_fn; + break next_fn } - if ident, is_ident := field.field.derived.(ast.Ident); is_ident { - i, ok = get_field_list_name_index(field.field.derived.(ast.Ident).name, procedure.arg_types); + if ident, is_ident := field.field.derived.(^ast.Ident); is_ident { + i, ok = get_field_list_name_index(field.field.derived.(^ast.Ident).name, procedure.arg_types) } else { - break next_fn; + break next_fn } } else { - call_symbol, ok = resolve_type_expression(ast_context, arg); + call_symbol, ok = resolve_type_expression(ast_context, arg) } if !ok { - break next_fn; + break next_fn } if p, ok := call_symbol.value.(index.SymbolProcedureValue); ok { if len(p.return_types) != 1 { - break next_fn; + break next_fn } if s, ok := resolve_type_expression(ast_context, p.return_types[0].type); ok { - call_symbol = s; + call_symbol = s } } if procedure.arg_types[i].type != nil { - arg_symbol, ok = resolve_type_expression(ast_context, procedure.arg_types[i].type); + arg_symbol, ok = resolve_type_expression(ast_context, procedure.arg_types[i].type) } else { - arg_symbol, ok = resolve_type_expression(ast_context, procedure.arg_types[i].default_value); + arg_symbol, ok = resolve_type_expression(ast_context, procedure.arg_types[i].default_value) } if !ok { - break next_fn; + break next_fn } if !is_symbol_same_typed(ast_context, call_symbol, arg_symbol, procedure.arg_types[i].flags) { - break next_fn; + break next_fn } } - append(&candidates, f); + append(&candidates, f) } } } @@ -781,300 +779,300 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou value = index.SymbolAggregateValue { symbols = candidates[:], }, - }, true; + }, true } else if len(candidates) == 1 { - return candidates[0], true; + return candidates[0], true } - return index.Symbol {}, false; + return index.Symbol {}, false } resolve_basic_lit :: proc(ast_context: ^AstContext, basic_lit: ast.Basic_Lit) -> (index.Symbol, bool) { symbol := index.Symbol { type = .Constant, - }; + } - value: index.SymbolUntypedValue; + value: index.SymbolUntypedValue if v, ok := strconv.parse_int(basic_lit.tok.text); ok { - value.type = .Integer; + value.type = .Integer } else if v, ok := strconv.parse_bool(basic_lit.tok.text); ok { - value.type = .Bool; + value.type = .Bool } else if v, ok := strconv.parse_f64(basic_lit.tok.text); ok { - value.type = .Float; + value.type = .Float } else { - value.type = .String; + value.type = .String } symbol.pkg = ast_context.current_package - symbol.value = value; + symbol.value = value - return symbol, true; + return symbol, true } resolve_basic_directive :: proc(ast_context: ^AstContext, directive: ast.Basic_Directive, a := #caller_location) -> (index.Symbol, bool) { switch directive.name { case "caller_location": - ident := index.new_type(ast.Ident, directive.pos, directive.end, ast_context.allocator); - ident.name = "Source_Code_Location"; - ast_context.current_package = ast_context.document_package; + ident := index.new_type(ast.Ident, directive.pos, directive.end, ast_context.allocator) + ident.name = "Source_Code_Location" + ast_context.current_package = ast_context.document_package return resolve_type_identifier(ast_context, ident^) } - return {}, false; + return {}, false } resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.Symbol, bool) { if node == nil { - return {}, false; + return {}, false } - saved_package := ast_context.current_package; + saved_package := ast_context.current_package defer { - ast_context.current_package = saved_package; + ast_context.current_package = saved_package } if ast_context.recursion_counter > 15 { - log.error("Recursion passed 15 attempts - giving up"); - return {}, false; + log.error("Recursion passed 15 attempts - giving up") + return {}, false } - ast_context.recursion_counter += 1; + ast_context.recursion_counter += 1 defer { - ast_context.recursion_counter -= 1; - } - - using ast; - - switch v in &node.derived { - case Union_Type: - return make_symbol_union_from_ast(ast_context, v, ast_context.field_name, true), true; - case Enum_Type: - return make_symbol_enum_from_ast(ast_context, v, ast_context.field_name, true), true; - case Struct_Type: - return make_symbol_struct_from_ast(ast_context, v, ast_context.field_name, true), true; - case Bit_Set_Type: - return make_symbol_bitset_from_ast(ast_context, v, ast_context.field_name, true), true; - case Array_Type: - return make_symbol_array_from_ast(ast_context, v), true; - case Dynamic_Array_Type: - return make_symbol_dynamic_array_from_ast(ast_context, v), true; - case Map_Type: - return make_symbol_map_from_ast(ast_context, v), true; - case Proc_Type: - return make_symbol_procedure_from_ast(ast_context, node, v, ast_context.field_name), true; - case Basic_Directive: - return resolve_basic_directive(ast_context, v); - case Binary_Expr: - return resolve_first_symbol_from_binary_expression(ast_context, &v); - case Ident: - return resolve_type_identifier(ast_context, v); - case Basic_Lit: - return resolve_basic_lit(ast_context, v); - case Type_Cast: - return resolve_type_expression(ast_context, v.type); - case Auto_Cast: - return resolve_type_expression(ast_context, v.expr); - case Comp_Lit: - return resolve_type_expression(ast_context, v.type); - case Unary_Expr: + ast_context.recursion_counter -= 1 + } + + using ast + + #partial switch v in node.derived { + case ^Union_Type: + return make_symbol_union_from_ast(ast_context, v^, ast_context.field_name, true), true + case ^Enum_Type: + return make_symbol_enum_from_ast(ast_context, v^, ast_context.field_name, true), true + case ^Struct_Type: + return make_symbol_struct_from_ast(ast_context, v^, ast_context.field_name, true), true + case ^Bit_Set_Type: + return make_symbol_bitset_from_ast(ast_context, v^, ast_context.field_name, true), true + case ^Array_Type: + return make_symbol_array_from_ast(ast_context, v^), true + case ^Dynamic_Array_Type: + return make_symbol_dynamic_array_from_ast(ast_context, v^), true + case ^Map_Type: + return make_symbol_map_from_ast(ast_context, v^), true + case ^Proc_Type: + return make_symbol_procedure_from_ast(ast_context, node, v^, ast_context.field_name), true + case ^Basic_Directive: + return resolve_basic_directive(ast_context, v^) + case ^Binary_Expr: + return resolve_first_symbol_from_binary_expression(ast_context, v) + case ^Ident: + return resolve_type_identifier(ast_context, v^) + case ^Basic_Lit: + return resolve_basic_lit(ast_context, v^) + case ^Type_Cast: + return resolve_type_expression(ast_context, v.type) + case ^Auto_Cast: + return resolve_type_expression(ast_context, v.expr) + case ^Comp_Lit: + return resolve_type_expression(ast_context, v.type) + case ^Unary_Expr: if v.op.kind == .And { - symbol, ok := resolve_type_expression(ast_context, v.expr); - symbol.pointers += 1; - return symbol, ok; + symbol, ok := resolve_type_expression(ast_context, v.expr) + symbol.pointers += 1 + return symbol, ok } else { - return resolve_type_expression(ast_context, v.expr); - } - case Deref_Expr: - symbol, ok := resolve_type_expression(ast_context, v.expr); - symbol.pointers -= 1; - return symbol, ok; - case Paren_Expr: - return resolve_type_expression(ast_context, v.expr); - case Slice_Expr: - return resolve_type_expression(ast_context, v.expr); - case Tag_Expr: - return resolve_type_expression(ast_context, v.expr); - case Helper_Type: - return resolve_type_expression(ast_context, v.type); - case Ellipsis: - return resolve_type_expression(ast_context, v.expr); - case Implicit: - ident := index.new_type(Ident, v.node.pos, v.node.end, context.temp_allocator); - ident.name = v.tok.text; - return resolve_type_identifier(ast_context, ident^); - case Type_Assertion: - if unary, ok := v.type.derived.(ast.Unary_Expr); ok { + return resolve_type_expression(ast_context, v.expr) + } + case ^Deref_Expr: + symbol, ok := resolve_type_expression(ast_context, v.expr) + symbol.pointers -= 1 + return symbol, ok + case ^Paren_Expr: + return resolve_type_expression(ast_context, v.expr) + case ^Slice_Expr: + return resolve_type_expression(ast_context, v.expr) + case ^Tag_Expr: + return resolve_type_expression(ast_context, v.expr) + case ^Helper_Type: + return resolve_type_expression(ast_context, v.type) + case ^Ellipsis: + return resolve_type_expression(ast_context, v.expr) + case ^Implicit: + ident := index.new_type(Ident, v.node.pos, v.node.end, context.temp_allocator) + ident.name = v.tok.text + return resolve_type_identifier(ast_context, ident^) + case ^Type_Assertion: + if unary, ok := v.type.derived.(^ast.Unary_Expr); ok { if unary.op.kind == .Question { if symbol, ok := resolve_type_expression(ast_context, v.expr); ok { if union_value, ok := symbol.value.(index.SymbolUnionValue); ok { if len(union_value.types) != 1 { - return {}, false; + return {}, false } - return resolve_type_expression(ast_context, union_value.types[0]); + return resolve_type_expression(ast_context, union_value.types[0]) } } } } else { - return resolve_type_expression(ast_context, v.type); + return resolve_type_expression(ast_context, v.type) } - case Proc_Lit: + case ^Proc_Lit: if v.type.results != nil { if len(v.type.results.list) == 1 { - return resolve_type_expression(ast_context, v.type.results.list[0].type); + return resolve_type_expression(ast_context, v.type.results.list[0].type) } } - case Pointer_Type: - symbol, ok := resolve_type_expression(ast_context, v.elem); - symbol.pointers += 1; - return symbol, ok; - case Multi_Pointer_Type: - symbol, ok := resolve_type_expression(ast_context, v.elem); - symbol.pointers += 1; - return symbol, ok; - case Index_Expr: - indexed, ok := resolve_type_expression(ast_context, v.expr); + case ^Pointer_Type: + symbol, ok := resolve_type_expression(ast_context, v.elem) + symbol.pointers += 1 + return symbol, ok + case ^Multi_Pointer_Type: + symbol, ok := resolve_type_expression(ast_context, v.elem) + symbol.pointers += 1 + return symbol, ok + case ^Index_Expr: + indexed, ok := resolve_type_expression(ast_context, v.expr) if !ok { - return {}, false; + return {}, false } - symbol: index.Symbol; + symbol: index.Symbol #partial switch v2 in indexed.value { case index.SymbolDynamicArrayValue: - symbol, ok = resolve_type_expression(ast_context, v2.expr); + symbol, ok = resolve_type_expression(ast_context, v2.expr) case index.SymbolSliceValue: - symbol, ok = resolve_type_expression(ast_context, v2.expr); + symbol, ok = resolve_type_expression(ast_context, v2.expr) case index.SymbolFixedArrayValue: - symbol, ok = resolve_type_expression(ast_context, v2.expr); + symbol, ok = resolve_type_expression(ast_context, v2.expr) case index.SymbolMapValue: - symbol, ok = resolve_type_expression(ast_context, v2.value); + symbol, ok = resolve_type_expression(ast_context, v2.value) } - symbol.type = indexed.type; + symbol.type = indexed.type - return symbol, ok; - case Call_Expr: - ast_context.call = cast(^Call_Expr)node; - return resolve_type_expression(ast_context, v.expr); - case Implicit_Selector_Expr: - return index.Symbol {}, false; - case Selector_Call_Expr: - return resolve_type_expression(ast_context, v.expr); - case Selector_Expr: + return symbol, ok + case ^Call_Expr: + ast_context.call = cast(^Call_Expr)node + return resolve_type_expression(ast_context, v.expr) + case ^Implicit_Selector_Expr: + return index.Symbol {}, false + case ^Selector_Call_Expr: + return resolve_type_expression(ast_context, v.expr) + case ^Selector_Expr: if selector, ok := resolve_type_expression(ast_context, v.expr); ok { - ast_context.use_locals = false; + ast_context.use_locals = false #partial switch s in selector.value { case index.SymbolFixedArrayValue: - components_count := 0; + components_count := 0 for c in v.field.name { if c == 'x' || c == 'y' || c == 'z' || c == 'w' || c == 'r' || c == 'g' || c == 'b' || c == 'a' { - components_count += 1; + components_count += 1 } } if components_count == 0 { - return {}, false; + return {}, false } if components_count == 1 { if selector.pkg != "" { - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg } else { - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package } - symbol, ok := resolve_type_expression(ast_context, s.expr); - symbol.type = .Variable; - return symbol, ok; + symbol, ok := resolve_type_expression(ast_context, s.expr) + symbol.type = .Variable + return symbol, ok } else { value := index.SymbolFixedArrayValue { expr = s.expr, len = make_int_basic_value(ast_context, components_count), - }; - selector.value = value; - selector.type = .Variable; - return selector, true; + } + selector.value = value + selector.type = .Variable + return selector, true } case index.SymbolProcedureValue: if len(s.return_types) == 1 { - selector_expr := index.new_type(ast.Selector_Expr, s.return_types[0].node.pos, s.return_types[0].node.end, context.temp_allocator); - selector_expr.expr = s.return_types[0].type; - selector_expr.field = v.field; - return resolve_type_expression(ast_context, selector_expr); + selector_expr := index.new_type(ast.Selector_Expr, s.return_types[0].node.pos, s.return_types[0].node.end, context.temp_allocator) + selector_expr.expr = s.return_types[0].type + selector_expr.field = v.field + return resolve_type_expression(ast_context, selector_expr) } case index.SymbolStructValue: if selector.pkg != "" { - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg } else { - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package } for name, i in s.names { if v.field != nil && name == v.field.name { - ast_context.field_name = v.field.name; - symbol, ok := resolve_type_expression(ast_context, s.types[i]); - symbol.type = .Variable; - return symbol, ok; + ast_context.field_name = v.field.name + symbol, ok := resolve_type_expression(ast_context, s.types[i]) + symbol.type = .Variable + return symbol, ok } } case index.SymbolPackageValue: - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg if v.field != nil { - return resolve_symbol_return(ast_context, index.lookup(v.field.name, selector.pkg)); + return resolve_symbol_return(ast_context, index.lookup(v.field.name, selector.pkg)) } else { - return index.Symbol {}, false; + return index.Symbol {}, false } } } else { - return index.Symbol {}, false; + return index.Symbol {}, false } case: - log.warnf("default node kind, resolve_type_expression: %T", v); + log.warnf("default node kind, resolve_type_expression: %T", v) if v == nil { - return {}, false; + return {}, false } } - return index.Symbol {}, false; + return index.Symbol {}, false } store_local :: proc(ast_context: ^AstContext, expr: ^ast.Expr, offset: int, name: string, id := 0) { - local_stack := &ast_context.locals[id][name]; + local_stack := &ast_context.locals[id][name] if local_stack == nil { - locals := &ast_context.locals[id]; - locals[name] = make([dynamic]DocumentLocal, ast_context.allocator); - local_stack = &locals[name]; + locals := &ast_context.locals[id] + locals[name] = make([dynamic]DocumentLocal, ast_context.allocator) + local_stack = &locals[name] } - append(local_stack, DocumentLocal {expr = expr, offset = offset, id = id}); + append(local_stack, DocumentLocal {expr = expr, offset = offset, id = id}) } add_local_group :: proc(ast_context: ^AstContext, id: int) { - ast_context.locals[id] = make(map[string][dynamic]DocumentLocal, 100, ast_context.allocator); + ast_context.locals[id] = make(map[string][dynamic]DocumentLocal, 100, ast_context.allocator) } clear_local_group :: proc(ast_context: ^AstContext, id: int) { - ast_context.locals[id] = {}; + ast_context.locals[id] = {} } get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.Expr { - previous := 0; + previous := 0 //is the local we are getting being declared? if ast_context.value_decl != nil { for value_decl_name in ast_context.value_decl.names { - if ident, ok := value_decl_name.derived.(ast.Ident); ok { + if ident, ok := value_decl_name.derived.(^ast.Ident); ok { if ident.name == name { - previous = 1; - break; + previous = 1 + break } } } @@ -1085,16 +1083,16 @@ get_local :: proc(ast_context: ^AstContext, offset: int, name: string) -> ^ast.E for i := len(local_stack) - 1; i >= 0; i -= 1 { if local_stack[i].offset <= offset { if i - previous < 0 { - return nil; + return nil } else { - return local_stack[i - previous].expr; + return local_stack[i - previous].expr } } } } } - return nil; + return nil } get_local_offset :: proc(ast_context: ^AstContext, offset: int, name: string) -> int { @@ -1103,40 +1101,40 @@ get_local_offset :: proc(ast_context: ^AstContext, offset: int, name: string) -> for i := len(local_stack) - 1; i >= 0; i -= 1 { if local_stack[i].offset <= offset { if i < 0 { - return -1; + return -1 } else { - return local_stack[i].offset; + return local_stack[i].offset } } } } } - return -1; + return -1 } resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (index.Symbol, bool) { - using ast; + using ast if ast_context.recursion_counter > 15 { - log.error("Recursion passed 15 attempts - giving up"); - return {}, false; + log.error("Recursion passed 15 attempts - giving up") + return {}, false } - saved_package := ast_context.current_package; + saved_package := ast_context.current_package defer { - ast_context.current_package = saved_package; + ast_context.current_package = saved_package } - ast_context.recursion_counter += 1; + ast_context.recursion_counter += 1 defer { - ast_context.recursion_counter -= 1; + ast_context.recursion_counter -= 1 } if pkg, ok := ast_context.in_package[node.name]; ok { - ast_context.current_package = pkg; + ast_context.current_package = pkg } if _, ok := ast_context.parameters[node.name]; ok { @@ -1146,152 +1144,152 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i type = .Package, pkg = imp.name, value = index.SymbolPackageValue {}, - }; + } - return symbol, true; + return symbol, true } } } //note(Daniel, if global and local ends up being 100% same just make a function that takes the map) if local := get_local(ast_context, node.pos.offset, node.name); local != nil && ast_context.use_locals { - is_distinct := false; + is_distinct := false - if dist, ok := local.derived.(ast.Distinct_Type); ok { + if dist, ok := local.derived.(^ast.Distinct_Type); ok { if dist.type != nil { - local = dist.type; - is_distinct = true; - } - } - - return_symbol: index.Symbol; - ok: bool; - - switch v in local.derived { - case Ident: - return_symbol, ok = resolve_type_identifier(ast_context, v); - case Union_Type: - return_symbol, ok = make_symbol_union_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Enum_Type: - return_symbol, ok = make_symbol_enum_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Struct_Type: - return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Bit_Set_Type: - return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Proc_Lit: + local = dist.type + is_distinct = true + } + } + + return_symbol: index.Symbol + ok: bool + + #partial switch v in local.derived { + case ^Ident: + return_symbol, ok = resolve_type_identifier(ast_context, v^) + case ^Union_Type: + return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Enum_Type: + return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Struct_Type: + return_symbol, ok = make_symbol_struct_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Bit_Set_Type: + return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Proc_Lit: if !v.type.generic { - return_symbol, ok = make_symbol_procedure_from_ast(ast_context, local, v.type^, node.name), true; + return_symbol, ok = make_symbol_procedure_from_ast(ast_context, local, v.type^, node.name), true } else { - if return_symbol, ok = resolve_generic_function(ast_context, v); !ok { - return_symbol, ok = make_symbol_procedure_from_ast(ast_context, local, v.type^, node.name), true; + if return_symbol, ok = resolve_generic_function(ast_context, v^); !ok { + return_symbol, ok = make_symbol_procedure_from_ast(ast_context, local, v.type^, node.name), true } } - case Proc_Group: - return_symbol, ok = resolve_function_overload(ast_context, v); - case Array_Type: - return_symbol, ok = make_symbol_array_from_ast(ast_context, v), true; - case Dynamic_Array_Type: - return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v), true; - case Map_Type: - return_symbol, ok = make_symbol_map_from_ast(ast_context, v), true; - case Basic_Lit: - return_symbol, ok = resolve_basic_lit(ast_context, v); - return_symbol.name = node.name; - return_symbol.type = ast_context.variables[node.name] ? .Variable : .Constant; + case ^Proc_Group: + return_symbol, ok = resolve_function_overload(ast_context, v^) + case ^Array_Type: + return_symbol, ok = make_symbol_array_from_ast(ast_context, v^), true + case ^Dynamic_Array_Type: + return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^), true + case ^Map_Type: + return_symbol, ok = make_symbol_map_from_ast(ast_context, v^), true + case ^Basic_Lit: + return_symbol, ok = resolve_basic_lit(ast_context, v^) + return_symbol.name = node.name + return_symbol.type = ast_context.variables[node.name] ? .Variable : .Constant case: - return_symbol, ok = resolve_type_expression(ast_context, local); + return_symbol, ok = resolve_type_expression(ast_context, local) } if is_distinct { - return_symbol.name = node.name; - return_symbol.flags |= {.Distinct}; + return_symbol.name = node.name + return_symbol.flags |= {.Distinct} } if is_variable, ok := ast_context.variables[node.name]; ok && is_variable { - return_symbol.type = .Variable; + return_symbol.type = .Variable } - return return_symbol, ok; + return return_symbol, ok } else if global, ok := ast_context.globals[node.name]; ast_context.use_globals && ok { - is_distinct := false; + is_distinct := false - if dist, ok := global.expr.derived.(ast.Distinct_Type); ok { + if dist, ok := global.expr.derived.(^ast.Distinct_Type); ok { if dist.type != nil { - global.expr = dist.type; - is_distinct = true; - } - } - - return_symbol: index.Symbol; - ok: bool; - - switch v in global.expr.derived { - case Ident: - return_symbol, ok = resolve_type_identifier(ast_context, v); - case Struct_Type: - return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Bit_Set_Type: - return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Union_Type: - return_symbol, ok = make_symbol_union_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Enum_Type: - return_symbol, ok = make_symbol_enum_from_ast(ast_context, v, node.name), true; - return_symbol.name = node.name; - case Proc_Lit: + global.expr = dist.type + is_distinct = true + } + } + + return_symbol: index.Symbol + ok: bool + + #partial switch v in global.expr.derived { + case ^Ident: + return_symbol, ok = resolve_type_identifier(ast_context, v^) + case ^Struct_Type: + return_symbol, ok = make_symbol_struct_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Bit_Set_Type: + return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Union_Type: + return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Enum_Type: + return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node.name), true + return_symbol.name = node.name + case ^Proc_Lit: if !v.type.generic { - return_symbol, ok = make_symbol_procedure_from_ast(ast_context, global.expr, v.type^, node.name), true; + return_symbol, ok = make_symbol_procedure_from_ast(ast_context, global.expr, v.type^, node.name), true } else { - if return_symbol, ok = resolve_generic_function(ast_context, v); !ok { - return_symbol, ok = make_symbol_procedure_from_ast(ast_context, global.expr, v.type^, node.name), true; + if return_symbol, ok = resolve_generic_function(ast_context, v^); !ok { + return_symbol, ok = make_symbol_procedure_from_ast(ast_context, global.expr, v.type^, node.name), true } } - case Proc_Group: - return_symbol, ok = resolve_function_overload(ast_context, v); - case Array_Type: - return_symbol, ok = make_symbol_array_from_ast(ast_context, v), true; - case Dynamic_Array_Type: - return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v), true; - case Basic_Lit: - return_symbol, ok = resolve_basic_lit(ast_context, v); - return_symbol.name = node.name; - return_symbol.type = global.mutable ? .Variable : .Constant; + case ^Proc_Group: + return_symbol, ok = resolve_function_overload(ast_context, v^) + case ^Array_Type: + return_symbol, ok = make_symbol_array_from_ast(ast_context, v^), true + case ^Dynamic_Array_Type: + return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^), true + case ^Basic_Lit: + return_symbol, ok = resolve_basic_lit(ast_context, v^) + return_symbol.name = node.name + return_symbol.type = global.mutable ? .Variable : .Constant case: - return_symbol, ok = resolve_type_expression(ast_context, global.expr); + return_symbol, ok = resolve_type_expression(ast_context, global.expr) } if is_distinct { - return_symbol.name = node.name; - return_symbol.flags |= {.Distinct}; + return_symbol.name = node.name + return_symbol.flags |= {.Distinct} } if is_variable, ok := ast_context.variables[node.name]; ok && is_variable { - return_symbol.type = .Variable; + return_symbol.type = .Variable } - return_symbol.doc = common.get_doc(global.docs, ast_context.allocator); + return_symbol.doc = common.get_doc(global.docs, ast_context.allocator) - return return_symbol, ok; + return return_symbol, ok } else if node.name == "context" { for built in index.indexer.builtin_packages { if symbol, ok := index.lookup("Context", built); ok { - symbol.type = .Variable; - return symbol, ok; + symbol.type = .Variable + return symbol, ok } } } else if v, ok := common.keyword_map[node.name]; ok { //keywords - ident := index.new_type(Ident, node.pos, node.end, ast_context.allocator); - ident.name = node.name; + ident := index.new_type(Ident, node.pos, node.end, ast_context.allocator) + ident.name = node.name - symbol: index.Symbol; + symbol: index.Symbol switch ident.name { case "true", "false": @@ -1302,7 +1300,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i value = index.SymbolUntypedValue { type = .Bool, }, - }; + } case: symbol = index.Symbol { type = .Keyword, @@ -1312,10 +1310,10 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i value = index.SymbolBasicValue { ident = ident, }, - }; + } } - return symbol, true; + return symbol, true } else { //right now we replace the package ident with the absolute directory name, so it should have '/' which is not a valid ident character if strings.contains(node.name, "/") { @@ -1323,9 +1321,9 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i type = .Package, pkg = node.name, value = index.SymbolPackageValue {}, - }; + } - return symbol, true; + return symbol, true } else { //part of the ast so we check the imports of the document for imp in ast_context.imports { @@ -1334,23 +1332,23 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i type = .Package, pkg = imp.name, value = index.SymbolPackageValue {}, - }; + } - return symbol, true; + return symbol, true } } } //last option is to check the index if symbol, ok := index.lookup(node.name, ast_context.current_package); ok { - return resolve_symbol_return(ast_context, symbol); + return resolve_symbol_return(ast_context, symbol) } //If we are resolving a symbol that is in the document package, then we'll check the builtin packages. if ast_context.current_package == ast_context.document_package { for built in index.indexer.builtin_packages { if symbol, ok := index.lookup(node.name, built); ok { - return resolve_symbol_return(ast_context, symbol); + return resolve_symbol_return(ast_context, symbol) } } } @@ -1360,59 +1358,59 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i for imp in ast_context.imports { if strings.compare(imp.base, u) == 0 { if symbol, ok := index.lookup(node.name, imp.name); ok { - return resolve_symbol_return(ast_context, symbol); + return resolve_symbol_return(ast_context, symbol) } } } } } - return index.Symbol {}, false; + return index.Symbol {}, false } resolve_ident_is_package :: proc(ast_context: ^AstContext, node: ast.Ident) -> bool { if strings.contains(node.name, "/") { - return true; + return true } else { for imp in ast_context.imports { if imp.base == node.name { - return true; + return true } } } - return false; + return false } expand_struct_usings :: proc(ast_context: ^AstContext, symbol: index.Symbol, value: index.SymbolStructValue) -> index.SymbolStructValue { - names := slice.to_dynamic(value.names, ast_context.allocator); - types := slice.to_dynamic(value.types, ast_context.allocator); + names := slice.to_dynamic(value.names, ast_context.allocator) + types := slice.to_dynamic(value.types, ast_context.allocator) for k, v in value.usings { - ast_context.current_package = symbol.pkg; + ast_context.current_package = symbol.pkg - field_expr: ^ast.Expr; + field_expr: ^ast.Expr for name, i in value.names { if name == k && v { - field_expr = value.types[i]; + field_expr = value.types[i] } } if field_expr == nil { - continue; + continue } if s, ok := resolve_type_expression(ast_context, field_expr); ok { if struct_value, ok := s.value.(index.SymbolStructValue); ok { for name in struct_value.names { - append(&names, name); + append(&names, name) } for type in struct_value.types { - append(&types, type); + append(&types, type) } } } @@ -1421,126 +1419,126 @@ expand_struct_usings :: proc(ast_context: ^AstContext, symbol: index.Symbol, val return { names = names[:], types = types[:], - }; + } } resolve_symbol_return :: proc(ast_context: ^AstContext, symbol: index.Symbol, ok := true) -> (index.Symbol, bool) { if !ok { - return symbol, ok; + return symbol, ok } - symbol := symbol; + symbol := symbol if symbol.type == .Unresolved { - resolve_unresolved_symbol(ast_context, &symbol); + resolve_unresolved_symbol(ast_context, &symbol) } #partial switch v in &symbol.value { case index.SymbolProcedureGroupValue: - if symbol, ok := resolve_function_overload(ast_context, v.group.derived.(ast.Proc_Group)); ok { - return symbol, true; + if symbol, ok := resolve_function_overload(ast_context, v.group.derived.(^ast.Proc_Group)^); ok { + return symbol, true } else { - return symbol, false; + return symbol, false } case index.SymbolProcedureValue: if v.generic { if resolved_symbol, ok := resolve_generic_function(ast_context, v.arg_types, v.return_types); ok { - return resolved_symbol, ok; + return resolved_symbol, ok } else { - return symbol, true; + return symbol, true } } else { - return symbol, true; + return symbol, true } case index.SymbolUnionValue: if v.poly != nil { //Todo(daniel): Maybe change the function to return a new symbol instead of referencing it. //resolving the poly union means changing the type, so we do a copy of it. - types := make([dynamic]^ast.Expr, ast_context.allocator); - append_elems(&types, ..v.types); - v.types = types[:]; - resolve_poly_union(ast_context, v.poly, &symbol); + types := make([dynamic]^ast.Expr, ast_context.allocator) + append_elems(&types, ..v.types) + v.types = types[:] + resolve_poly_union(ast_context, v.poly, &symbol) } - return symbol, ok; + return symbol, ok case index.SymbolStructValue: if v.poly != nil { //Todo(daniel): Maybe change the function to return a new symbol instead of referencing it. //resolving the struct union means changing the type, so we do a copy of it. - types := make([dynamic]^ast.Expr, ast_context.allocator); - append_elems(&types, ..v.types); - v.types = types[:]; - resolve_poly_struct(ast_context, v.poly, &symbol); + types := make([dynamic]^ast.Expr, ast_context.allocator) + append_elems(&types, ..v.types) + v.types = types[:] + resolve_poly_struct(ast_context, v.poly, &symbol) } //expand the types and names from the using - can't be done while indexing without complicating everything(this also saves memory) if len(v.usings) > 0 { - expanded := symbol; - expanded.value = expand_struct_usings(ast_context, symbol, v); - return expanded, true; + expanded := symbol + expanded.value = expand_struct_usings(ast_context, symbol, v) + return expanded, true } else { - return symbol, true; + return symbol, true } case index.SymbolGenericValue: - ret, ok := resolve_type_expression(ast_context, v.expr); - return ret, ok; + ret, ok := resolve_type_expression(ast_context, v.expr) + return ret, ok } - return symbol, true; + return symbol, true } resolve_unresolved_symbol :: proc(ast_context: ^AstContext, symbol: ^index.Symbol) { - using index; + using index if symbol.type != .Unresolved { - return; + return } #partial switch v in symbol.value { case SymbolStructValue: - symbol.type = .Struct; + symbol.type = .Struct case SymbolPackageValue: - symbol.type = .Package; + symbol.type = .Package case SymbolProcedureValue, SymbolProcedureGroupValue: - symbol.type = .Function; + symbol.type = .Function case SymbolUnionValue: - symbol.type = .Enum; + symbol.type = .Enum case SymbolEnumValue: - symbol.type = .Enum; + symbol.type = .Enum case SymbolBitSetValue: - symbol.type = .Enum; + symbol.type = .Enum case index.SymbolGenericValue: - ast_context.current_package = symbol.pkg; + ast_context.current_package = symbol.pkg if ret, ok := resolve_type_expression(ast_context, v.expr); ok { - symbol.type = ret.type; - symbol.signature = ret.signature; + symbol.type = ret.type + symbol.signature = ret.signature } } } resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (index.Symbol, bool) { - symbol: index.Symbol; + symbol: index.Symbol if local := get_local(ast_context, node.pos.offset, node.name); local != nil { - symbol.range = common.get_token_range(get_local(ast_context, node.pos.offset, node.name), ast_context.file.src); - return symbol, true; + symbol.range = common.get_token_range(get_local(ast_context, node.pos.offset, node.name), ast_context.file.src) + return symbol, true } else if global, ok := ast_context.globals[node.name]; ok { - symbol.range = common.get_token_range(global.expr, ast_context.file.src); - return symbol, true; + symbol.range = common.get_token_range(global.expr, ast_context.file.src) + return symbol, true } if symbol, ok := index.lookup(node.name, ast_context.document_package); ok { - return symbol, ok; + return symbol, ok } - usings := get_using_packages(ast_context); + usings := get_using_packages(ast_context) for pkg in usings { if symbol, ok := index.lookup(node.name, pkg); ok { - return symbol, ok; + return symbol, ok } } - return {}, false; + return {}, false } resolve_first_symbol_from_binary_expression :: proc(ast_context: ^AstContext, binary: ^ast.Binary_Expr) -> (index.Symbol, bool) { @@ -1548,87 +1546,87 @@ resolve_first_symbol_from_binary_expression :: proc(ast_context: ^AstContext, bi if binary.left != nil { - if ident, ok := binary.left.derived.(ast.Ident); ok { - if s, ok := resolve_type_identifier(ast_context, ident); ok { - return s, ok; + if ident, ok := binary.left.derived.(^ast.Ident); ok { + if s, ok := resolve_type_identifier(ast_context, ident^); ok { + return s, ok } - } else if _, ok := binary.left.derived.(ast.Binary_Expr); ok { + } else if _, ok := binary.left.derived.(^ast.Binary_Expr); ok { if s, ok := resolve_first_symbol_from_binary_expression(ast_context, cast(^ast.Binary_Expr)binary.left); ok { - return s, ok; + return s, ok } } } if binary.right != nil { - if ident, ok := binary.right.derived.(ast.Ident); ok { - if s, ok := resolve_type_identifier(ast_context, ident); ok { - return s, ok; + if ident, ok := binary.right.derived.(^ast.Ident); ok { + if s, ok := resolve_type_identifier(ast_context, ident^); ok { + return s, ok } - } else if _, ok := binary.right.derived.(ast.Binary_Expr); ok { + } else if _, ok := binary.right.derived.(^ast.Binary_Expr); ok { if s, ok := resolve_first_symbol_from_binary_expression(ast_context, cast(^ast.Binary_Expr)binary.right); ok { - return s, ok; + return s, ok } } } - return {}, false; + return {}, false } find_position_in_call_param :: proc(ast_context: ^AstContext, call: ast.Call_Expr) -> (int, bool) { if call.args == nil { - return 0, false; + return 0, false } for arg, i in call.args { if position_in_node(arg, ast_context.position) { - return i, true; + return i, true } } - return len(call.args) - 1, true; + return len(call.args) - 1, true } make_pointer_ast :: proc(ast_context: ^AstContext, elem: ^ast.Expr) -> ^ast.Pointer_Type { - pointer := index.new_type(ast.Pointer_Type, elem.pos, elem.end, ast_context.allocator); - pointer.elem = elem; - return pointer; + pointer := index.new_type(ast.Pointer_Type, elem.pos, elem.end, ast_context.allocator) + pointer.elem = elem + return pointer } make_bool_ast :: proc(ast_context: ^AstContext) -> ^ast.Ident { - ident := index.new_type(ast.Ident, {}, {}, ast_context.allocator); - ident.name = "bool"; - return ident; + ident := index.new_type(ast.Ident, {}, {}, ast_context.allocator) + ident.name = "bool" + return ident } make_int_ast :: proc(ast_context: ^AstContext) -> ^ast.Ident { - ident := index.new_type(ast.Ident, {}, {}, ast_context.allocator); - ident.name = "int"; - return ident; + ident := index.new_type(ast.Ident, {}, {}, ast_context.allocator) + ident.name = "int" + return ident } make_int_basic_value :: proc(ast_context: ^AstContext, n: int) -> ^ast.Basic_Lit { - basic := index.new_type(ast.Basic_Lit, {}, {}, ast_context.allocator); - basic.tok.text = fmt.tprintf("%v", n); - return basic; + basic := index.new_type(ast.Basic_Lit, {}, {}, ast_context.allocator) + basic.tok.text = fmt.tprintf("%v", n) + return basic } get_package_from_node :: proc(node: ast.Node) -> string { - slashed, _ := filepath.to_slash(node.pos.file, context.temp_allocator); + slashed, _ := filepath.to_slash(node.pos.file, context.temp_allocator) - when ODIN_OS == "windows" { - ret := strings.to_lower(path.dir(slashed, context.temp_allocator), context.temp_allocator); + when ODIN_OS == .Windows { + ret := strings.to_lower(path.dir(slashed, context.temp_allocator), context.temp_allocator) } else { - ret := path.dir(slashed, context.temp_allocator); + ret := path.dir(slashed, context.temp_allocator) } - return ret; + return ret } get_using_packages :: proc(ast_context: ^AstContext) -> []string { - usings := make([]string, len(ast_context.usings), context.temp_allocator); + usings := make([]string, len(ast_context.usings), context.temp_allocator) if len(ast_context.usings) == 0 { - return usings; + return usings } //probably map instead @@ -1637,12 +1635,12 @@ get_using_packages :: proc(ast_context: ^AstContext) -> []string { for imp in ast_context.imports { if strings.compare(imp.base, u) == 0 { - usings[i] = imp.name; + usings[i] = imp.name } } } - return usings; + return usings } make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v: ast.Proc_Type, name: string) -> index.Symbol { @@ -1651,35 +1649,35 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v type = .Function, pkg = get_package_from_node(n^), name = name, - }; + } - return_types := make([dynamic]^ast.Field, ast_context.allocator); - arg_types := make([dynamic]^ast.Field, ast_context.allocator); + return_types := make([dynamic]^ast.Field, ast_context.allocator) + arg_types := make([dynamic]^ast.Field, ast_context.allocator) if v.results != nil { for ret in v.results.list { - append(&return_types, ret); + append(&return_types, ret) } } if v.params != nil { for param in v.params.list { - append(&arg_types, param); + append(&arg_types, param) } } if expr, ok := ast_context.globals[name]; ok { if expr.deprecated { - symbol.flags |= {.Distinct}; + symbol.flags |= {.Distinct} } } symbol.value = index.SymbolProcedureValue { return_types = return_types[:], arg_types = arg_types[:], - }; + } - return symbol; + return symbol } make_symbol_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Array_Type) -> index.Symbol { @@ -1687,20 +1685,20 @@ make_symbol_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Array_Type) range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, pkg = get_package_from_node(v.node), - }; + } if v.len != nil { symbol.value = index.SymbolFixedArrayValue { expr = v.elem, len = v.len, - }; + } } else { symbol.value = index.SymbolSliceValue { expr = v.elem, - }; + } } - return symbol; + return symbol } make_symbol_dynamic_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Dynamic_Array_Type) -> index.Symbol { @@ -1708,13 +1706,13 @@ make_symbol_dynamic_array_from_ast :: proc(ast_context: ^AstContext, v: ast.Dyna range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, pkg = get_package_from_node(v.node), - }; + } symbol.value = index.SymbolDynamicArrayValue { expr = v.elem, - }; + } - return symbol; + return symbol } make_symbol_map_from_ast :: proc(ast_context: ^AstContext, v: ast.Map_Type) -> index.Symbol { @@ -1722,14 +1720,14 @@ make_symbol_map_from_ast :: proc(ast_context: ^AstContext, v: ast.Map_Type) -> i range = common.get_token_range(v.node, ast_context.file.src), type = .Variable, pkg = get_package_from_node(v.node), - }; + } symbol.value = index.SymbolMapValue { key = v.key, value = v.value, - }; + } - return symbol; + return symbol } make_symbol_basic_type_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v: ^ast.Ident) -> index.Symbol { @@ -1737,13 +1735,13 @@ make_symbol_basic_type_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, range = common.get_token_range(n^, ast_context.file.src), type = .Variable, pkg = get_package_from_node(n^), - }; + } symbol.value = index.SymbolBasicValue { ident = v, - }; + } - return symbol; + return symbol } make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type, ident: string, inlined := false) -> index.Symbol { @@ -1752,22 +1750,22 @@ make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type, type = .Union, pkg = get_package_from_node(v.node), name = ident, - }; + } if inlined { - symbol.flags |= {.Anonymous}; - symbol.name = "union"; + symbol.flags |= {.Anonymous} + symbol.name = "union" } symbol.value = index.SymbolUnionValue { types = v.variants, - }; + } if v.poly_params != nil { - resolve_poly_union(ast_context, v.poly_params, &symbol); + resolve_poly_union(ast_context, v.poly_params, &symbol) } - return symbol; + return symbol } make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, ident: string, inlined := false) -> index.Symbol { @@ -1776,33 +1774,33 @@ make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, id type = .Enum, name = ident, pkg = get_package_from_node(v.node), - }; + } if inlined { - symbol.flags |= {.Anonymous}; - symbol.name = "enum"; + symbol.flags |= {.Anonymous} + symbol.name = "enum" } - names := make([dynamic]string, ast_context.allocator); + names := make([dynamic]string, ast_context.allocator) for n in v.fields { - if ident, ok := n.derived.(ast.Ident); ok { - append(&names, ident.name); - } else if field, ok := n.derived.(ast.Field_Value); ok { - if ident, ok := field.field.derived.(ast.Ident); ok { - append(&names, ident.name); - } else if binary, ok := field.field.derived.(ast.Binary_Expr); ok { - append(&names, binary.left.derived.(ast.Ident).name); + if ident, ok := n.derived.(^ast.Ident); ok { + append(&names, ident.name) + } else if field, ok := n.derived.(^ast.Field_Value); ok { + if ident, ok := field.field.derived.(^ast.Ident); ok { + append(&names, ident.name) + } else if binary, ok := field.field.derived.(^ast.Binary_Expr); ok { + append(&names, binary.left.derived.(^ast.Ident).name) } } } symbol.value = index.SymbolEnumValue { names = names[:], - }; + } - return symbol; + return symbol } make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Type, ident: string, inlined := false) -> index.Symbol { @@ -1811,18 +1809,18 @@ make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Typ type = .Enum, name = ident, pkg = get_package_from_node(v.node), - }; + } if inlined { - symbol.flags |= {.Anonymous}; - symbol.name = "bitset"; + symbol.flags |= {.Anonymous} + symbol.name = "bitset" } symbol.value = index.SymbolBitSetValue { expr = v.elem, - }; + } - return symbol; + return symbol } make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type, ident: string, inlined := false) -> index.Symbol { @@ -1831,25 +1829,25 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type type = .Struct, pkg = get_package_from_node(v.node), name = ident, - }; + } if inlined { - symbol.flags |= {.Anonymous}; - symbol.name = "struct"; + symbol.flags |= {.Anonymous} + symbol.name = "struct" } - names := make([dynamic]string, ast_context.allocator); - types := make([dynamic]^ast.Expr, ast_context.allocator); - usings := make(map[string]bool, 0, ast_context.allocator); + names := make([dynamic]string, ast_context.allocator) + types := make([dynamic]^ast.Expr, ast_context.allocator) + usings := make(map[string]bool, 0, ast_context.allocator) for field in v.fields.list { for n in field.names { - if identifier, ok := n.derived.(ast.Ident); ok { - append(&names, identifier.name); - append(&types, index.clone_type(field.type, ast_context.allocator, nil)); + if identifier, ok := n.derived.(^ast.Ident); ok { + append(&names, identifier.name) + append(&types, index.clone_type(field.type, ast_context.allocator, nil)) if .Using in field.flags { - usings[identifier.name] = true; + usings[identifier.name] = true } } } @@ -1859,73 +1857,73 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type names = names[:], types = types[:], usings = usings, - }; + } if v.poly_params != nil { - resolve_poly_struct(ast_context, v.poly_params, &symbol); + resolve_poly_struct(ast_context, v.poly_params, &symbol) } //TODO change the expand to not double copy the array, but just pass the dynamic arrays if len(usings) > 0 { - symbol.value = expand_struct_usings(ast_context, symbol, symbol.value.(index.SymbolStructValue)); + symbol.value = expand_struct_usings(ast_context, symbol, symbol.value.(index.SymbolStructValue)) } - return symbol; + return symbol } resolve_poly_union :: proc(ast_context: ^AstContext, poly_params: ^ast.Field_List, symbol: ^index.Symbol) { if ast_context.call == nil { - return; + return } - symbol_value := &symbol.value.(index.SymbolUnionValue); + symbol_value := &symbol.value.(index.SymbolUnionValue) if symbol_value == nil { - return; + return } - i := 0; + i := 0 - poly_map := make(map[string]^ast.Expr, 0, context.temp_allocator); + poly_map := make(map[string]^ast.Expr, 0, context.temp_allocator) for param in poly_params.list { for name in param.names { if len(ast_context.call.args) <= i { - break; + break } if param.type == nil { - continue; + continue } - if poly, ok := param.type.derived.(ast.Typeid_Type); ok { - if ident, ok := name.derived.(ast.Ident); ok { - poly_map[ident.name] = ast_context.call.args[i]; - } else if poly, ok := name.derived.(ast.Poly_Type); ok { + if poly, ok := param.type.derived.(^ast.Typeid_Type); ok { + if ident, ok := name.derived.(^ast.Ident); ok { + poly_map[ident.name] = ast_context.call.args[i] + } else if poly, ok := name.derived.(^ast.Poly_Type); ok { if poly.type != nil { - poly_map[poly.type.name] = ast_context.call.args[i]; + poly_map[poly.type.name] = ast_context.call.args[i] } } } - i += 1; + i += 1 } } for type, i in symbol_value.types { - if ident, ok := type.derived.(ast.Ident); ok { + if ident, ok := type.derived.(^ast.Ident); ok { if expr, ok := poly_map[ident.name]; ok { - symbol_value.types[i] = expr; + symbol_value.types[i] = expr } - } else if call_expr, ok := type.derived.(ast.Call_Expr); ok { + } else if call_expr, ok := type.derived.(^ast.Call_Expr); ok { if call_expr.args == nil { - continue; + continue } for arg, i in call_expr.args { - if ident, ok := arg.derived.(ast.Ident); ok { + if ident, ok := arg.derived.(^ast.Ident); ok { if expr, ok := poly_map[ident.name]; ok { - symbol_value.types[i] = expr; + symbol_value.types[i] = expr } } } @@ -1935,57 +1933,57 @@ resolve_poly_union :: proc(ast_context: ^AstContext, poly_params: ^ast.Field_Lis resolve_poly_struct :: proc(ast_context: ^AstContext, poly_params: ^ast.Field_List, symbol: ^index.Symbol) { if ast_context.call == nil { - return; + return } - symbol_value := &symbol.value.(index.SymbolStructValue); + symbol_value := &symbol.value.(index.SymbolStructValue) if symbol_value == nil { - return; + return } - i := 0; + i := 0 - poly_map := make(map[string]^ast.Expr, 0, context.temp_allocator); + poly_map := make(map[string]^ast.Expr, 0, context.temp_allocator) for param in poly_params.list { for name in param.names { if len(ast_context.call.args) <= i { - break; + break } if param.type == nil { - continue; + continue } - if poly, ok := param.type.derived.(ast.Typeid_Type); ok { - if ident, ok := name.derived.(ast.Ident); ok { - poly_map[ident.name] = ast_context.call.args[i]; - } else if poly, ok := name.derived.(ast.Poly_Type); ok { + if poly, ok := param.type.derived.(^ast.Typeid_Type); ok { + if ident, ok := name.derived.(^ast.Ident); ok { + poly_map[ident.name] = ast_context.call.args[i] + } else if poly, ok := name.derived.(^ast.Poly_Type); ok { if poly.type != nil { - poly_map[poly.type.name] = ast_context.call.args[i]; + poly_map[poly.type.name] = ast_context.call.args[i] } } } - i += 1; + i += 1 } } for type, i in symbol_value.types { - if ident, ok := type.derived.(ast.Ident); ok { + if ident, ok := type.derived.(^ast.Ident); ok { if expr, ok := poly_map[ident.name]; ok { - symbol_value.types[i] = expr; + symbol_value.types[i] = expr } - } else if call_expr, ok := type.derived.(ast.Call_Expr); ok { + } else if call_expr, ok := type.derived.(^ast.Call_Expr); ok { if call_expr.args == nil { - continue; + continue } for arg, i in call_expr.args { - if ident, ok := arg.derived.(ast.Ident); ok { + if ident, ok := arg.derived.(^ast.Ident); ok { if expr, ok := poly_map[ident.name]; ok { - symbol_value.types[i] = expr; + symbol_value.types[i] = expr } } } @@ -1994,149 +1992,149 @@ resolve_poly_struct :: proc(ast_context: ^AstContext, poly_params: ^ast.Field_Li } get_globals :: proc(file: ast.File, ast_context: ^AstContext) { - ast_context.variables["context"] = true; + ast_context.variables["context"] = true - exprs := common.collect_globals(file); + exprs := common.collect_globals(file) for expr in exprs { - ast_context.variables[expr.name] = expr.mutable; - ast_context.globals[expr.name] = expr; + ast_context.variables[expr.name] = expr.mutable + ast_context.globals[expr.name] = expr } } get_generic_assignment :: proc(file: ast.File, value: ^ast.Expr, ast_context: ^AstContext, results: ^[dynamic]^ast.Expr) { - using ast; + using ast - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true - switch v in &value.derived { - case Call_Expr: - ast_context.call = cast(^ast.Call_Expr)value; + #partial switch v in value.derived { + case ^Call_Expr: + ast_context.call = cast(^ast.Call_Expr)value if symbol, ok := resolve_type_expression(ast_context, v.expr); ok { if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok { for ret in procedure.return_types { - append(results, ret.type); + append(results, ret.type) } } } - case Comp_Lit: + case ^Comp_Lit: if v.type != nil { - append(results, v.type); + append(results, v.type) } - case Array_Type: + case ^Array_Type: if v.elem != nil { - append(results, v.elem); + append(results, v.elem) } - case Dynamic_Array_Type: + case ^Dynamic_Array_Type: if v.elem != nil { - append(results, v.elem); + append(results, v.elem) } - case Selector_Expr: + case ^Selector_Expr: if v.expr != nil { - append(results, value); + append(results, value) } - case Type_Assertion: + case ^Type_Assertion: if v.type != nil { //This is the unique .? that can only be used with maybe - if unary, ok := v.type.derived.(ast.Unary_Expr); ok && unary.op.kind == .Question { - append(results, cast(^ast.Expr)&v.node); + if unary, ok := v.type.derived.(^ast.Unary_Expr); ok && unary.op.kind == .Question { + append(results, cast(^ast.Expr)&v.node) } else { - append(results, v.type); + append(results, v.type) } - b := make_bool_ast(ast_context); - b.pos.file = v.type.pos.file; - append(results, b); + b := make_bool_ast(ast_context) + b.pos.file = v.type.pos.file + append(results, b) } case: //log.debugf("default node get_generic_assignment %v", v); - append(results, value); + append(results, value) } } get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_context: ^AstContext) { - using ast; + using ast if len(value_decl.names) <= 0 { - return; + return } if value_decl.type != nil { for name, i in value_decl.names { - str := common.get_ast_node_string(value_decl.names[i], file.src); - ast_context.variables[str] = value_decl.is_mutable; - store_local(ast_context, value_decl.type, value_decl.end.offset, str, ast_context.local_id); + str := common.get_ast_node_string(value_decl.names[i], file.src) + ast_context.variables[str] = value_decl.is_mutable + store_local(ast_context, value_decl.type, value_decl.end.offset, str, ast_context.local_id) } - return; + return } - results := make([dynamic]^Expr, context.temp_allocator); + results := make([dynamic]^Expr, context.temp_allocator) for value in value_decl.values { - get_generic_assignment(file, value, ast_context, &results); + get_generic_assignment(file, value, ast_context, &results) } if len(results) == 0 { - return; + return } for name, i in value_decl.names { - result_i := min(len(results)-1, i); - str := common.get_ast_node_string(name, file.src); - ast_context.in_package[str] = get_package_from_node(results[result_i]); - store_local(ast_context, results[result_i], value_decl.end.offset, str, ast_context.local_id); - ast_context.variables[str] = value_decl.is_mutable; + result_i := min(len(results)-1, i) + str := common.get_ast_node_string(name, file.src) + ast_context.in_package[str] = get_package_from_node(results[result_i]^) + store_local(ast_context, results[result_i], value_decl.end.offset, str, ast_context.local_id) + ast_context.variables[str] = value_decl.is_mutable } } get_locals_stmt :: proc(file: ast.File, stmt: ^ast.Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext, save_assign := false) { - ast_context.use_locals = true; - ast_context.use_globals = true; - ast_context.current_package = ast_context.document_package; + ast_context.use_locals = true + ast_context.use_globals = true + ast_context.current_package = ast_context.document_package - using ast; + using ast if stmt == nil { - return; + return } if stmt.pos.offset > document_position.position { - return; - } - - switch v in stmt.derived { - case Value_Decl: - get_locals_value_decl(file, v, ast_context); - case Type_Switch_Stmt: - get_locals_type_switch_stmt(file, v, ast_context, document_position); - case Switch_Stmt: - get_locals_switch_stmt(file, v, ast_context, document_position); - case For_Stmt: - get_locals_for_stmt(file, v, ast_context, document_position); - case Inline_Range_Stmt: - get_locals_stmt(file, v.body, ast_context, document_position); - case Range_Stmt: - get_locals_for_range_stmt(file, v, ast_context, document_position); - case If_Stmt: - get_locals_if_stmt(file, v, ast_context, document_position); - case Block_Stmt: - get_locals_block_stmt(file, v, ast_context, document_position); - case Proc_Lit: - get_locals_stmt(file, v.body, ast_context, document_position); - case Assign_Stmt: + return + } + + #partial switch v in stmt.derived { + case ^Value_Decl: + get_locals_value_decl(file, v^, ast_context) + case ^Type_Switch_Stmt: + get_locals_type_switch_stmt(file, v^, ast_context, document_position) + case ^Switch_Stmt: + get_locals_switch_stmt(file, v^, ast_context, document_position) + case ^For_Stmt: + get_locals_for_stmt(file, v^, ast_context, document_position) + case ^Inline_Range_Stmt: + get_locals_stmt(file, v.body, ast_context, document_position) + case ^Range_Stmt: + get_locals_for_range_stmt(file, v^, ast_context, document_position) + case ^If_Stmt: + get_locals_if_stmt(file, v^, ast_context, document_position) + case ^Block_Stmt: + get_locals_block_stmt(file, v^, ast_context, document_position) + case ^Proc_Lit: + get_locals_stmt(file, v.body, ast_context, document_position) + case ^Assign_Stmt: if save_assign { - get_locals_assign_stmt(file, v, ast_context); - } - case Using_Stmt: - get_locals_using_stmt(v, ast_context); - case When_Stmt: - get_locals_stmt(file, v.else_stmt, ast_context, document_position); - get_locals_stmt(file, v.body, ast_context, document_position); - case Case_Clause: + get_locals_assign_stmt(file, v^, ast_context) + } + case ^Using_Stmt: + get_locals_using_stmt(v^, ast_context) + case ^When_Stmt: + get_locals_stmt(file, v.else_stmt, ast_context, document_position) + get_locals_stmt(file, v.body, ast_context, document_position) + case ^Case_Clause: for stmt in v.body { - get_locals_stmt(file, stmt, ast_context, document_position); + get_locals_stmt(file, stmt, ast_context, document_position) } case: //log.debugf("default node local stmt %v", v); @@ -2145,11 +2143,11 @@ get_locals_stmt :: proc(file: ast.File, stmt: ^ast.Stmt, ast_context: ^AstContex get_locals_block_stmt :: proc(file: ast.File, block: ast.Block_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { if !(block.pos.offset <= document_position.position && document_position.position <= block.end.offset) { - return; + return } for stmt in block.stmts { - get_locals_stmt(file, stmt, ast_context, document_position); + get_locals_stmt(file, stmt, ast_context, document_position) } } @@ -2158,17 +2156,17 @@ get_locals_using_stmt :: proc(stmt: ast.Using_Stmt, ast_context: ^AstContext) { if symbol, ok := resolve_type_expression(ast_context, u); ok { #partial switch v in symbol.value { case index.SymbolPackageValue: - if ident, ok := u.derived.(ast.Ident); ok { - append(&ast_context.usings, ident.name); + if ident, ok := u.derived.(^ast.Ident); ok { + append(&ast_context.usings, ident.name) } case index.SymbolStructValue: for name, i in v.names { - selector := index.new_type(ast.Selector_Expr, v.types[i].pos, v.types[i].end, context.temp_allocator); - selector.expr = u; - selector.field = index.new_type(ast.Ident, v.types[i].pos, v.types[i].end, context.temp_allocator); - selector.field.name = name; - store_local(ast_context, selector, 0, name, ast_context.local_id); - ast_context.variables[name] = true; + selector := index.new_type(ast.Selector_Expr, v.types[i].pos, v.types[i].end, context.temp_allocator) + selector.expr = u + selector.field = index.new_type(ast.Ident, v.types[i].pos, v.types[i].end, context.temp_allocator) + selector.field.name = name + store_local(ast_context, selector, 0, name, ast_context.local_id) + ast_context.variables[name] = true } } } @@ -2176,163 +2174,163 @@ get_locals_using_stmt :: proc(stmt: ast.Using_Stmt, ast_context: ^AstContext) { } get_locals_assign_stmt :: proc(file: ast.File, stmt: ast.Assign_Stmt, ast_context: ^AstContext) { - using ast; + using ast if stmt.lhs == nil || stmt.rhs == nil { - return; + return } - results := make([dynamic]^Expr, context.temp_allocator); + results := make([dynamic]^Expr, context.temp_allocator) for rhs in stmt.rhs { - get_generic_assignment(file, rhs, ast_context, &results); + get_generic_assignment(file, rhs, ast_context, &results) } if len(stmt.lhs) != len(results) { - return; + return } for lhs, i in stmt.lhs { - if ident, ok := lhs.derived.(ast.Ident); ok { - store_local(ast_context, results[i], ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; + if ident, ok := lhs.derived.(^ast.Ident); ok { + store_local(ast_context, results[i], ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true } } } get_locals_if_stmt :: proc(file: ast.File, stmt: ast.If_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { if !(stmt.pos.offset <= document_position.position && document_position.position <= stmt.end.offset) { - return; + return } - get_locals_stmt(file, stmt.init, ast_context, document_position, true); - get_locals_stmt(file, stmt.body, ast_context, document_position); - get_locals_stmt(file, stmt.else_stmt, ast_context, document_position); + get_locals_stmt(file, stmt.init, ast_context, document_position, true) + get_locals_stmt(file, stmt.body, ast_context, document_position) + get_locals_stmt(file, stmt.else_stmt, ast_context, document_position) } get_locals_for_range_stmt :: proc(file: ast.File, stmt: ast.Range_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { - using ast; + using ast if !(stmt.body.pos.offset <= document_position.position && document_position.position <= stmt.body.end.offset) { - return; + return } - results := make([dynamic]^Expr, context.temp_allocator); + results := make([dynamic]^Expr, context.temp_allocator) if stmt.expr == nil { - return; + return } if symbol, ok := resolve_type_expression(ast_context, stmt.expr); ok { #partial switch v in symbol.value { case index.SymbolMapValue: if len(stmt.vals) >= 1 { - if ident, ok := stmt.vals[0].derived.(Ident); ok { - store_local(ast_context, v.key, ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[0].derived.(^Ident); ok { + store_local(ast_context, v.key, ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } if len(stmt.vals) >= 2 { - if ident, ok := stmt.vals[1].derived.(Ident); ok { - store_local(ast_context, v.value, ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[1].derived.(^Ident); ok { + store_local(ast_context, v.value, ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } case index.SymbolDynamicArrayValue: if len(stmt.vals) >= 1 { - if ident, ok := stmt.vals[0].derived.(Ident); ok { - store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[0].derived.(^Ident); ok { + store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } if len(stmt.vals) >= 2 { - if ident, ok := stmt.vals[1].derived.(Ident); ok { - store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[1].derived.(^Ident); ok { + store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } case index.SymbolFixedArrayValue: if len(stmt.vals) >= 1 { - if ident, ok := stmt.vals[0].derived.(Ident); ok { - store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[0].derived.(^Ident); ok { + store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } if len(stmt.vals) >= 2 { - if ident, ok := stmt.vals[1].derived.(Ident); ok { - store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[1].derived.(^Ident); ok { + store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } case index.SymbolSliceValue: if len(stmt.vals) >= 1 { - if ident, ok := stmt.vals[0].derived.(Ident); ok { - store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[0].derived.(^Ident); ok { + store_local(ast_context, v.expr, ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } if len(stmt.vals) >= 2 { - if ident, ok := stmt.vals[1].derived.(Ident); ok { - store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; - ast_context.in_package[ident.name] = symbol.pkg; + if ident, ok := stmt.vals[1].derived.(^Ident); ok { + store_local(ast_context, make_int_ast(ast_context), ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true + ast_context.in_package[ident.name] = symbol.pkg } } } } - get_locals_stmt(file, stmt.body, ast_context, document_position); + get_locals_stmt(file, stmt.body, ast_context, document_position) } get_locals_for_stmt :: proc(file: ast.File, stmt: ast.For_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { if !(stmt.pos.offset <= document_position.position && document_position.position <= stmt.end.offset) { - return; + return } - get_locals_stmt(file, stmt.init, ast_context, document_position, true); - get_locals_stmt(file, stmt.body, ast_context, document_position); + get_locals_stmt(file, stmt.init, ast_context, document_position, true) + get_locals_stmt(file, stmt.body, ast_context, document_position) } get_locals_switch_stmt :: proc(file: ast.File, stmt: ast.Switch_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { if !(stmt.pos.offset <= document_position.position && document_position.position <= stmt.end.offset) { - return; + return } - get_locals_stmt(file, stmt.body, ast_context, document_position); + get_locals_stmt(file, stmt.body, ast_context, document_position) } get_locals_type_switch_stmt :: proc(file: ast.File, stmt: ast.Type_Switch_Stmt, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { - using ast; + using ast if !(stmt.pos.offset <= document_position.position && document_position.position <= stmt.end.offset) { - return; + return } if stmt.body == nil { - return; + return } - if block, ok := stmt.body.derived.(Block_Stmt); ok { + if block, ok := stmt.body.derived.(^Block_Stmt); ok { for block_stmt in block.stmts { - if cause, ok := block_stmt.derived.(Case_Clause); ok && cause.pos.offset <= document_position.position && document_position.position <= cause.end.offset { + if cause, ok := block_stmt.derived.(^Case_Clause); ok && cause.pos.offset <= document_position.position && document_position.position <= cause.end.offset { for b in cause.body { - get_locals_stmt(file, b, ast_context, document_position); + get_locals_stmt(file, b, ast_context, document_position) } - tag := stmt.tag.derived.(Assign_Stmt); + tag := stmt.tag.derived.(^Assign_Stmt) if len(tag.lhs) == 1 && len(cause.list) == 1 { - ident := tag.lhs[0].derived.(Ident); - store_local(ast_context, cause.list[0], ident.pos.offset, ident.name, ast_context.local_id); - ast_context.variables[ident.name] = true; + ident := tag.lhs[0].derived.(^Ident) + store_local(ast_context, cause.list[0], ident.pos.offset, ident.name, ast_context.local_id) + ast_context.variables[ident.name] = true } } } @@ -2340,32 +2338,32 @@ get_locals_type_switch_stmt :: proc(file: ast.File, stmt: ast.Type_Switch_Stmt, } get_locals_proc_param_and_results :: proc(file: ast.File, function: ast.Proc_Lit, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { - proc_lit, ok := function.derived.(ast.Proc_Lit); + proc_lit, ok := function.derived.(^ast.Proc_Lit) if !ok || proc_lit.body == nil { - return; + return } if proc_lit.type != nil && proc_lit.type.params != nil { for arg in proc_lit.type.params.list { for name in arg.names { if arg.type != nil { - str := common.get_ast_node_string(name, file.src); - store_local(ast_context, arg.type, name.pos.offset, str, ast_context.local_id); - ast_context.variables[str] = true; - ast_context.parameters[str] = true; + str := common.get_ast_node_string(name, file.src) + store_local(ast_context, arg.type, name.pos.offset, str, ast_context.local_id) + ast_context.variables[str] = true + ast_context.parameters[str] = true if .Using in arg.flags { - using_stmt: ast.Using_Stmt; - using_stmt.list = make([]^ast.Expr, 1, context.temp_allocator); - using_stmt.list[0] = arg.type; - get_locals_using_stmt(using_stmt, ast_context); + using_stmt: ast.Using_Stmt + using_stmt.list = make([]^ast.Expr, 1, context.temp_allocator) + using_stmt.list[0] = arg.type + get_locals_using_stmt(using_stmt, ast_context) } } else { - str := common.get_ast_node_string(name, file.src); - store_local(ast_context, arg.default_value, name.pos.offset, str, ast_context.local_id); - ast_context.variables[str] = true; - ast_context.parameters[str] = true; + str := common.get_ast_node_string(name, file.src) + store_local(ast_context, arg.default_value, name.pos.offset, str, ast_context.local_id) + ast_context.variables[str] = true + ast_context.parameters[str] = true } } } @@ -2375,10 +2373,10 @@ get_locals_proc_param_and_results :: proc(file: ast.File, function: ast.Proc_Lit for result in proc_lit.type.results.list { for name in result.names { if result.type != nil { - str := common.get_ast_node_string(name, file.src); - store_local(ast_context, result.type, name.pos.offset, str, ast_context.local_id); - ast_context.variables[str] = true; - ast_context.parameters[str] = true; + str := common.get_ast_node_string(name, file.src) + store_local(ast_context, result.type, name.pos.offset, str, ast_context.local_id) + ast_context.variables[str] = true + ast_context.parameters[str] = true } } } @@ -2386,50 +2384,50 @@ get_locals_proc_param_and_results :: proc(file: ast.File, function: ast.Proc_Lit } get_locals :: proc(file: ast.File, function: ^ast.Node, ast_context: ^AstContext, document_position: ^DocumentPositionContext) { - proc_lit, ok := function.derived.(ast.Proc_Lit); + proc_lit, ok := function.derived.(^ast.Proc_Lit) if !ok || proc_lit.body == nil { - return; + return } - get_locals_proc_param_and_results(file, proc_lit, ast_context, document_position); + get_locals_proc_param_and_results(file, proc_lit^, ast_context, document_position) - block: ast.Block_Stmt; - block, ok = proc_lit.body.derived.(ast.Block_Stmt); + block: ^ast.Block_Stmt + block, ok = proc_lit.body.derived.(^ast.Block_Stmt) if !ok { - log.error("Proc_List body not block"); - return; + log.error("Proc_List body not block") + return } for stmt in block.stmts { - get_locals_stmt(file, stmt, ast_context, document_position); + get_locals_stmt(file, stmt, ast_context, document_position) } } clear_locals :: proc(ast_context: ^AstContext) { - clear(&ast_context.locals); - clear(&ast_context.parameters); - clear(&ast_context.variables); - clear(&ast_context.usings); + clear(&ast_context.locals) + clear(&ast_context.parameters) + clear(&ast_context.variables) + clear(&ast_context.usings) } resolve_entire_file :: proc(document: ^common.Document, allocator := context.allocator) -> map[uintptr]index.Symbol { - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, allocator); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri, allocator) - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package - symbols := make(map[uintptr]index.Symbol, 100, allocator); + symbols := make(map[uintptr]index.Symbol, 100, allocator) for k, v in ast_context.globals { - resolve_entire_decl(&ast_context, v.expr, &symbols, allocator); - clear_local_group(&ast_context, 0); - add_local_group(&ast_context, 0); + resolve_entire_decl(&ast_context, v.expr, &symbols, allocator) + clear_local_group(&ast_context, 0) + add_local_group(&ast_context, 0) } - return symbols; + return symbols } resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Expr, symbols: ^map[uintptr]index.Symbol, allocator := context.allocator) { @@ -2449,75 +2447,75 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Expr, symbols: ast_context = ast_context, symbols = symbols, scopes = make([dynamic]Scope, allocator), - }; + } visit :: proc(visitor: ^ast.Visitor, node: ^ast.Node) -> ^ast.Visitor { if node == nil || visitor == nil { - return nil; + return nil } - data := cast(^Visit_Data)visitor.data; - ast_context := data.ast_context; - ast_context.use_locals = true; - ast_context.use_globals = true; + data := cast(^Visit_Data)visitor.data + ast_context := data.ast_context + ast_context.use_locals = true + ast_context.use_globals = true //It's somewhat silly to check the scope everytime, but the alternative is to implement my own walker function. if len(data.scopes) > 0 { - current_scope := data.scopes[len(data.scopes)-1]; + current_scope := data.scopes[len(data.scopes)-1] if current_scope.offset < node.end.offset { - clear_local_group(ast_context, current_scope.id); + clear_local_group(ast_context, current_scope.id) - pop(&data.scopes); + pop(&data.scopes) if len(data.scopes) > 0 { - current_scope = data.scopes[len(data.scopes)-1]; - ast_context.local_id = current_scope.id; + current_scope = data.scopes[len(data.scopes)-1] + ast_context.local_id = current_scope.id } else { - ast_context.local_id = 0; + ast_context.local_id = 0 } } } - switch v in &node.derived { - case ast.If_Stmt, ast.For_Stmt, ast.Range_Stmt, ast.Inline_Range_Stmt, ast.Proc_Lit: - scope: Scope; - scope.id = data.id_counter; - scope.offset = node.end.offset; - data.id_counter += 1; - ast_context.local_id = scope.id; + #partial switch v in node.derived { + case ^ast.If_Stmt, ^ast.For_Stmt, ^ast.Range_Stmt, ^ast.Inline_Range_Stmt, ^ast.Proc_Lit: + scope: Scope + scope.id = data.id_counter + scope.offset = node.end.offset + data.id_counter += 1 + ast_context.local_id = scope.id - append(&data.scopes, scope); - add_local_group(ast_context, scope.id); + append(&data.scopes, scope) + add_local_group(ast_context, scope.id) - position_context: DocumentPositionContext; - position_context.position = node.end.offset; - get_locals_stmt(ast_context.file, cast(^ast.Stmt)node, ast_context, &position_context); - case ast.Ident: - if symbol, ok := resolve_type_identifier(ast_context, v); ok { - data.symbols[cast(uintptr)node] = symbol; + position_context: DocumentPositionContext + position_context.position = node.end.offset + get_locals_stmt(ast_context.file, cast(^ast.Stmt)node, ast_context, &position_context) + case ^ast.Ident: + if symbol, ok := resolve_type_identifier(ast_context, v^); ok { + data.symbols[cast(uintptr)node] = symbol } - case ast.Selector_Expr: + case ^ast.Selector_Expr: if symbol, ok := resolve_type_expression(ast_context, &v.node); ok { - data.symbols[cast(uintptr)node] = symbol; + data.symbols[cast(uintptr)node] = symbol } - case ast.Call_Expr: + case ^ast.Call_Expr: if symbol, ok := resolve_type_expression(ast_context, &v.node); ok { - data.symbols[cast(uintptr)node] = symbol; + data.symbols[cast(uintptr)node] = symbol } } - switch v in &node.derived { - case ast.Proc_Lit: + #partial switch v in node.derived { + case ^ast.Proc_Lit: if v.body == nil { - break; + break } - type_position_context: DocumentPositionContext; - type_position_context.position = v.end.offset; - get_locals_proc_param_and_results(ast_context.file, v, ast_context, &type_position_context); + type_position_context: DocumentPositionContext + type_position_context.position = v.end.offset + get_locals_proc_param_and_results(ast_context.file, v^, ast_context, &type_position_context) } - return visitor; + return visitor } visitor := ast.Visitor { @@ -2525,7 +2523,7 @@ resolve_entire_decl :: proc(ast_context: ^AstContext, decl: ^ast.Expr, symbols: visit = visit, } - ast.walk(&visitor, decl); + ast.walk(&visitor, decl) } concatenate_symbol_information :: proc { @@ -2534,113 +2532,113 @@ concatenate_symbol_information :: proc { } concatenate_raw_symbol_information :: proc(ast_context: ^AstContext, symbol: index.Symbol, is_completion: bool) -> string { - return concatenate_raw_string_information(ast_context, symbol.pkg, symbol.name, symbol.signature, symbol.type, is_completion); + return concatenate_raw_string_information(ast_context, symbol.pkg, symbol.name, symbol.signature, symbol.type, is_completion) } concatenate_raw_string_information :: proc(ast_context: ^AstContext, pkg: string, name: string, signature: string, type: index.SymbolType, is_completion: bool) -> string { - pkg := path.base(pkg, false, context.temp_allocator); + pkg := path.base(pkg, false, context.temp_allocator) if type == .Package { - return fmt.tprintf("%v: package", name); + return fmt.tprintf("%v: package", name) } else if type == .Keyword && is_completion { - return name; + return name } else { if signature != "" { - return fmt.tprintf("%v.%v: %v", pkg, name, signature); + return fmt.tprintf("%v.%v: %v", pkg, name, signature) } else { - return fmt.tprintf("%v.%v", pkg, name); + return fmt.tprintf("%v.%v", pkg, name) } } } unwrap_enum :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolEnumValue, bool) { if node == nil { - return {}, false; + return {}, false } if enum_symbol, ok := resolve_type_expression(ast_context, node); ok { if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { - return enum_value, true; + return enum_value, true } } - return {}, false; + return {}, false } unwrap_union :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolUnionValue, bool) { if union_symbol, ok := resolve_type_expression(ast_context, node); ok { if union_value, ok := union_symbol.value.(index.SymbolUnionValue); ok { - return union_value, true; + return union_value, true } } - return {}, false; + return {}, false } unwrap_bitset :: proc(ast_context: ^AstContext, bitset_symbol: index.Symbol) -> (index.SymbolEnumValue, bool) { if bitset_value, ok := bitset_symbol.value.(index.SymbolBitSetValue); ok { if enum_symbol, ok := resolve_type_expression(ast_context, bitset_value.expr); ok { if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { - return enum_value, true; + return enum_value, true } } } - return {}, false; + return {}, false } get_signature :: proc(ast_context: ^AstContext, ident: ast.Ident, symbol: index.Symbol, was_variable := false) -> string { - using index; + using index if symbol.type == .Function { - return symbol.signature; + return symbol.signature } if .Distinct in symbol.flags { - return symbol.name; + return symbol.name } - is_variable := symbol.type == .Variable; + is_variable := symbol.type == .Variable #partial switch v in symbol.value { case SymbolBasicValue: - return common.node_to_string(v.ident); + return common.node_to_string(v.ident) case SymbolBitSetValue: - return common.node_to_string(v.expr); + return common.node_to_string(v.expr) case SymbolEnumValue: if is_variable { - return symbol.name; + return symbol.name } else { - return "enum"; + return "enum" } case SymbolMapValue: - return strings.concatenate(a = {"map[", common.node_to_string(v.key), "]", common.node_to_string(v.value)}, allocator = ast_context.allocator); + return strings.concatenate(a = {"map[", common.node_to_string(v.key), "]", common.node_to_string(v.value)}, allocator = ast_context.allocator) case SymbolProcedureValue: - return "proc"; + return "proc" case SymbolStructValue: if is_variable { - return symbol.name; + return symbol.name } else { - return "struct"; + return "struct" } case SymbolUnionValue: if is_variable { - return symbol.name; + return symbol.name } else { - return "union"; + return "union" } case SymbolDynamicArrayValue: - return strings.concatenate(a = {"[dynamic]", common.node_to_string(v.expr)}, allocator = ast_context.allocator); + return strings.concatenate(a = {"[dynamic]", common.node_to_string(v.expr)}, allocator = ast_context.allocator) case SymbolSliceValue: - return strings.concatenate(a = {"[]", common.node_to_string(v.expr)}, allocator = ast_context.allocator); + return strings.concatenate(a = {"[]", common.node_to_string(v.expr)}, allocator = ast_context.allocator) case SymbolFixedArrayValue: - return strings.concatenate(a = {"[", common.node_to_string(v.len), "]", common.node_to_string(v.expr)}, allocator = ast_context.allocator); + return strings.concatenate(a = {"[", common.node_to_string(v.len), "]", common.node_to_string(v.expr)}, allocator = ast_context.allocator) case SymbolPackageValue: - return "package"; + return "package" case SymbolUntypedValue: switch v.type { case .Float: return "float" @@ -2650,74 +2648,71 @@ get_signature :: proc(ast_context: ^AstContext, ident: ast.Ident, symbol: index. } } - return ""; + return "" } position_in_proc_decl :: proc(position_context: ^DocumentPositionContext) -> bool { if position_context.value_decl == nil { - return false; + return false } if len(position_context.value_decl.values) != 1 { - return false; + return false } - if _, ok := position_context.value_decl.values[0].derived.(ast.Proc_Type); ok { - return true; + if _, ok := position_context.value_decl.values[0].derived.(^ast.Proc_Type); ok { + return true } - if proc_lit, ok := position_context.value_decl.values[0].derived.(ast.Proc_Lit); ok { + if proc_lit, ok := position_context.value_decl.values[0].derived.(^ast.Proc_Lit); ok { if proc_lit.type != nil && position_in_node(proc_lit.type, position_context.position) { - return true; + return true } } - return false; + return false } is_lhs_comp_lit :: proc(position_context: ^DocumentPositionContext) -> bool { - if position_context.position <= position_context.comp_lit.open.offset { - return false; + return false } if len(position_context.comp_lit.elems) == 0 { - return true; + return true } for elem in position_context.comp_lit.elems { - if position_in_node(elem, position_context.position) { - - if ident, ok := elem.derived.(ast.Ident); ok { - return true; - } else if field, ok := elem.derived.(ast.Field_Value); ok { + if ident, ok := elem.derived.(^ast.Ident); ok { + return true + } else if field, ok := elem.derived.(^ast.Field_Value); ok { if position_in_node(field.value, position_context.position) { - return false; + return false } } } } - return true; + return true } field_exists_in_comp_lit :: proc(comp_lit: ^ast.Comp_Lit, name: string) -> bool { for elem in comp_lit.elems { - if field, ok := elem.derived.(ast.Field_Value); ok { + if field, ok := elem.derived.(^ast.Field_Value); ok { if field.field != nil { - if ident, ok := field.field.derived.(ast.Ident); ok { + if ident, ok := field.field.derived.(^ast.Ident); ok { if ident.name == name { - return true; + return true } } } } } - return false; + return false } /* @@ -2725,183 +2720,183 @@ field_exists_in_comp_lit :: proc(comp_lit: ^ast.Comp_Lit, name: string) -> bool */ get_call_commas :: proc(position_context: ^DocumentPositionContext, document: ^common.Document) { if position_context.call == nil { - return; + return } - commas := make([dynamic]int, 0, 10, context.temp_allocator); + commas := make([dynamic]int, 0, 10, context.temp_allocator) - paren_count := 0; - bracket_count := 0; - brace_count := 0; + paren_count := 0 + bracket_count := 0 + brace_count := 0 - if call, ok := position_context.call.derived.(ast.Call_Expr); ok { + if call, ok := position_context.call.derived.(^ast.Call_Expr); ok { if document.text[call.open.offset] == '(' { - paren_count -= 1; + paren_count -= 1 } for i := call.open.offset; i < call.close.offset; i += 1 { switch document.text[i] { - case '[': paren_count += 1; - case ']': paren_count -= 1; - case '{': brace_count += 1; - case '}': brace_count -= 1; - case '(': paren_count += 1; - case ')': paren_count -= 1; + case '[': paren_count += 1 + case ']': paren_count -= 1 + case '{': brace_count += 1 + case '}': brace_count -= 1 + case '(': paren_count += 1 + case ')': paren_count -= 1 case ',': if paren_count == 0 && brace_count == 0 && bracket_count == 0 { - append(&commas, i); + append(&commas, i) } } } } - position_context.call_commas = commas[:]; + position_context.call_commas = commas[:] } type_to_string :: proc(ast_context: ^AstContext, expr: ^ast.Expr) -> string { if symbol, ok := resolve_type_expression(ast_context, expr); ok { if .Anonymous in symbol.flags { - return symbol.name; + return symbol.name } } - return common.node_to_string(expr); + return common.node_to_string(expr) } /* Figure out what exactly is at the given position and whether it is in a function, struct, etc. */ get_document_position_context :: proc(document: ^common.Document, position: common.Position, hint: DocumentPositionContextHint) -> (DocumentPositionContext, bool) { - position_context: DocumentPositionContext; + position_context: DocumentPositionContext - position_context.hint = hint; - position_context.file = document.ast; - position_context.line = position.line; + position_context.hint = hint + position_context.file = document.ast + position_context.line = position.line - absolute_position, ok := common.get_absolute_position(position, document.text); + absolute_position, ok := common.get_absolute_position(position, document.text) if !ok { - log.error("failed to get absolute position"); - return position_context, false; + log.error("failed to get absolute position") + return position_context, false } - position_context.position = absolute_position; + position_context.position = absolute_position - exists_in_decl := false; + exists_in_decl := false for decl in document.ast.decls { if position_in_node(decl, position_context.position) { - get_document_position(decl, &position_context); - exists_in_decl = true; - switch v in decl.derived { - case ast.Expr_Stmt: - position_context.global_lhs_stmt = true; + get_document_position(decl, &position_context) + exists_in_decl = true + #partial switch v in decl.derived { + case ^ast.Expr_Stmt: + position_context.global_lhs_stmt = true } - break; + break } } for import_stmt in document.ast.imports { if position_in_node(import_stmt, position_context.position) { - position_context.import_stmt = import_stmt; - break; + position_context.import_stmt = import_stmt + break } } if !exists_in_decl && position_context.import_stmt == nil { - position_context.abort_completion = true; + position_context.abort_completion = true } if !position_in_node(position_context.comp_lit, position_context.position) { - position_context.comp_lit = nil; + position_context.comp_lit = nil } if !position_in_node(position_context.parent_comp_lit, position_context.position) { - position_context.parent_comp_lit = nil; + position_context.parent_comp_lit = nil } if !position_in_node(position_context.assign, position_context.position) { - position_context.assign = nil; + position_context.assign = nil } if !position_in_node(position_context.binary, position_context.position) { - position_context.binary = nil; + position_context.binary = nil } if !position_in_node(position_context.parent_binary, position_context.position) { - position_context.parent_binary = nil; + position_context.parent_binary = nil } if hint == .Completion && position_context.selector == nil && position_context.field == nil { - fallback_position_context_completion(document, position, &position_context); + fallback_position_context_completion(document, position, &position_context) } if (hint == .SignatureHelp || hint == .Completion) && position_context.call == nil { - fallback_position_context_signature(document, position, &position_context); + fallback_position_context_signature(document, position, &position_context) } if hint == .SignatureHelp { - get_call_commas(&position_context, document); + get_call_commas(&position_context, document) } - return position_context, true; + return position_context, true } //terrible fallback code fallback_position_context_completion :: proc(document: ^common.Document, position: common.Position, position_context: ^DocumentPositionContext) { - paren_count: int; - bracket_count: int; - end: int; - start: int; - empty_dot: bool; - empty_arrow: bool; - last_dot: bool; - last_arrow: bool; - dots_seen: int; - partial_arrow: bool; + paren_count: int + bracket_count: int + end: int + start: int + empty_dot: bool + empty_arrow: bool + last_dot: bool + last_arrow: bool + dots_seen: int + partial_arrow: bool - i := position_context.position - 1; + i := position_context.position - 1 - end = i; + end = i for i > 0 { - c := position_context.file.src[i]; + c := position_context.file.src[i] if c == '(' && paren_count == 0 { - start = i + 1; - break; + start = i + 1 + break } else if c == '[' && bracket_count == 0 { - start = i + 1; - break; + start = i + 1 + break } else if c == ']' && !last_dot { - start = i + 1; - break; + start = i + 1 + break } else if c == ')' && !last_dot { - start = i + 1; - break; + start = i + 1 + break } else if c == ')' { - paren_count -= 1; + paren_count -= 1 } else if c == '(' { - paren_count += 1; + paren_count += 1 } else if c == '[' { - bracket_count += 1; + bracket_count += 1 } else if c == ']' { - bracket_count -= 1; + bracket_count -= 1 } else if c == '.' { - dots_seen += 1; - last_dot = true; - i -= 1; - continue; + dots_seen += 1 + last_dot = true + i -= 1 + continue } else if position_context.file.src[max(0, i - 1)] == '-' && c == '>' { - last_arrow = true; - i -= 2; - continue; + last_arrow = true + i -= 2 + continue } //ignore everything in the bracket if bracket_count != 0 || paren_count != 0 { - i -= 1; - continue; + i -= 1 + continue } //yeah.. @@ -2910,51 +2905,51 @@ fallback_position_context_completion :: proc(document: ^common.Document, positio c == '\n' || c == '\r' || c == '=' || c == '<' || c == '-' || c == '!' || c == '+' || c == '&'|| c == '|' { - start = i + 1; - break; + start = i + 1 + break } else if c == '>' { - partial_arrow = true; + partial_arrow = true } - last_dot = false; - last_arrow = false; + last_dot = false + last_arrow = false - i -= 1; + i -= 1 } if i >= 0 && position_context.file.src[end] == '.' { - empty_dot = true; - end -= 1; + empty_dot = true + end -= 1 } else if i >= 0 && position_context.file.src[max(0, end - 1)] == '-' && position_context.file.src[end] == '>' { - empty_arrow = true; - end -= 2; - position_context.arrow = true; + empty_arrow = true + end -= 2 + position_context.arrow = true } - begin_offset := max(0, start); - end_offset := max(start, end + 1); + begin_offset := max(0, start) + end_offset := max(start, end + 1) - str := position_context.file.src[0:end_offset]; + str := position_context.file.src[0:end_offset] if empty_dot && end_offset - begin_offset == 0 { - position_context.implicit = true; - return; + position_context.implicit = true + return } - s := string(position_context.file.src[begin_offset:end_offset]); + s := string(position_context.file.src[begin_offset:end_offset]) if !partial_arrow { - only_whitespaces := true; + only_whitespaces := true for r in s { if !strings.is_space(r) { - only_whitespaces = false; + only_whitespaces = false } } if only_whitespaces { - return; + return } } @@ -2962,149 +2957,149 @@ fallback_position_context_completion :: proc(document: ^common.Document, positio err = common.parser_warning_handler, //empty warn = common.parser_warning_handler, //empty file = &position_context.file, - }; + } - tokenizer.init(&p.tok, str, position_context.file.fullpath, common.parser_warning_handler); + tokenizer.init(&p.tok, str, position_context.file.fullpath, common.parser_warning_handler) - p.tok.ch = ' '; - p.tok.line_count = position.line; - p.tok.offset = begin_offset; - p.tok.read_offset = begin_offset; + p.tok.ch = ' ' + p.tok.line_count = position.line + p.tok.offset = begin_offset + p.tok.read_offset = begin_offset - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) if p.tok.ch == utf8.RUNE_BOM { - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) } - parser.advance_token(&p); + parser.advance_token(&p) - context.allocator = context.temp_allocator; + context.allocator = context.temp_allocator - e := parser.parse_expr(&p, true); + e := parser.parse_expr(&p, true) if empty_dot || empty_arrow { - position_context.selector = e; - } else if s, ok := e.derived.(ast.Selector_Expr); ok { - position_context.selector = s.expr; - position_context.field = s.field; - } else if s, ok := e.derived.(ast.Implicit_Selector_Expr); ok { - position_context.implicit = true; - } else if s, ok := e.derived.(ast.Tag_Expr); ok { - position_context.tag = s.expr; - } else if bad_expr, ok := e.derived.(ast.Bad_Expr); ok { + position_context.selector = e + } else if s, ok := e.derived.(^ast.Selector_Expr); ok { + position_context.selector = s.expr + position_context.field = s.field + } else if s, ok := e.derived.(^ast.Implicit_Selector_Expr); ok { + position_context.implicit = true + } else if s, ok := e.derived.(^ast.Tag_Expr); ok { + position_context.tag = s.expr + } else if bad_expr, ok := e.derived.(^ast.Bad_Expr); ok { //this is most likely because of use of 'in', 'context', etc. //try to go back one dot. - src_with_dot := string(position_context.file.src[0:min(len(position_context.file.src), end_offset + 1)]); - last_dot := strings.last_index(src_with_dot, "."); + src_with_dot := string(position_context.file.src[0:min(len(position_context.file.src), end_offset + 1)]) + last_dot := strings.last_index(src_with_dot, ".") if last_dot == -1 { - return; + return } - tokenizer.init(&p.tok, position_context.file.src[0:last_dot], position_context.file.fullpath, common.parser_warning_handler); + tokenizer.init(&p.tok, position_context.file.src[0:last_dot], position_context.file.fullpath, common.parser_warning_handler) - p.tok.ch = ' '; - p.tok.line_count = position.line; - p.tok.offset = begin_offset; - p.tok.read_offset = begin_offset; + p.tok.ch = ' ' + p.tok.line_count = position.line + p.tok.offset = begin_offset + p.tok.read_offset = begin_offset - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) if p.tok.ch == utf8.RUNE_BOM { - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) } - parser.advance_token(&p); + parser.advance_token(&p) - e := parser.parse_expr(&p, true); + e := parser.parse_expr(&p, true) if e == nil { - position_context.abort_completion = true; - return; - } else if e, ok := e.derived.(ast.Bad_Expr); ok { - position_context.abort_completion = true; - return; + position_context.abort_completion = true + return + } else if e, ok := e.derived.(^ast.Bad_Expr); ok { + position_context.abort_completion = true + return } - position_context.selector = e; + position_context.selector = e - ident := index.new_type(ast.Ident, e.pos, e.end, context.temp_allocator); - ident.name = string(position_context.file.src[last_dot + 1:end_offset]); + ident := index.new_type(ast.Ident, e.pos, e.end, context.temp_allocator) + ident.name = string(position_context.file.src[last_dot + 1:end_offset]) if ident.name != "" { - position_context.field = ident; + position_context.field = ident } } else { - position_context.identifier = e; + position_context.identifier = e } } fallback_position_context_signature :: proc(document: ^common.Document, position: common.Position, position_context: ^DocumentPositionContext) { - end: int; - start: int; - i := position_context.position - 1; - end = i; + end: int + start: int + i := position_context.position - 1 + end = i for i > 0 { - c := position_context.file.src[i]; + c := position_context.file.src[i] if c == ' ' || c == '\n' || c == '\r' { - start = i + 1; - break; + start = i + 1 + break } - i -= 1; + i -= 1 } if end < 0 { - return; + return } if position_context.file.src[end] != '(' { - return; + return } - end -= 1; + end -= 1 - begin_offset := max(0, start); - end_offset := max(start, end + 1); + begin_offset := max(0, start) + end_offset := max(start, end + 1) if end_offset - begin_offset <= 1 { - return; + return } - str := position_context.file.src[0:end_offset]; + str := position_context.file.src[0:end_offset] p := parser.Parser { err = common.parser_warning_handler, //empty warn = common.parser_warning_handler, //empty file = &position_context.file, - }; + } - tokenizer.init(&p.tok, str, position_context.file.fullpath, common.parser_warning_handler); + tokenizer.init(&p.tok, str, position_context.file.fullpath, common.parser_warning_handler) - p.tok.ch = ' '; - p.tok.line_count = position.line; - p.tok.offset = begin_offset; - p.tok.read_offset = begin_offset; + p.tok.ch = ' ' + p.tok.line_count = position.line + p.tok.offset = begin_offset + p.tok.read_offset = begin_offset - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) if p.tok.ch == utf8.RUNE_BOM { - tokenizer.advance_rune(&p.tok); + tokenizer.advance_rune(&p.tok) } - parser.advance_token(&p); + parser.advance_token(&p) - context.allocator = context.temp_allocator; + context.allocator = context.temp_allocator - position_context.call = parser.parse_expr(&p, true); + position_context.call = parser.parse_expr(&p, true) - if _, ok := position_context.call.derived.(ast.Proc_Type); ok { - position_context.call = nil; + if _, ok := position_context.call.derived.(^ast.Proc_Type); ok { + position_context.call = nil } //log.error(string(position_context.file.src[begin_offset:end_offset])); @@ -3118,81 +3113,81 @@ get_document_position ::proc { get_document_position_array, get_document_position_dynamic_array, get_document_position_node, -}; +} get_document_position_array :: proc(array: $A/[]^$T, position_context: ^DocumentPositionContext) { for elem, i in array { - get_document_position(elem, position_context); + get_document_position(elem, position_context) } } get_document_position_dynamic_array :: proc(array: $A/[dynamic]^$T, position_context: ^DocumentPositionContext) { for elem, i in array { - get_document_position(elem, position_context); + get_document_position(elem, position_context) } } position_in_node :: proc(node: ^ast.Node, position: common.AbsolutePosition) -> bool { - return node != nil && node.pos.offset <= position && position <= node.end.offset; + return node != nil && node.pos.offset <= position && position <= node.end.offset } get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentPositionContext) { - using ast; + using ast if node == nil { - return; + return } if !position_in_node(node, position_context.position) { - return; + return } - switch n in node.derived { - case Bad_Expr: - case Ident: - position_context.identifier = node; - case Implicit: - case Undef: - case Basic_Lit: - case Ellipsis: - get_document_position(n.expr, position_context); - case Proc_Lit: - get_document_position(n.type, position_context); + #partial switch n in node.derived { + case ^Bad_Expr: + case ^Ident: + position_context.identifier = node + case ^Implicit: + case ^Undef: + case ^Basic_Lit: + case ^Ellipsis: + get_document_position(n.expr, position_context) + case ^Proc_Lit: + get_document_position(n.type, position_context) if position_in_node(n.body, position_context.position) { - position_context.function = cast(^Proc_Lit)node; - get_document_position(n.body, position_context); + position_context.function = cast(^Proc_Lit)node + get_document_position(n.body, position_context) } - case Comp_Lit: + case ^Comp_Lit: //only set this for the parent comp literal, since we will need to walk through it to infer types. if position_context.parent_comp_lit == nil { - position_context.parent_comp_lit = cast(^Comp_Lit)node; + position_context.parent_comp_lit = cast(^Comp_Lit)node } - position_context.comp_lit = cast(^Comp_Lit)node; + position_context.comp_lit = cast(^Comp_Lit)node - get_document_position(n.type, position_context); - get_document_position(n.elems, position_context); - case Tag_Expr: - get_document_position(n.expr, position_context); - case Unary_Expr: - get_document_position(n.expr, position_context); - case Binary_Expr: + get_document_position(n.type, position_context) + get_document_position(n.elems, position_context) + case ^Tag_Expr: + get_document_position(n.expr, position_context) + case ^Unary_Expr: + get_document_position(n.expr, position_context) + case ^Binary_Expr: if position_context.parent_binary == nil { - position_context.parent_binary = cast(^Binary_Expr)node; - } - position_context.binary = cast(^Binary_Expr)node; - get_document_position(n.left, position_context); - get_document_position(n.right, position_context); - case Paren_Expr: - get_document_position(n.expr, position_context); - case Call_Expr: + position_context.parent_binary = cast(^Binary_Expr)node + } + position_context.binary = cast(^Binary_Expr)node + get_document_position(n.left, position_context) + get_document_position(n.right, position_context) + case ^Paren_Expr: + get_document_position(n.expr, position_context) + case ^Call_Expr: if position_context.hint == .SignatureHelp || position_context.hint == .Completion { - position_context.call = cast(^Expr)node; + position_context.call = cast(^Expr)node } - get_document_position(n.expr, position_context); - get_document_position(n.args, position_context); - case Selector_Expr: + get_document_position(n.expr, position_context) + get_document_position(n.args, position_context) + case ^Selector_Expr: if position_context.hint == .Completion { if n.field != nil && n.field.pos.line - 1 == position_context.line { //The parser is not fault tolerant enough, relying on the fallback as the main completion parsing for now @@ -3200,182 +3195,181 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP //position_context.field = n.field; } } else if (position_context.hint == .Definition || position_context.hint == .Hover) && n.field != nil { - position_context.selector = n.expr; - position_context.field = n.field; - get_document_position(n.expr, position_context); - get_document_position(n.field, position_context); + position_context.selector = n.expr + position_context.field = n.field + get_document_position(n.expr, position_context) + get_document_position(n.field, position_context) } else { - get_document_position(n.expr, position_context); - get_document_position(n.field, position_context); - } - case Index_Expr: - get_document_position(n.expr, position_context); - get_document_position(n.index, position_context); - case Deref_Expr: - get_document_position(n.expr, position_context); - case Slice_Expr: - get_document_position(n.expr, position_context); - get_document_position(n.low, position_context); - get_document_position(n.high, position_context); - case Field_Value: - position_context.field_value = cast(^Field_Value)node; - get_document_position(n.field, position_context); - get_document_position(n.value, position_context); - case Ternary_If_Expr: - get_document_position(n.x, position_context); - get_document_position(n.cond, position_context); - get_document_position(n.y, position_context); - case Ternary_When_Expr: - get_document_position(n.x, position_context); - get_document_position(n.cond, position_context); - get_document_position(n.y, position_context); - case Type_Assertion: - get_document_position(n.expr, position_context); - get_document_position(n.type, position_context); - case Type_Cast: - get_document_position(n.type, position_context); - get_document_position(n.expr, position_context); - case Auto_Cast: - get_document_position(n.expr, position_context); - case Bad_Stmt: - case Empty_Stmt: - case Expr_Stmt: - get_document_position(n.expr, position_context); - case Tag_Stmt: - r := cast(^Tag_Stmt)node; - get_document_position(r.stmt, position_context); - case Assign_Stmt: - position_context.assign = cast(^Assign_Stmt)node; - get_document_position(n.lhs, position_context); - get_document_position(n.rhs, position_context); - case Block_Stmt: - get_document_position(n.label, position_context); - get_document_position(n.stmts, position_context); - case If_Stmt: - get_document_position(n.label, position_context); - get_document_position(n.init, position_context); - get_document_position(n.cond, position_context); - get_document_position(n.body, position_context); - get_document_position(n.else_stmt, position_context); - case When_Stmt: - get_document_position(n.cond, position_context); - get_document_position(n.body, position_context); - get_document_position(n.else_stmt, position_context); - case Return_Stmt: - position_context.returns = cast(^Return_Stmt)node; - get_document_position(n.results, position_context); - case Defer_Stmt: - get_document_position(n.stmt, position_context); - case For_Stmt: - get_document_position(n.label, position_context); - get_document_position(n.init, position_context); - get_document_position(n.cond, position_context); - get_document_position(n.post, position_context); - get_document_position(n.body, position_context); - case Range_Stmt: - get_document_position(n.label, position_context); - get_document_position(n.vals, position_context); - get_document_position(n.expr, position_context); - get_document_position(n.body, position_context); - case Case_Clause: - + get_document_position(n.expr, position_context) + get_document_position(n.field, position_context) + } + case ^Index_Expr: + get_document_position(n.expr, position_context) + get_document_position(n.index, position_context) + case ^Deref_Expr: + get_document_position(n.expr, position_context) + case ^Slice_Expr: + get_document_position(n.expr, position_context) + get_document_position(n.low, position_context) + get_document_position(n.high, position_context) + case ^Field_Value: + position_context.field_value = cast(^Field_Value)node + get_document_position(n.field, position_context) + get_document_position(n.value, position_context) + case ^Ternary_If_Expr: + get_document_position(n.x, position_context) + get_document_position(n.cond, position_context) + get_document_position(n.y, position_context) + case ^Ternary_When_Expr: + get_document_position(n.x, position_context) + get_document_position(n.cond, position_context) + get_document_position(n.y, position_context) + case ^Type_Assertion: + get_document_position(n.expr, position_context) + get_document_position(n.type, position_context) + case ^Type_Cast: + get_document_position(n.type, position_context) + get_document_position(n.expr, position_context) + case ^Auto_Cast: + get_document_position(n.expr, position_context) + case ^Bad_Stmt: + case ^Empty_Stmt: + case ^Expr_Stmt: + get_document_position(n.expr, position_context) + case ^Tag_Stmt: + r := cast(^Tag_Stmt)node + get_document_position(r.stmt, position_context) + case ^Assign_Stmt: + position_context.assign = cast(^Assign_Stmt)node + get_document_position(n.lhs, position_context) + get_document_position(n.rhs, position_context) + case ^Block_Stmt: + get_document_position(n.label, position_context) + get_document_position(n.stmts, position_context) + case ^If_Stmt: + get_document_position(n.label, position_context) + get_document_position(n.init, position_context) + get_document_position(n.cond, position_context) + get_document_position(n.body, position_context) + get_document_position(n.else_stmt, position_context) + case ^When_Stmt: + get_document_position(n.cond, position_context) + get_document_position(n.body, position_context) + get_document_position(n.else_stmt, position_context) + case ^Return_Stmt: + position_context.returns = cast(^Return_Stmt)node + get_document_position(n.results, position_context) + case ^Defer_Stmt: + get_document_position(n.stmt, position_context) + case ^For_Stmt: + get_document_position(n.label, position_context) + get_document_position(n.init, position_context) + get_document_position(n.cond, position_context) + get_document_position(n.post, position_context) + get_document_position(n.body, position_context) + case ^Range_Stmt: + get_document_position(n.label, position_context) + get_document_position(n.vals, position_context) + get_document_position(n.expr, position_context) + get_document_position(n.body, position_context) + case ^Case_Clause: for elem in n.list { if position_in_node(elem, position_context.position) { - position_context.case_clause = cast(^Case_Clause)node; - break; - } - } - - get_document_position(n.list, position_context); - get_document_position(n.body, position_context); - case Switch_Stmt: - position_context.switch_stmt = cast(^Switch_Stmt)node; - get_document_position(n.label, position_context); - get_document_position(n.init, position_context); - get_document_position(n.cond, position_context); - get_document_position(n.body, position_context); - case Type_Switch_Stmt: - position_context.switch_type_stmt = cast(^Type_Switch_Stmt)node; - get_document_position(n.label, position_context); - get_document_position(n.tag, position_context); - get_document_position(n.expr, position_context); - get_document_position(n.body, position_context); - case Branch_Stmt: - get_document_position(n.label, position_context); - case Using_Stmt: - get_document_position(n.list, position_context); - case Bad_Decl: - case Value_Decl: - position_context.value_decl = cast(^Value_Decl)node; - get_document_position(n.attributes, position_context); + position_context.case_clause = cast(^Case_Clause)node + break + } + } + + get_document_position(n.list, position_context) + get_document_position(n.body, position_context) + case ^Switch_Stmt: + position_context.switch_stmt = cast(^Switch_Stmt)node + get_document_position(n.label, position_context) + get_document_position(n.init, position_context) + get_document_position(n.cond, position_context) + get_document_position(n.body, position_context) + case ^Type_Switch_Stmt: + position_context.switch_type_stmt = cast(^Type_Switch_Stmt)node + get_document_position(n.label, position_context) + get_document_position(n.tag, position_context) + get_document_position(n.expr, position_context) + get_document_position(n.body, position_context) + case ^Branch_Stmt: + get_document_position(n.label, position_context) + case ^Using_Stmt: + get_document_position(n.list, position_context) + case ^Bad_Decl: + case ^Value_Decl: + position_context.value_decl = cast(^Value_Decl)node + get_document_position(n.attributes, position_context) for name in n.names { if position_in_node(name, position_context.position) && n.end.line - 1 == position_context.line { - position_context.abort_completion = true; - break; - } - } - get_document_position(n.names, position_context); - get_document_position(n.type, position_context); - get_document_position(n.values, position_context); - case Package_Decl: - case Import_Decl: - case Foreign_Block_Decl: - get_document_position(n.attributes, position_context); - get_document_position(n.foreign_library, position_context); - get_document_position(n.body, position_context); - case Foreign_Import_Decl: - get_document_position(n.name, position_context); - case Proc_Group: - get_document_position(n.args, position_context); - case Attribute: - get_document_position(n.elems, position_context); - case Field: - get_document_position(n.names, position_context); - get_document_position(n.type, position_context); - get_document_position(n.default_value, position_context); - case Field_List: - get_document_position(n.list, position_context); - case Typeid_Type: - get_document_position(n.specialization, position_context); - case Helper_Type: - get_document_position(n.type, position_context); - case Distinct_Type: - get_document_position(n.type, position_context); - case Poly_Type: - get_document_position(n.type, position_context); - get_document_position(n.specialization, position_context); - case Proc_Type: - get_document_position(n.params, position_context); - get_document_position(n.results, position_context); - case Pointer_Type: - get_document_position(n.elem, position_context); - case Array_Type: - get_document_position(n.len, position_context); - get_document_position(n.elem, position_context); - case Dynamic_Array_Type: - get_document_position(n.elem, position_context); - case Struct_Type: - get_document_position(n.poly_params, position_context); - get_document_position(n.align, position_context); - get_document_position(n.fields, position_context); - case Union_Type: - get_document_position(n.poly_params, position_context); - get_document_position(n.align, position_context); - get_document_position(n.variants, position_context); - case Enum_Type: - get_document_position(n.base_type, position_context); - get_document_position(n.fields, position_context); - case Bit_Set_Type: - get_document_position(n.elem, position_context); - get_document_position(n.underlying, position_context); - case Map_Type: - get_document_position(n.key, position_context); - get_document_position(n.value, position_context); - case Implicit_Selector_Expr: - position_context.implicit = true; - get_document_position(n.field, position_context); + position_context.abort_completion = true + break + } + } + get_document_position(n.names, position_context) + get_document_position(n.type, position_context) + get_document_position(n.values, position_context) + case ^Package_Decl: + case ^Import_Decl: + case ^Foreign_Block_Decl: + get_document_position(n.attributes, position_context) + get_document_position(n.foreign_library, position_context) + get_document_position(n.body, position_context) + case ^Foreign_Import_Decl: + get_document_position(n.name, position_context) + case ^Proc_Group: + get_document_position(n.args, position_context) + case ^Attribute: + get_document_position(n.elems, position_context) + case ^Field: + get_document_position(n.names, position_context) + get_document_position(n.type, position_context) + get_document_position(n.default_value, position_context) + case ^Field_List: + get_document_position(n.list, position_context) + case ^Typeid_Type: + get_document_position(n.specialization, position_context) + case ^Helper_Type: + get_document_position(n.type, position_context) + case ^Distinct_Type: + get_document_position(n.type, position_context) + case ^Poly_Type: + get_document_position(n.type, position_context) + get_document_position(n.specialization, position_context) + case ^Proc_Type: + get_document_position(n.params, position_context) + get_document_position(n.results, position_context) + case ^Pointer_Type: + get_document_position(n.elem, position_context) + case ^Array_Type: + get_document_position(n.len, position_context) + get_document_position(n.elem, position_context) + case ^Dynamic_Array_Type: + get_document_position(n.elem, position_context) + case ^Struct_Type: + get_document_position(n.poly_params, position_context) + get_document_position(n.align, position_context) + get_document_position(n.fields, position_context) + case ^Union_Type: + get_document_position(n.poly_params, position_context) + get_document_position(n.align, position_context) + get_document_position(n.variants, position_context) + case ^Enum_Type: + get_document_position(n.base_type, position_context) + get_document_position(n.fields, position_context) + case ^Bit_Set_Type: + get_document_position(n.elem, position_context) + get_document_position(n.underlying, position_context) + case ^Map_Type: + get_document_position(n.key, position_context) + get_document_position(n.value, position_context) + case ^Implicit_Selector_Expr: + position_context.implicit = true + get_document_position(n.field, position_context) case: - log.errorf("Unhandled node kind: %T", n); + log.errorf("Unhandled node kind: %T", n) } } |