From 58287455d64ab16091522bf8a358b079ef05daad Mon Sep 17 00:00:00 2001 From: Daniel Gavin Date: Fri, 4 Mar 2022 12:17:00 +0100 Subject: strip colons and update ast to use unions --- src/analysis/analysis.odin | 2836 +++++++++++++++++++------------------- src/common/allocator.odin | 104 +- src/common/ast.odin | 1116 ++++++++------- src/common/fuzzy.odin | 254 ++-- src/common/position.odin | 166 +-- src/common/sha1.odin | 334 ++--- src/common/uri.odin | 92 +- src/common/util_windows.odin | 62 +- src/index/build.odin | 122 +- src/index/clone.odin | 378 +++-- src/index/collector.odin | 577 ++++---- src/index/indexer.odin | 50 +- src/index/memory_index.odin | 28 +- src/index/symbol.odin | 46 +- src/main.odin | 72 +- src/odin/printer/document.odin | 2 +- src/odin/printer/printer.odin | 4 +- src/odin/printer/visit.odin | 224 ++- src/server/check.odin | 118 +- src/server/completion.odin | 652 ++++----- src/server/definition.odin | 91 +- src/server/document_links.odin | 20 +- src/server/document_symbols.odin | 56 +- src/server/documents.odin | 252 ++-- src/server/format.odin | 40 +- src/server/hover.odin | 126 +- src/server/inlay_hints.odin | 36 +- src/server/lens.odin | 14 +- src/server/log.odin | 18 +- src/server/reader.odin | 42 +- src/server/requests.odin | 648 ++++----- src/server/response.odin | 36 +- src/server/semantic_tokens.odin | 468 +++---- src/server/signature.odin | 110 +- src/server/unmarshal.odin | 96 +- src/server/writer.odin | 18 +- src/testing/testing.odin | 4 +- 37 files changed, 4644 insertions(+), 4668 deletions(-) (limited to 'src') 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) } } diff --git a/src/common/allocator.odin b/src/common/allocator.odin index bbb654c..6d2d371 100644 --- a/src/common/allocator.odin +++ b/src/common/allocator.odin @@ -12,119 +12,119 @@ Scratch_Allocator :: struct { } scratch_allocator_init :: proc (s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) { - s.data, _ = mem.make_aligned([]byte, size, 2 * align_of(rawptr), backup_allocator); - s.curr_offset = 0; - s.prev_allocation = nil; - s.backup_allocator = backup_allocator; - s.leaked_allocations.allocator = backup_allocator; + s.data, _ = mem.make_aligned([]byte, size, 2 * align_of(rawptr), backup_allocator) + s.curr_offset = 0 + s.prev_allocation = nil + s.backup_allocator = backup_allocator + s.leaked_allocations.allocator = backup_allocator } scratch_allocator_destroy :: proc (s: ^Scratch_Allocator) { if s == nil { - return; + return } for ptr in s.leaked_allocations { - mem.free_bytes(ptr, s.backup_allocator); + mem.free_bytes(ptr, s.backup_allocator) } - delete(s.leaked_allocations); - delete(s.data, s.backup_allocator); - s^ = {}; + delete(s.leaked_allocations) + delete(s.data, s.backup_allocator) + s^ = {} } scratch_allocator_proc :: proc (allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, mem.Allocator_Error) { - s := (^Scratch_Allocator)(allocator_data); + s := (^Scratch_Allocator)(allocator_data) if s.data == nil { - DEFAULT_BACKING_SIZE :: 1 << 22; + DEFAULT_BACKING_SIZE :: 1 << 22 if !(context.allocator.procedure != scratch_allocator_proc && context.allocator.data != allocator_data) { - panic("cyclic initialization of the scratch allocator with itself"); + panic("cyclic initialization of the scratch allocator with itself") } - scratch_allocator_init(s, DEFAULT_BACKING_SIZE); + scratch_allocator_init(s, DEFAULT_BACKING_SIZE) } - size := size; + size := size switch mode { case .Alloc: - size = mem.align_forward_int(size, alignment); + size = mem.align_forward_int(size, alignment) switch { case s.curr_offset + size <= len(s.data): - start := uintptr(raw_data(s.data)); - ptr := start + uintptr(s.curr_offset); - ptr = mem.align_forward_uintptr(ptr, uintptr(alignment)); - mem.zero(rawptr(ptr), size); - - s.prev_allocation = rawptr(ptr); - offset := int(ptr - start); - s.curr_offset = offset + size; - return mem.byte_slice(rawptr(ptr), size), nil; + start := uintptr(raw_data(s.data)) + ptr := start + uintptr(s.curr_offset) + ptr = mem.align_forward_uintptr(ptr, uintptr(alignment)) + mem.zero(rawptr(ptr), size) + + s.prev_allocation = rawptr(ptr) + offset := int(ptr - start) + s.curr_offset = offset + size + return mem.byte_slice(rawptr(ptr), size), nil } - a := s.backup_allocator; + a := s.backup_allocator if a.procedure == nil { - a = context.allocator; - s.backup_allocator = a; + a = context.allocator + s.backup_allocator = a } - ptr, err := mem.alloc_bytes(size, alignment, a, loc); + ptr, err := mem.alloc_bytes(size, alignment, a, loc) if err != nil { - return ptr, err; + return ptr, err } if s.leaked_allocations == nil { - s.leaked_allocations = make([dynamic][]byte, a); + s.leaked_allocations = make([dynamic][]byte, a) } - append(&s.leaked_allocations, ptr); + append(&s.leaked_allocations, ptr) if logger := context.logger; logger.lowest_level <= .Warning { if logger.procedure != nil { - logger.procedure(logger.data, .Warning, "mem.Scratch_Allocator resorted to backup_allocator" , logger.options, loc); + logger.procedure(logger.data, .Warning, "mem.Scratch_Allocator resorted to backup_allocator" , logger.options, loc) } } - return ptr, err; + return ptr, err case .Free: case .Free_All: - s.curr_offset = 0; - s.prev_allocation = nil; + s.curr_offset = 0 + s.prev_allocation = nil for ptr in s.leaked_allocations { - mem.free_bytes(ptr, s.backup_allocator); + mem.free_bytes(ptr, s.backup_allocator) } - clear(&s.leaked_allocations); + clear(&s.leaked_allocations) case .Resize: - begin := uintptr(raw_data(s.data)); - end := begin + uintptr(len(s.data)); - old_ptr := uintptr(old_memory); + begin := uintptr(raw_data(s.data)) + end := begin + uintptr(len(s.data)) + old_ptr := uintptr(old_memory) - data, err := scratch_allocator_proc(allocator_data, .Alloc, size, alignment, old_memory, old_size, loc); + data, err := scratch_allocator_proc(allocator_data, .Alloc, size, alignment, old_memory, old_size, loc) if err != nil { - return data, err; + return data, err } - runtime.copy(data, mem.byte_slice(old_memory, old_size)); - _, err = scratch_allocator_proc(allocator_data, .Free, 0, alignment, old_memory, old_size, loc); - return data, err; + runtime.copy(data, mem.byte_slice(old_memory, old_size)) + _, err = scratch_allocator_proc(allocator_data, .Free, 0, alignment, old_memory, old_size, loc) + return data, err case .Query_Features: - set := (^mem.Allocator_Mode_Set)(old_memory); + set := (^mem.Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, nil; + return nil, nil } - return nil, nil; + return nil, nil } scratch_allocator :: proc (allocator: ^Scratch_Allocator) -> mem.Allocator { return mem.Allocator { procedure = scratch_allocator_proc, data = allocator, - }; + } } diff --git a/src/common/ast.odin b/src/common/ast.odin index 69f35e0..7677634 100644 --- a/src/common/ast.odin +++ b/src/common/ast.odin @@ -62,7 +62,7 @@ keyword_map: map[string]bool = { "quaternion64" = true, "quaternion128" = true, "quaternion256" = true, -}; +} GlobalExpr :: struct { name: string, @@ -77,63 +77,63 @@ GlobalExpr :: struct { unwrap_pointer :: proc(expr: ^ast.Expr) -> (ast.Ident, bool) { - expr := expr; + expr := expr for expr != nil { - if pointer, ok := expr.derived.(ast.Pointer_Type); ok { - expr = pointer.elem; + if pointer, ok := expr.derived.(^ast.Pointer_Type); ok { + expr = pointer.elem } else { - break; + break } } if expr != nil { - ident, ok := expr.derived.(ast.Ident); - return ident, ok; + ident, ok := expr.derived.(^ast.Ident) + return ident^, ok } - return {}, false; + return {}, false } collect_value_decl :: proc(exprs: ^[dynamic]GlobalExpr, file: ast.File, stmt: ^ast.Node, skip_private: bool) { - if value_decl, ok := stmt.derived.(ast.Value_Decl); ok { + if value_decl, ok := stmt.derived.(^ast.Value_Decl); ok { - is_deprecated := false; - is_private_file := false; - is_package_file := false; + is_deprecated := false + is_private_file := false + is_package_file := false for attribute in value_decl.attributes { for elem in attribute.elems { - if value, ok := elem.derived.(ast.Field_Value); ok { - if ident, ok := value.field.derived.(ast.Ident); ok { + if value, ok := elem.derived.(^ast.Field_Value); ok { + if ident, ok := value.field.derived.(^ast.Ident); ok { switch ident.name { case "private": - if val, ok := value.value.derived.(ast.Basic_Lit); ok { + if val, ok := value.value.derived.(^ast.Basic_Lit); ok { switch val.tok.text { case "\"file\"": - is_private_file = true; + is_private_file = true case "package": - is_package_file = true; + is_package_file = true } } case "deprecated": - is_deprecated = true; + is_deprecated = true } } - } else if ident, ok := elem.derived.(ast.Ident); ok { + } else if ident, ok := elem.derived.(^ast.Ident); ok { switch ident.name { case "deprecated": - is_deprecated = true; + is_deprecated = true } } } } if is_private_file && skip_private { - return; + return } for name, i in value_decl.names { - str := get_ast_node_string(name, file.src); + str := get_ast_node_string(name, file.src) if value_decl.type != nil { append(exprs, GlobalExpr { @@ -143,7 +143,7 @@ collect_value_decl :: proc(exprs: ^[dynamic]GlobalExpr, file: ast.File, stmt: ^a docs = value_decl.docs, attributes = value_decl.attributes[:], deprecated = is_deprecated, - }); + }) } else { if len(value_decl.values) > i { append(exprs, GlobalExpr { @@ -153,7 +153,7 @@ collect_value_decl :: proc(exprs: ^[dynamic]GlobalExpr, file: ast.File, stmt: ^a docs = value_decl.docs, attributes = value_decl.attributes[:], deprecated = is_deprecated, - }); + }) } } } @@ -161,98 +161,97 @@ collect_value_decl :: proc(exprs: ^[dynamic]GlobalExpr, file: ast.File, stmt: ^a } collect_globals :: proc(file: ast.File, skip_private := false) -> []GlobalExpr { - exprs := make([dynamic]GlobalExpr, context.temp_allocator); + exprs := make([dynamic]GlobalExpr, context.temp_allocator) for decl in file.decls { - if value_decl, ok := decl.derived.(ast.Value_Decl); ok { - collect_value_decl(&exprs, file, decl, skip_private); - } else if when_decl, ok := decl.derived.(ast.When_Stmt); ok { + if value_decl, ok := decl.derived.(^ast.Value_Decl); ok { + collect_value_decl(&exprs, file, decl, skip_private) + } else if when_decl, ok := decl.derived.(^ast.When_Stmt); ok { if when_decl.cond == nil { - continue; + continue } if when_decl.body == nil { - continue; + continue } - if binary, ok := when_decl.cond.derived.(ast.Binary_Expr); ok { + if binary, ok := when_decl.cond.derived.(^ast.Binary_Expr); ok { if binary.left == nil || binary.right == nil { - continue; + continue } - ident: ^ast.Ident; - basic_lit: ^ast.Basic_Lit; + ident: ^ast.Ident + implicit: ^ast.Implicit - if t, ok := binary.left.derived.(ast.Ident); ok { - ident = cast(^ast.Ident)binary.left; - } else if t, ok := binary.left.derived.(ast.Basic_Lit); ok { - basic_lit = cast(^ast.Basic_Lit)binary.left; + if t, ok := binary.left.derived.(^ast.Ident); ok { + ident = cast(^ast.Ident)binary.left + } else if t, ok := binary.left.derived.(^ast.Basic_Lit); ok { + implicit = cast(^ast.Implicit)binary.left } - if t, ok := binary.right.derived.(ast.Ident); ok { - ident = cast(^ast.Ident)binary.right; - } else if t, ok := binary.right.derived.(ast.Basic_Lit); ok { - basic_lit = cast(^ast.Basic_Lit)binary.right; + if t, ok := binary.right.derived.(^ast.Ident); ok { + ident = cast(^ast.Ident)binary.right + } else if t, ok := binary.right.derived.(^ast.Basic_Lit); ok { + implicit = cast(^ast.Implicit)binary.right } - if ident != nil && basic_lit != nil { - if ident.name == "ODIN_OS" && basic_lit.tok.text[1:len(basic_lit.tok.text)-1] == ODIN_OS { - if block, ok := when_decl.body.derived.(ast.Block_Stmt); ok { + if ident != nil && implicit != nil { + if ident.name == "ODIN_OS" && implicit.tok.text == fmt.tprint(ODIN_OS) { + if block, ok := when_decl.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - collect_value_decl(&exprs, file, stmt, skip_private); + collect_value_decl(&exprs, file, stmt, skip_private) } } } else if ident.name != "ODIN_OS" { - if block, ok := when_decl.body.derived.(ast.Block_Stmt); ok { + if block, ok := when_decl.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - collect_value_decl(&exprs, file, stmt, skip_private); + collect_value_decl(&exprs, file, stmt, skip_private) } } } } } else { - if block, ok := when_decl.body.derived.(ast.Block_Stmt); ok { + if block, ok := when_decl.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - collect_value_decl(&exprs, file, stmt, skip_private); + collect_value_decl(&exprs, file, stmt, skip_private) } } } - } else if foreign_decl, ok := decl.derived.(ast.Foreign_Block_Decl); ok { + } else if foreign_decl, ok := decl.derived.(^ast.Foreign_Block_Decl); ok { if foreign_decl.body == nil { - continue; + continue } - if block, ok := foreign_decl.body.derived.(ast.Block_Stmt); ok { + if block, ok := foreign_decl.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - collect_value_decl(&exprs, file, stmt, skip_private); + collect_value_decl(&exprs, file, stmt, skip_private) } } } } - return exprs[:]; + return exprs[:] } get_ast_node_string :: proc(node: ^ast.Node, src: string) -> string { - return string(src[node.pos.offset:node.end.offset]); + return string(src[node.pos.offset:node.end.offset]) } get_doc :: proc(comment: ^ast.Comment_Group, allocator: mem.Allocator) -> string { - if comment != nil { - tmp: string; + tmp: string for doc in comment.list { - tmp = strings.concatenate({tmp, "\n", doc.text}, context.temp_allocator); + tmp = strings.concatenate({tmp, "\n", doc.text}, context.temp_allocator) } if tmp != "" { - replaced, allocated := strings.replace_all(tmp, "//", "", context.temp_allocator); - return strings.clone(replaced, allocator); + replaced, allocated := strings.replace_all(tmp, "//", "", context.temp_allocator) + return strings.clone(replaced, allocator) } } - return ""; + return "" } free_ast :: proc{ @@ -260,451 +259,443 @@ free_ast :: proc{ free_ast_array, free_ast_dynamic_array, free_ast_comment, -}; +} free_ast_comment :: proc(a: ^ast.Comment_Group, allocator: mem.Allocator) { if a == nil { - return; + return } if len(a.list) > 0 { - delete(a.list, allocator); + delete(a.list, allocator) } - free(a, allocator); + free(a, allocator) } free_ast_array :: proc(array: $A/[]^$T, allocator: mem.Allocator) { for elem, i in array { - free_ast(elem, allocator); + free_ast(elem, allocator) } - delete(array, allocator); + delete(array, allocator) } free_ast_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator) { for elem, i in array { - free_ast(elem, allocator); + free_ast(elem, allocator) } - delete(array); + delete(array) } free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) { - - using ast; + using ast if node == nil { - return; + return } - switch n in node.derived { - case Bad_Expr: - case Ident: - case Implicit: - case Undef: - case Basic_Directive: - case Basic_Lit: - case Ellipsis: - free_ast(n.expr, allocator); - case Proc_Lit: - free_ast(n.type, allocator); - free_ast(n.body, allocator); - free_ast(n.where_clauses, allocator); - case Comp_Lit: - free_ast(n.type, allocator); - free_ast(n.elems, allocator); - case Tag_Expr: - free_ast(n.expr, allocator); - case Unary_Expr: - free_ast(n.expr, allocator); - case Binary_Expr: - free_ast(n.left, allocator); - free_ast(n.right, allocator); - case Paren_Expr: - free_ast(n.expr, allocator); - case Call_Expr: - free_ast(n.expr, allocator); - free_ast(n.args, allocator); - case Selector_Expr: - free_ast(n.expr, allocator); - free_ast(n.field, allocator); - case Implicit_Selector_Expr: - free_ast(n.field, allocator); - case Index_Expr: - free_ast(n.expr, allocator); - free_ast(n.index, allocator); - case Deref_Expr: - free_ast(n.expr, allocator); - case Slice_Expr: - free_ast(n.expr, allocator); - free_ast(n.low, allocator); - free_ast(n.high, allocator); - case Field_Value: - free_ast(n.field, allocator); - free_ast(n.value, allocator); - case Ternary_If_Expr: - free_ast(n.x, allocator); - free_ast(n.cond, allocator); - free_ast(n.y, allocator); - case Ternary_When_Expr: - free_ast(n.x, allocator); - free_ast(n.cond, allocator); - free_ast(n.y, allocator); - case Type_Assertion: - free_ast(n.expr, allocator); - free_ast(n.type, allocator); - case Type_Cast: - free_ast(n.type, allocator); - free_ast(n.expr, allocator); - case Auto_Cast: - free_ast(n.expr, allocator); - case Bad_Stmt: - case Empty_Stmt: - case Expr_Stmt: - free_ast(n.expr, allocator); - case Tag_Stmt: - r := cast(^Expr_Stmt)node; - free_ast(r.expr, allocator); - case Assign_Stmt: - free_ast(n.lhs, allocator); - free_ast(n.rhs, allocator); - case Block_Stmt: - free_ast(n.label, allocator); - free_ast(n.stmts, allocator); - case If_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - free_ast(n.else_stmt, allocator); - case When_Stmt: - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - free_ast(n.else_stmt, allocator); - case Return_Stmt: - free_ast(n.results, allocator); - case Defer_Stmt: - free_ast(n.stmt, allocator); - case For_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.post, allocator); - free_ast(n.body, allocator); - case Range_Stmt: - free_ast(n.label, allocator); - free_ast(n.vals, allocator); - free_ast(n.expr, allocator); - free_ast(n.body, allocator); - case Case_Clause: - free_ast(n.list, allocator); - free_ast(n.body, allocator); - case Switch_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - case Type_Switch_Stmt: - free_ast(n.label, allocator); - free_ast(n.tag, allocator); - free_ast(n.expr, allocator); - free_ast(n.body, allocator); - case Branch_Stmt: - free_ast(n.label, allocator); - case Using_Stmt: - free_ast(n.list, allocator); - case Bad_Decl: - case Value_Decl: - free_ast(n.attributes, allocator); - free_ast(n.names, allocator); - free_ast(n.type, allocator); - free_ast(n.values, allocator); - //free_ast(n.docs); - //free_ast(n.comment); - case Package_Decl: - //free_ast(n.docs); - //free_ast(n.comment); - case Import_Decl: - //free_ast(n.docs); - //free_ast(n.comment); - case Foreign_Block_Decl: - free_ast(n.attributes, allocator); - free_ast(n.foreign_library, allocator); - free_ast(n.body, allocator); - case Foreign_Import_Decl: - free_ast(n.name, allocator); - free_ast(n.attributes, allocator); - case Proc_Group: - free_ast(n.args, allocator); - case Attribute: - free_ast(n.elems, allocator); - case Field: - free_ast(n.names, allocator); - free_ast(n.type, allocator); - free_ast(n.default_value, allocator); + if node.derived != nil do #partial switch n in node.derived { + case ^Bad_Expr: + case ^Ident: + case ^Implicit: + case ^Undef: + case ^Basic_Directive: + case ^Basic_Lit: + case ^Ellipsis: + free_ast(n.expr, allocator) + case ^Proc_Lit: + free_ast(n.type, allocator) + free_ast(n.body, allocator) + free_ast(n.where_clauses, allocator) + case ^Comp_Lit: + free_ast(n.type, allocator) + free_ast(n.elems, allocator) + case ^Tag_Expr: + free_ast(n.expr, allocator) + case ^Unary_Expr: + free_ast(n.expr, allocator) + case ^Binary_Expr: + free_ast(n.left, allocator) + free_ast(n.right, allocator) + case ^Paren_Expr: + free_ast(n.expr, allocator) + case ^Call_Expr: + free_ast(n.expr, allocator) + free_ast(n.args, allocator) + case ^Selector_Expr: + free_ast(n.expr, allocator) + free_ast(n.field, allocator) + case ^Implicit_Selector_Expr: + free_ast(n.field, allocator) + case ^Index_Expr: + free_ast(n.expr, allocator) + free_ast(n.index, allocator) + case ^Deref_Expr: + free_ast(n.expr, allocator) + case ^Slice_Expr: + free_ast(n.expr, allocator) + free_ast(n.low, allocator) + free_ast(n.high, allocator) + case ^Field_Value: + free_ast(n.field, allocator) + free_ast(n.value, allocator) + case ^Ternary_If_Expr: + free_ast(n.x, allocator) + free_ast(n.cond, allocator) + free_ast(n.y, allocator) + case ^Ternary_When_Expr: + free_ast(n.x, allocator) + free_ast(n.cond, allocator) + free_ast(n.y, allocator) + case ^Type_Assertion: + free_ast(n.expr, allocator) + free_ast(n.type, allocator) + case ^Type_Cast: + free_ast(n.type, allocator) + free_ast(n.expr, allocator) + case ^Auto_Cast: + free_ast(n.expr, allocator) + case ^Bad_Stmt: + case ^Empty_Stmt: + case ^Expr_Stmt: + free_ast(n.expr, allocator) + case ^Tag_Stmt: + r := cast(^Expr_Stmt)node + free_ast(r.expr, allocator) + case ^Assign_Stmt: + free_ast(n.lhs, allocator) + free_ast(n.rhs, allocator) + case ^Block_Stmt: + free_ast(n.label, allocator) + free_ast(n.stmts, allocator) + case ^If_Stmt: + free_ast(n.label, allocator) + free_ast(n.init, allocator) + free_ast(n.cond, allocator) + free_ast(n.body, allocator) + free_ast(n.else_stmt, allocator) + case ^When_Stmt: + free_ast(n.cond, allocator) + free_ast(n.body, allocator) + free_ast(n.else_stmt, allocator) + case ^Return_Stmt: + free_ast(n.results, allocator) + case ^Defer_Stmt: + free_ast(n.stmt, allocator) + case ^For_Stmt: + free_ast(n.label, allocator) + free_ast(n.init, allocator) + free_ast(n.cond, allocator) + free_ast(n.post, allocator) + free_ast(n.body, allocator) + case ^Range_Stmt: + free_ast(n.label, allocator) + free_ast(n.vals, allocator) + free_ast(n.expr, allocator) + free_ast(n.body, allocator) + case ^Case_Clause: + free_ast(n.list, allocator) + free_ast(n.body, allocator) + case ^Switch_Stmt: + free_ast(n.label, allocator) + free_ast(n.init, allocator) + free_ast(n.cond, allocator) + free_ast(n.body, allocator) + case ^Type_Switch_Stmt: + free_ast(n.label, allocator) + free_ast(n.tag, allocator) + free_ast(n.expr, allocator) + free_ast(n.body, allocator) + case ^Branch_Stmt: + free_ast(n.label, allocator) + case ^Using_Stmt: + free_ast(n.list, allocator) + case ^Bad_Decl: + case ^Value_Decl: + free_ast(n.attributes, allocator) + free_ast(n.names, allocator) + free_ast(n.type, allocator) + free_ast(n.values, allocator) + case ^Package_Decl: + case ^Import_Decl: + case ^Foreign_Block_Decl: + free_ast(n.attributes, allocator) + free_ast(n.foreign_library, allocator) + free_ast(n.body, allocator) + case ^Foreign_Import_Decl: + free_ast(n.name, allocator) + free_ast(n.attributes, allocator) + case ^Proc_Group: + free_ast(n.args, allocator) + case ^Attribute: + free_ast(n.elems, allocator) + case ^Field: + free_ast(n.names, allocator) + free_ast(n.type, allocator) + free_ast(n.default_value, allocator) //free_ast(n.docs); //free_ast(n.comment); - case Field_List: - free_ast(n.list, allocator); - case Typeid_Type: - free_ast(n.specialization, allocator); - case Helper_Type: - free_ast(n.type, allocator); - case Distinct_Type: - free_ast(n.type, allocator); - case Poly_Type: - free_ast(n.type, allocator); - free_ast(n.specialization, allocator); - case Proc_Type: - free_ast(n.params, allocator); - free_ast(n.results, allocator); - case Pointer_Type: - free_ast(n.elem, allocator); - case Array_Type: - free_ast(n.len, allocator); - free_ast(n.elem, allocator); - free_ast(n.tag, allocator); - case Dynamic_Array_Type: - free_ast(n.elem, allocator); - free_ast(n.tag, allocator); - case Struct_Type: - free_ast(n.poly_params, allocator); - free_ast(n.align, allocator); - free_ast(n.fields, allocator); - free_ast(n.where_clauses, allocator); - case Union_Type: - free_ast(n.poly_params, allocator); - free_ast(n.align, allocator); - free_ast(n.variants, allocator); - free_ast(n.where_clauses, allocator); - case Enum_Type: - free_ast(n.base_type, allocator); - free_ast(n.fields, allocator); - case Bit_Set_Type: - free_ast(n.elem, allocator); - free_ast(n.underlying, allocator); - case Map_Type: - free_ast(n.key, allocator); - free_ast(n.value, allocator); - case Multi_Pointer_Type: - free_ast(n.elem, allocator); - case Matrix_Type: - free_ast(n.elem, allocator); + case ^Field_List: + free_ast(n.list, allocator) + case ^Typeid_Type: + free_ast(n.specialization, allocator) + case ^Helper_Type: + free_ast(n.type, allocator) + case ^Distinct_Type: + free_ast(n.type, allocator) + case ^Poly_Type: + free_ast(n.type, allocator) + free_ast(n.specialization, allocator) + case ^Proc_Type: + free_ast(n.params, allocator) + free_ast(n.results, allocator) + case ^Pointer_Type: + free_ast(n.elem, allocator) + case ^Array_Type: + free_ast(n.len, allocator) + free_ast(n.elem, allocator) + free_ast(n.tag, allocator) + case ^Dynamic_Array_Type: + free_ast(n.elem, allocator) + free_ast(n.tag, allocator) + case ^Struct_Type: + free_ast(n.poly_params, allocator) + free_ast(n.align, allocator) + free_ast(n.fields, allocator) + free_ast(n.where_clauses, allocator) + case ^Union_Type: + free_ast(n.poly_params, allocator) + free_ast(n.align, allocator) + free_ast(n.variants, allocator) + free_ast(n.where_clauses, allocator) + case ^Enum_Type: + free_ast(n.base_type, allocator) + free_ast(n.fields, allocator) + case ^Bit_Set_Type: + free_ast(n.elem, allocator) + free_ast(n.underlying, allocator) + case ^Map_Type: + free_ast(n.key, allocator) + free_ast(n.value, allocator) + case ^Multi_Pointer_Type: + free_ast(n.elem, allocator) + case ^Matrix_Type: + free_ast(n.elem, allocator) case: - panic(fmt.aprintf("free Unhandled node kind: %T", n)); + panic(fmt.aprintf("free Unhandled node kind: %T", n)) } - mem.free(node, allocator); + mem.free(node, allocator) } free_ast_file :: proc(file: ast.File, allocator := context.allocator) { for decl in file.decls { - free_ast(decl, allocator); + free_ast(decl, allocator) } - free_ast(file.pkg_decl, allocator); + free_ast(file.pkg_decl, allocator) for comment in file.comments { - free_ast(comment, allocator); + free_ast(comment, allocator) } - delete(file.comments); - delete(file.imports); - delete(file.decls); + delete(file.comments) + delete(file.imports) + delete(file.decls) } node_equal :: proc{ node_equal_node, node_equal_array, node_equal_dynamic_array, -}; +} node_equal_array :: proc(a, b: $A/[]^$T) -> bool { - ret := true; + ret := true if len(a) != len(b) { - return false; + return false } for elem, i in a { - ret &= node_equal(elem, b[i]); + ret &= node_equal(elem, b[i]) } - return ret; + return ret } node_equal_dynamic_array :: proc(a, b: $A/[dynamic]^$T) -> bool { - ret := true; + ret := true if len(a) != len(b) { - return false; + return false } for elem, i in a { - ret &= node_equal(elem, b[i]); + ret &= node_equal(elem, b[i]) } - return ret; + return ret } node_equal_node :: proc(a, b: ^ast.Node) -> bool { - - using ast; + using ast if a == nil || b == nil { - return false; + return false } - switch m in b.derived { - case Bad_Expr: - if n, ok := a.derived.(Bad_Expr); ok { - return true; + #partial switch m in b.derived { + case ^Bad_Expr: + if n, ok := a.derived.(^Bad_Expr); ok { + return true } - case Ident: - if n, ok := a.derived.(Ident); ok { - return true; + case ^Ident: + if n, ok := a.derived.(^Ident); ok { + return true //return n.name == m.name; } - case Implicit: - if n, ok := a.derived.(Implicit); ok { - return true; - } - case Undef: - if n, ok := a.derived.(Undef); ok { - return true; - } - case Basic_Lit: - if n, ok := a.derived.(Basic_Lit); ok { - return true; - } - case Poly_Type: - return true; - case Ellipsis: - if n, ok := a.derived.(Ellipsis); ok { - return node_equal(n.expr, m.expr); - } - case Tag_Expr: - if n, ok := a.derived.(Tag_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Unary_Expr: - if n, ok := a.derived.(Unary_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Binary_Expr: - if n, ok := a.derived.(Binary_Expr); ok { - ret := node_equal(n.left, m.left); - ret &= node_equal(n.right, m.right); - return ret; - } - case Paren_Expr: - if n, ok := a.derived.(Paren_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Selector_Expr: - if n, ok := a.derived.(Selector_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.field, m.field); - return ret; - } - case Slice_Expr: - if n, ok := a.derived.(Slice_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.low, m.low); - ret &= node_equal(n.high, m.high); - return ret; - } - case Distinct_Type: - if n, ok := a.derived.(Distinct_Type); ok { - return node_equal(n.type, m.type); - } - case Proc_Type: - if n, ok := a.derived.(Proc_Type); ok { - ret := node_equal(n.params, m.params); - ret &= node_equal(n.results, m.results); - return ret; - } - case Pointer_Type: - if n, ok := a.derived.(Pointer_Type); ok { - return node_equal(n.elem, m.elem); - } - case Array_Type: - if n, ok := a.derived.(Array_Type); ok { - ret := node_equal(n.elem, m.elem); + case ^Implicit: + if n, ok := a.derived.(^Implicit); ok { + return true + } + case ^Undef: + if n, ok := a.derived.(^Undef); ok { + return true + } + case ^Basic_Lit: + if n, ok := a.derived.(^Basic_Lit); ok { + return true + } + case ^Poly_Type: + return true + case ^Ellipsis: + if n, ok := a.derived.(^Ellipsis); ok { + return node_equal(n.expr, m.expr) + } + case ^Tag_Expr: + if n, ok := a.derived.(^Tag_Expr); ok { + return node_equal(n.expr, m.expr) + } + case ^Unary_Expr: + if n, ok := a.derived.(^Unary_Expr); ok { + return node_equal(n.expr, m.expr) + } + case ^Binary_Expr: + if n, ok := a.derived.(^Binary_Expr); ok { + ret := node_equal(n.left, m.left) + ret &= node_equal(n.right, m.right) + return ret + } + case ^Paren_Expr: + if n, ok := a.derived.(^Paren_Expr); ok { + return node_equal(n.expr, m.expr) + } + case ^Selector_Expr: + if n, ok := a.derived.(^Selector_Expr); ok { + ret := node_equal(n.expr, m.expr) + ret &= node_equal(n.field, m.field) + return ret + } + case ^Slice_Expr: + if n, ok := a.derived.(^Slice_Expr); ok { + ret := node_equal(n.expr, m.expr) + ret &= node_equal(n.low, m.low) + ret &= node_equal(n.high, m.high) + return ret + } + case ^Distinct_Type: + if n, ok := a.derived.(^Distinct_Type); ok { + return node_equal(n.type, m.type) + } + case ^Proc_Type: + if n, ok := a.derived.(^Proc_Type); ok { + ret := node_equal(n.params, m.params) + ret &= node_equal(n.results, m.results) + return ret + } + case ^Pointer_Type: + if n, ok := a.derived.(^Pointer_Type); ok { + return node_equal(n.elem, m.elem) + } + case ^Array_Type: + if n, ok := a.derived.(^Array_Type); ok { + ret := node_equal(n.elem, m.elem) if n.len != nil && m.len != nil { - ret &= node_equal(n.len, m.len); + ret &= node_equal(n.len, m.len) } - return ret; - } - case Dynamic_Array_Type: - if n, ok := a.derived.(Dynamic_Array_Type); ok { - return node_equal(n.elem, m.elem); - } - case Struct_Type: - if n, ok := a.derived.(Struct_Type); ok { - ret := node_equal(n.poly_params, m.poly_params); - ret &= node_equal(n.align, m.align); - ret &= node_equal(n.fields, m.fields); - return ret; - } - case Field: - if n, ok := a.derived.(Field); ok { - ret := node_equal(n.names, m.names); - ret &= node_equal(n.type, m.type); - ret &= node_equal(n.default_value, m.default_value); - return ret; - } - case Field_List: - if n, ok := a.derived.(Field_List); ok { - return node_equal(n.list, m.list); - } - case Field_Value: - if n, ok := a.derived.(Field_Value); ok { - ret := node_equal(n.field, m.field); - ret &= node_equal(n.value, m.value); - return ret; - } - case Union_Type: - if n, ok := a.derived.(Union_Type); ok { - ret := node_equal(n.poly_params, m.poly_params); - ret &= node_equal(n.align, m.align); - ret &= node_equal(n.variants, m.variants); - return ret; - } - case Enum_Type: - if n, ok := a.derived.(Enum_Type); ok { - ret := node_equal(n.base_type, m.base_type); - ret &= node_equal(n.fields, m.fields); - return ret; - } - case Bit_Set_Type: - if n, ok := a.derived.(Bit_Set_Type); ok { - ret := node_equal(n.elem, m.elem); - ret &= node_equal(n.underlying, m.underlying); - return ret; - } - case Map_Type: - if n, ok := a.derived.(Map_Type); ok { - ret := node_equal(n.key, m.key); - ret &= node_equal(n.value, m.value); - return ret; - } - case Call_Expr: - if n, ok := a.derived.(Call_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.args, m.args); - return ret; - } - case Typeid_Type: - return true; + return ret + } + case ^Dynamic_Array_Type: + if n, ok := a.derived.(^Dynamic_Array_Type); ok { + return node_equal(n.elem, m.elem) + } + case ^Struct_Type: + if n, ok := a.derived.(^Struct_Type); ok { + ret := node_equal(n.poly_params, m.poly_params) + ret &= node_equal(n.align, m.align) + ret &= node_equal(n.fields, m.fields) + return ret + } + case ^Field: + if n, ok := a.derived.(^Field); ok { + ret := node_equal(n.names, m.names) + ret &= node_equal(n.type, m.type) + ret &= node_equal(n.default_value, m.default_value) + return ret + } + case ^Field_List: + if n, ok := a.derived.(^Field_List); ok { + return node_equal(n.list, m.list) + } + case ^Field_Value: + if n, ok := a.derived.(^Field_Value); ok { + ret := node_equal(n.field, m.field) + ret &= node_equal(n.value, m.value) + return ret + } + case ^Union_Type: + if n, ok := a.derived.(^Union_Type); ok { + ret := node_equal(n.poly_params, m.poly_params) + ret &= node_equal(n.align, m.align) + ret &= node_equal(n.variants, m.variants) + return ret + } + case ^Enum_Type: + if n, ok := a.derived.(^Enum_Type); ok { + ret := node_equal(n.base_type, m.base_type) + ret &= node_equal(n.fields, m.fields) + return ret + } + case ^Bit_Set_Type: + if n, ok := a.derived.(^Bit_Set_Type); ok { + ret := node_equal(n.elem, m.elem) + ret &= node_equal(n.underlying, m.underlying) + return ret + } + case ^Map_Type: + if n, ok := a.derived.(^Map_Type); ok { + ret := node_equal(n.key, m.key) + ret &= node_equal(n.value, m.value) + return ret + } + case ^Call_Expr: + if n, ok := a.derived.(^Call_Expr); ok { + ret := node_equal(n.expr, m.expr) + ret &= node_equal(n.args, m.args) + return ret + } + case ^Typeid_Type: + return true case: - log.warn("Unhandled poly node kind: %T", m); + log.warn("Unhandled poly node kind: %T", m) } - return false; + return false } /* @@ -712,199 +703,198 @@ node_equal_node :: proc(a, b: ^ast.Node) -> bool { */ node_to_string :: proc(node: ^ast.Node) -> string { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) - build_string(node, &builder); + build_string(node, &builder) - return strings.to_string(builder); + return strings.to_string(builder) } build_string :: proc{ build_string_ast_array, build_string_dynamic_array, build_string_node, -}; +} build_string_dynamic_array :: proc(array: $A/[]^$T, builder: ^strings.Builder) { for elem, i in array { - build_string(elem, builder); + build_string(elem, builder) } } build_string_ast_array :: proc(array: $A/[dynamic]^$T, builder: ^strings.Builder) { for elem, i in array { - build_string(elem, builder); + build_string(elem, builder) } } build_string_node :: proc(node: ^ast.Node, builder: ^strings.Builder) { - using ast; + using ast if node == nil { - return; + return } - switch n in node.derived { - case Bad_Expr: - case Ident: + #partial switch n in node.derived { + case ^Bad_Expr: + case ^Ident: if strings.contains(n.name, "/") { - strings.write_string(builder, path.base(n.name, false, context.temp_allocator)); + strings.write_string(builder, path.base(n.name, false, context.temp_allocator)) } else { - strings.write_string(builder, n.name); - } - case Implicit: - strings.write_string(builder, n.tok.text); - case Undef: - case Basic_Lit: - strings.write_string(builder, n.tok.text); - case Basic_Directive: - strings.write_string(builder, n.name); - case Implicit_Selector_Expr: - strings.write_string(builder, "."); - build_string(n.field, builder); - case Ellipsis: - strings.write_string(builder, ".."); - build_string(n.expr, builder); - case Proc_Lit: - build_string(n.type, builder); - build_string(n.body, builder); - case Comp_Lit: - build_string(n.type, builder); - strings.write_string(builder, "{"); - build_string(n.elems, builder); - strings.write_string(builder, "}"); - case Tag_Expr: - build_string(n.expr, builder); - case Unary_Expr: - build_string(n.expr, builder); - case Binary_Expr: - build_string(n.left, builder); - build_string(n.right, builder); - case Paren_Expr: - strings.write_string(builder, "("); - build_string(n.expr, builder); - strings.write_string(builder, ")"); - case Call_Expr: - build_string(n.expr, builder); - strings.write_string(builder, "("); + strings.write_string(builder, n.name) + } + case ^Implicit: + strings.write_string(builder, n.tok.text) + case ^Undef: + case ^Basic_Lit: + strings.write_string(builder, n.tok.text) + case ^Basic_Directive: + strings.write_string(builder, n.name) + case ^Implicit_Selector_Expr: + strings.write_string(builder, ".") + build_string(n.field, builder) + case ^Ellipsis: + strings.write_string(builder, "..") + build_string(n.expr, builder) + case ^Proc_Lit: + build_string(n.type, builder) + build_string(n.body, builder) + case ^Comp_Lit: + build_string(n.type, builder) + strings.write_string(builder, "{") + build_string(n.elems, builder) + strings.write_string(builder, "}") + case ^Tag_Expr: + build_string(n.expr, builder) + case ^Unary_Expr: + build_string(n.expr, builder) + case ^Binary_Expr: + build_string(n.left, builder) + build_string(n.right, builder) + case ^Paren_Expr: + strings.write_string(builder, "(") + build_string(n.expr, builder) + strings.write_string(builder, ")") + case ^Call_Expr: + build_string(n.expr, builder) + strings.write_string(builder, "(") for arg, i in n.args { - build_string(arg, builder); + build_string(arg, builder) if len(n.args) - 1 != i { - strings.write_string(builder, ", "); + strings.write_string(builder, ", ") } } - strings.write_string(builder, ")"); - case Selector_Expr: - build_string(n.expr, builder); - strings.write_string(builder, "."); - build_string(n.field, builder); - case Index_Expr: - build_string(n.expr, builder); - strings.write_string(builder, "["); - build_string(n.index, builder); - strings.write_string(builder, "]"); - case Deref_Expr: - build_string(n.expr, builder); - case Slice_Expr: - build_string(n.expr, builder); - build_string(n.low, builder); - build_string(n.high, builder); - case Field_Value: - build_string(n.field, builder); - strings.write_string(builder, ": "); - build_string(n.value, builder); - case Type_Cast: - build_string(n.type, builder); - build_string(n.expr, builder); - case Bad_Stmt: - case Bad_Decl: - case Attribute: - build_string(n.elems, builder); - case Field: - + strings.write_string(builder, ")") + case ^Selector_Expr: + build_string(n.expr, builder) + strings.write_string(builder, ".") + build_string(n.field, builder) + case ^Index_Expr: + build_string(n.expr, builder) + strings.write_string(builder, "[") + build_string(n.index, builder) + strings.write_string(builder, "]") + case ^Deref_Expr: + build_string(n.expr, builder) + case ^Slice_Expr: + build_string(n.expr, builder) + build_string(n.low, builder) + build_string(n.high, builder) + case ^Field_Value: + build_string(n.field, builder) + strings.write_string(builder, ": ") + build_string(n.value, builder) + case ^Type_Cast: + build_string(n.type, builder) + build_string(n.expr, builder) + case ^Bad_Stmt: + case ^Bad_Decl: + case ^Attribute: + build_string(n.elems, builder) + case ^Field: for name, i in n.names { - build_string(name, builder); + build_string(name, builder) if len(n.names) - 1 != i { - strings.write_string(builder, ", "); + strings.write_string(builder, ", ") } } if len(n.names) > 0 && n.type != nil { - strings.write_string(builder, ": "); - build_string(n.type, builder); + strings.write_string(builder, ": ") + build_string(n.type, builder) if n.default_value != nil && n.type != nil { - strings.write_string(builder, " = "); + strings.write_string(builder, " = ") } } else if len(n.names) > 0 && n.default_value != nil { - strings.write_string(builder, " := "); + strings.write_string(builder, " := ") } else { - build_string(n.type, builder); + build_string(n.type, builder) } - build_string(n.default_value, builder); - case Field_List: + build_string(n.default_value, builder) + case ^Field_List: for field, i in n.list { - build_string(field, builder); + build_string(field, builder) if len(n.list) - 1 != i { - strings.write_string(builder, ","); + strings.write_string(builder, ",") } } - case Typeid_Type: - strings.write_string(builder, "$"); - build_string(n.specialization, builder); - case Helper_Type: - build_string(n.type, builder); - case Distinct_Type: - build_string(n.type, builder); - case Poly_Type: - strings.write_string(builder, "$"); + case ^Typeid_Type: + strings.write_string(builder, "$") + build_string(n.specialization, builder) + case ^Helper_Type: + build_string(n.type, builder) + case ^Distinct_Type: + build_string(n.type, builder) + case ^Poly_Type: + strings.write_string(builder, "$") - build_string(n.type, builder); + build_string(n.type, builder) if n.specialization != nil { - strings.write_string(builder, "/"); - build_string(n.specialization, builder); - } - case Proc_Type: - strings.write_string(builder, "proc("); - build_string(n.params, builder); - strings.write_string(builder, ") -> "); - build_string(n.results, builder); - case Pointer_Type: - strings.write_string(builder, "^"); - build_string(n.elem, builder); - case Array_Type: - strings.write_string(builder, "["); - build_string(n.len, builder); - strings.write_string(builder, "]"); - build_string(n.elem, builder); - case Dynamic_Array_Type: - strings.write_string(builder, "[dynamic]"); - build_string(n.elem, builder); - case Struct_Type: - build_string(n.poly_params, builder); - build_string(n.align, builder); - build_string(n.fields, builder); - case Union_Type: - build_string(n.poly_params, builder); - build_string(n.align, builder); - build_string(n.variants, builder); - case Enum_Type: - build_string(n.base_type, builder); - build_string(n.fields, builder); - case Bit_Set_Type: - build_string(n.elem, builder); - build_string(n.underlying, builder); - case Map_Type: - strings.write_string(builder, "map"); - strings.write_string(builder, "["); - build_string(n.key, builder); - strings.write_string(builder, "]"); - build_string(n.value, builder); + strings.write_string(builder, "/") + build_string(n.specialization, builder) + } + case ^Proc_Type: + strings.write_string(builder, "proc(") + build_string(n.params, builder) + strings.write_string(builder, ") -> ") + build_string(n.results, builder) + case ^Pointer_Type: + strings.write_string(builder, "^") + build_string(n.elem, builder) + case ^Array_Type: + strings.write_string(builder, "[") + build_string(n.len, builder) + strings.write_string(builder, "]") + build_string(n.elem, builder) + case ^Dynamic_Array_Type: + strings.write_string(builder, "[dynamic]") + build_string(n.elem, builder) + case ^Struct_Type: + build_string(n.poly_params, builder) + build_string(n.align, builder) + build_string(n.fields, builder) + case ^Union_Type: + build_string(n.poly_params, builder) + build_string(n.align, builder) + build_string(n.variants, builder) + case ^Enum_Type: + build_string(n.base_type, builder) + build_string(n.fields, builder) + case ^Bit_Set_Type: + build_string(n.elem, builder) + build_string(n.underlying, builder) + case ^Map_Type: + strings.write_string(builder, "map") + strings.write_string(builder, "[") + build_string(n.key, builder) + strings.write_string(builder, "]") + build_string(n.value, builder) } } diff --git a/src/common/fuzzy.odin b/src/common/fuzzy.odin index 68223e0..f6c8b11 100644 --- a/src/common/fuzzy.odin +++ b/src/common/fuzzy.odin @@ -7,15 +7,15 @@ import "core:fmt" Ported from https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clangd/FuzzyMatch.cpp */ -max_pattern :: 63; -max_word :: 127; +max_pattern :: 63 +max_word :: 127 -awful_score: int = -(1 << 13); -perfect_bonus :: 4; -miss :: 0; -match :: 1; +awful_score: int = -(1 << 13) +perfect_bonus :: 4 +miss :: 0 +match :: 1 -FuzzyCharTypeSet :: u8; +FuzzyCharTypeSet :: u8 //do bitfield instead FuzzyScoreInfo :: struct { @@ -60,7 +60,7 @@ char_roles: []u8 = { /*Prev=Upper */0x00,0x55,0x59,0xff, // Ditto, but U(U)U->Tail /*Prev=Separ */0x00,0xaa,0xaa,0xff, // After separator, like at start // clang-format on -}; +} char_types: []u8 = { 0x00,0x00,0x00,0x00, // Control characters @@ -75,266 +75,266 @@ char_types: []u8 = { 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, // (probably UTF-8). 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, -}; +} make_fuzzy_matcher :: proc(pattern: string, allocator := context.temp_allocator) -> ^FuzzyMatcher { - matcher := new(FuzzyMatcher, allocator); + matcher := new(FuzzyMatcher, allocator) - matcher.pattern_count = min(len(pattern), max_pattern); - matcher.score_scale = matcher.pattern_count > 0 ? 1 / cast(f32)(perfect_bonus * matcher.pattern_count) : 0; - matcher.pattern = pattern[0:matcher.pattern_count]; - matcher.lower_pattern = strings.to_lower(matcher.pattern, context.temp_allocator); + matcher.pattern_count = min(len(pattern), max_pattern) + matcher.score_scale = matcher.pattern_count > 0 ? 1 / cast(f32)(perfect_bonus * matcher.pattern_count) : 0 + matcher.pattern = pattern[0:matcher.pattern_count] + matcher.lower_pattern = strings.to_lower(matcher.pattern, context.temp_allocator) - score_info_miss: FuzzyScoreInfo; - score_info_miss.score = 0; - score_info_miss.prev = miss; + score_info_miss: FuzzyScoreInfo + score_info_miss.score = 0 + score_info_miss.prev = miss - matcher.scores[0][0][miss] = score_info_miss; + matcher.scores[0][0][miss] = score_info_miss - score_info_match: FuzzyScoreInfo; - score_info_match.score = awful_score; - score_info_match.prev = match; + score_info_match: FuzzyScoreInfo + score_info_match.score = awful_score + score_info_match.prev = match - matcher.scores[0][0][match] = score_info_match; + matcher.scores[0][0][match] = score_info_match for p := 0; p < matcher.pattern_count; p += 1 { for w := 0; w < p; w += 1 { for a := 0; a < 2; a += 1 { - score_info: FuzzyScoreInfo; - score_info.score = awful_score; - score_info.prev = miss; - matcher.scores[p][w][a] = score_info; - ref := matcher.pattern_role[:matcher.pattern_count]; - matcher.pattern_type_set = fuzzy_calculate_roles(matcher.pattern, &ref); + score_info: FuzzyScoreInfo + score_info.score = awful_score + score_info.prev = miss + matcher.scores[p][w][a] = score_info + ref := matcher.pattern_role[:matcher.pattern_count] + matcher.pattern_type_set = fuzzy_calculate_roles(matcher.pattern, &ref) } } } - return matcher; + return matcher } fuzzy_to_acronym :: proc(word: string) -> (string, bool) { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) if len(word) <= 1 { - return "", false; + return "", false } - i := 1; - last_char := word[0]; + i := 1 + last_char := word[0] - strings.write_byte(&builder, last_char); + strings.write_byte(&builder, last_char) for i < len(word) { if last_char == '_' { - strings.write_byte(&builder, word[i]); + strings.write_byte(&builder, word[i]) } - last_char = word[i]; + last_char = word[i] - i += 1; + i += 1 } - str := strings.to_string(builder); + str := strings.to_string(builder) if len(str) <= 1 { - return "", false; + return "", false } - return str, true; + return str, true } //changed from bool to int because of a linux bug - 10.05.2021 fuzzy_match :: proc(matcher: ^FuzzyMatcher, word: string) -> (f32, int) { if !fuzzy_init(matcher, word) { - return 0, 0; + return 0, 0 } if matcher.pattern_count <= 0 { - return 1, 1; + return 1, 1 } if acronym, ok := fuzzy_to_acronym(word); ok { if acronym == matcher.pattern { - return 20, 1; + return 20, 1 } } - fuzzy_build_graph(matcher); + fuzzy_build_graph(matcher) best := max(cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][miss].score, - cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][match].score); + cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][match].score) if fuzzy_is_awful(best) { - return 0.0, 0; + return 0.0, 0 } - score := matcher.score_scale * min(perfect_bonus * cast(f32)matcher.pattern_count, cast(f32)max(0, best)); + score := matcher.score_scale * min(perfect_bonus * cast(f32)matcher.pattern_count, cast(f32)max(0, best)) if matcher.word_count == matcher.pattern_count { - score *= 2; + score *= 2 } - return score, 1; + return score, 1 } fuzzy_is_awful :: proc(s: int) -> bool { - return s < awful_score / 2; + return s < awful_score / 2 } fuzzy_calculate_roles :: proc(text: string, roles: ^[]FuzzyCharRole) -> FuzzyCharTypeSet { - assert(len(text) == len(roles)); + assert(len(text) == len(roles)) if len(text) == 0 { - return 0; + return 0 } - type: FuzzyCharType = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[0]); + type: FuzzyCharType = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[0]) - type_set: FuzzyCharTypeSet = cast(u8)(1 << cast(uint)type); + type_set: FuzzyCharTypeSet = cast(u8)(1 << cast(uint)type) - types := type; + types := type for i := 0; i < len(text) - 1; i += 1 { - type = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[i + 1]); - type_set |= 1 << cast(uint)type; + type = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[i + 1]) + type_set |= 1 << cast(uint)type - fuzzy_rotate(type, &types); + fuzzy_rotate(type, &types) - roles[i] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types); + roles[i] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types) } - fuzzy_rotate(.Empty, &types); + fuzzy_rotate(.Empty, &types) - roles[len(text) - 1] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types); + roles[len(text) - 1] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types) - return type_set; + return type_set } fuzzy_rotate :: proc(t: FuzzyCharType, types: ^FuzzyCharType) { - types^ = cast(FuzzyCharType)(((cast(uint)types^ << 2) | cast(uint)t) & 0x3f); + types^ = cast(FuzzyCharType)(((cast(uint)types^ << 2) | cast(uint)t) & 0x3f) } fuzzy_packed_lookup :: proc(data: $A/[]$T, i: uint) -> T { - return (data[i >> 2] >> ((i & 3) * 2)) & 3; + return (data[i >> 2] >> ((i & 3) * 2)) & 3 } fuzzy_init :: proc(matcher: ^FuzzyMatcher, word: string) -> bool { - matcher.word = word; - matcher.word_count = min(max_word, len(matcher.word)); + matcher.word = word + matcher.word_count = min(max_word, len(matcher.word)) if matcher.pattern_count > matcher.word_count { - return false; + return false } if matcher.pattern_count == 0 { - return true; + return true } - matcher.lower_word = strings.to_lower(word, context.temp_allocator); + matcher.lower_word = strings.to_lower(word, context.temp_allocator) - w, p := 0, 0; + w, p := 0, 0 for ; p != matcher.pattern_count; w += 1 { if w == matcher.word_count { - return false; + return false } if matcher.lower_word[w] == matcher.lower_pattern[p] { - p += 1; + p += 1 } } - ref := matcher.word_role[:matcher.word_count]; + ref := matcher.word_role[:matcher.word_count] - matcher.word_type_set = fuzzy_calculate_roles(word, &ref); + matcher.word_type_set = fuzzy_calculate_roles(word, &ref) - return true; + return true } fuzzy_skip_penalty :: proc(matcher: ^FuzzyMatcher, w: int) -> int { if w == 0 { // Skipping the first character. - return 3; + return 3 } if matcher.word_role[w] == .Head { // Skipping a segment. - return 1; + return 1 } - return 0; + return 0 } fuzzy_build_graph :: proc(matcher: ^FuzzyMatcher) { for w := 0; w < matcher.word_count; w += 1 { - s: FuzzyScoreInfo; + s: FuzzyScoreInfo - score := cast(int)matcher.scores[0][w][miss].score; - penalty := fuzzy_skip_penalty(matcher, w); - sum := score - penalty; + score := cast(int)matcher.scores[0][w][miss].score + penalty := fuzzy_skip_penalty(matcher, w) + sum := score - penalty - s.score = sum; - s.prev = miss; + s.score = sum + s.prev = miss - matcher.scores[0][w + 1][miss] = s; + matcher.scores[0][w + 1][miss] = s - s.score = awful_score; - s.prev = miss; + s.score = awful_score + s.prev = miss - matcher.scores[0][w + 1][match] = s; + matcher.scores[0][w + 1][match] = s } for p := 0; p < matcher.pattern_count; p += 1 { for w := p; w < matcher.word_count; w += 1 { - score := &matcher.scores[p + 1][w + 1]; - pre_miss := &matcher.scores[p + 1][w]; + score := &matcher.scores[p + 1][w + 1] + pre_miss := &matcher.scores[p + 1][w] - match_miss_score := pre_miss[match].score; - miss_miss_score := pre_miss[miss].score; + match_miss_score := pre_miss[match].score + miss_miss_score := pre_miss[miss].score if p < matcher.pattern_count - 1 { - match_miss_score -= fuzzy_skip_penalty(matcher, w); - miss_miss_score -= fuzzy_skip_penalty(matcher, w); + match_miss_score -= fuzzy_skip_penalty(matcher, w) + miss_miss_score -= fuzzy_skip_penalty(matcher, w) } if match_miss_score > miss_miss_score { - s: FuzzyScoreInfo; - s.score = match_miss_score; - s.prev = match; - score[miss] = s; + s: FuzzyScoreInfo + s.score = match_miss_score + s.prev = match + score[miss] = s } else { - s: FuzzyScoreInfo; - s.score = miss_miss_score; - s.prev = miss; - score[miss] = s; + s: FuzzyScoreInfo + s.score = miss_miss_score + s.prev = miss + score[miss] = s } - pre_match := &matcher.scores[p][w]; + pre_match := &matcher.scores[p][w] - match_match_score := fuzzy_allow_match(matcher, p, w, match) ? cast(int)pre_match[match].score + fuzzy_match_bonus(matcher, p, w, match) : awful_score; + match_match_score := fuzzy_allow_match(matcher, p, w, match) ? cast(int)pre_match[match].score + fuzzy_match_bonus(matcher, p, w, match) : awful_score - miss_match_score := fuzzy_allow_match(matcher, p, w, miss) ? cast(int)pre_match[miss].score + fuzzy_match_bonus(matcher, p, w, miss) : awful_score; + miss_match_score := fuzzy_allow_match(matcher, p, w, miss) ? cast(int)pre_match[miss].score + fuzzy_match_bonus(matcher, p, w, miss) : awful_score if match_match_score > miss_match_score { - s: FuzzyScoreInfo; - s.score = match_match_score; - s.prev = match; - score[match] = s; + s: FuzzyScoreInfo + s.score = match_match_score + s.prev = match + score[match] = s } else { - s: FuzzyScoreInfo; - s.score = miss_match_score; - s.prev = miss; - score[match] = s; + s: FuzzyScoreInfo + s.score = miss_match_score + s.prev = miss + score[match] = s } } } @@ -342,12 +342,12 @@ fuzzy_build_graph :: proc(matcher: ^FuzzyMatcher) { fuzzy_match_bonus :: proc(matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> int { - assert(matcher.lower_pattern[p] == matcher.lower_word[w]); + assert(matcher.lower_pattern[p] == matcher.lower_word[w]) - s := 1; + s := 1 - is_pattern_single_case := (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Lower); - is_pattern_single_case |= (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Upper); + is_pattern_single_case := (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Lower) + is_pattern_single_case |= (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Upper) // Bonus: case matches, or a Head in the pattern aligns with one in the word. // Single-case patterns lack segmentation signals and we assume any character @@ -355,53 +355,53 @@ fuzzy_match_bonus :: proc(matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> if matcher.pattern[p] == matcher.word[w] || (matcher.word_role[w] == FuzzyCharRole.Head && (is_pattern_single_case || matcher.pattern_role[p] == FuzzyCharRole.Head)) { - s += 1; + s += 1 //fmt.println("match 1"); } // Bonus: a consecutive match. First character match also gets a bonus to // ensure prefix final match score normalizes to 1.0. if w == 0 || last == match { - s += 2; + s += 2 //fmt.println("match 2"); } // Penalty: matching inside a segment (and previous char wasn't matched). if matcher.word_role[w] == FuzzyCharRole.Tail && p > 0 && last == miss { - s -= 3; + s -= 3 //fmt.println("match 3"); } // Penalty: a Head in the pattern matches in the middle of a word segment. if matcher.pattern_role[p] == FuzzyCharRole.Head && matcher.word_role[w] == FuzzyCharRole.Tail { - s -= 1; + s -= 1 //fmt.println("match 4"); } // Penalty: matching the first pattern character in the middle of a segment. if p == 0 && matcher.word_role[w] == FuzzyCharRole.Tail { - s -= 4; + s -= 4 //fmt.println("match 5"); } - assert(s <= perfect_bonus); + assert(s <= perfect_bonus) - return s; + return s } fuzzy_allow_match :: proc(matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> bool { if matcher.lower_pattern[p] != matcher.lower_word[w] { - return false; + return false } if last == miss { if matcher.word_role[w] == FuzzyCharRole.Tail && (matcher.word[w] == matcher.lower_word[w] || 0 >= (cast(uint)matcher.word_type_set & 1 << cast(uint)FuzzyCharType.Lower)) { - return false; + return false } } - return true; + return true } diff --git a/src/common/position.odin b/src/common/position.odin index 4e84568..2ccd0a8 100644 --- a/src/common/position.odin +++ b/src/common/position.odin @@ -31,219 +31,219 @@ AbsoluteRange :: struct { end: int, } -AbsolutePosition :: int; +AbsolutePosition :: int get_absolute_position :: proc(position: Position, document_text: []u8) -> (AbsolutePosition, bool) { - absolute: AbsolutePosition; + absolute: AbsolutePosition if len(document_text) == 0 { - absolute = 0; - return absolute, true; + absolute = 0 + return absolute, true } - line_count := 0; - index := 1; - last := document_text[0]; + line_count := 0 + index := 1 + last := document_text[0] if !get_index_at_line(&index, &line_count, &last, document_text, position.line) { - return absolute, false; + return absolute, false } - absolute = index + get_character_offset_u16_to_u8(position.character, document_text[index:]); + absolute = index + get_character_offset_u16_to_u8(position.character, document_text[index:]) - return absolute, true; + return absolute, true } get_relative_token_position :: proc(offset: int, document_text: []u8, current_start: int) -> Position { - start_index := current_start; + start_index := current_start - data := document_text[start_index:]; + data := document_text[start_index:] - i: int; + i: int - position: Position; + position: Position for i + start_index < offset { - r, w := utf8.decode_rune(data[i:]); + r, w := utf8.decode_rune(data[i:]) if r == '\n' { //\r? - position.character = 0; - position.line += 1; - i += 1; + position.character = 0 + position.line += 1 + i += 1 } else if w == 0 { - return position; + return position } else { if r < 0x10000 { - position.character += 1; + position.character += 1 } else { - position.character += 2; + position.character += 2 } - i += w; + i += w } } - return position; + return position } /* Get the range of a token in utf16 space */ get_token_range :: proc(node: ast.Node, document_text: string) -> Range { - range: Range; + range: Range go_backwards_to_endline :: proc(offset: int, document_text: []u8) -> int { - index := offset; + index := offset for index > 0 && document_text[index] != '\n' && document_text[index] != '\r' { - index -= 1; + index -= 1 } if index == 0 { - return 0; + return 0 } - return index + 1; - }; + return index + 1 + } - pos_offset := min(len(document_text) - 1, node.pos.offset); - end_offset := min(len(document_text) - 1, node.end.offset); + pos_offset := min(len(document_text) - 1, node.pos.offset) + end_offset := min(len(document_text) - 1, node.end.offset) - offset := go_backwards_to_endline(pos_offset, transmute([]u8)document_text); + offset := go_backwards_to_endline(pos_offset, transmute([]u8)document_text) - range.start.line = node.pos.line - 1; - range.start.character = get_character_offset_u8_to_u16(node.pos.column - 1, transmute([]u8)document_text[offset:]); + range.start.line = node.pos.line - 1 + range.start.character = get_character_offset_u8_to_u16(node.pos.column - 1, transmute([]u8)document_text[offset:]) - offset = go_backwards_to_endline(end_offset, transmute([]u8)document_text); + offset = go_backwards_to_endline(end_offset, transmute([]u8)document_text) - range.end.line = node.end.line - 1; - range.end.character = get_character_offset_u8_to_u16(node.end.column - 1, transmute([]u8)document_text[offset:]); + range.end.line = node.end.line - 1 + range.end.character = get_character_offset_u8_to_u16(node.end.column - 1, transmute([]u8)document_text[offset:]) - return range; + return range } get_absolute_range :: proc(range: Range, document_text: []u8) -> (AbsoluteRange, bool) { - absolute: AbsoluteRange; + absolute: AbsoluteRange if len(document_text) == 0 { - absolute.start = 0; - absolute.end = 0; - return absolute, true; + absolute.start = 0 + absolute.end = 0 + return absolute, true } - line_count := 0; - index := 1; - last := document_text[0]; + line_count := 0 + index := 1 + last := document_text[0] if !get_index_at_line(&index, &line_count, &last, document_text, range.start.line) { - return absolute, false; + return absolute, false } - absolute.start = index + get_character_offset_u16_to_u8(range.start.character, document_text[index:]); + absolute.start = index + get_character_offset_u16_to_u8(range.start.character, document_text[index:]) //if the last line was indexed at zero we have to move it back to index 1. //This happens when line = 0 if index == 0 { - index = 1; + index = 1 } if !get_index_at_line(&index, &line_count, &last, document_text, range.end.line) { - return absolute, false; + return absolute, false } - absolute.end = index + get_character_offset_u16_to_u8(range.end.character, document_text[index:]); + absolute.end = index + get_character_offset_u16_to_u8(range.end.character, document_text[index:]) - return absolute, true; + return absolute, true } get_index_at_line :: proc(current_index: ^int, current_line: ^int, last: ^u8, document_text: []u8, end_line: int) -> bool { if end_line == 0 { - current_index^ = 0; - return true; + current_index^ = 0 + return true } if current_line^ == end_line { - return true; + return true } for ; current_index^ < len(document_text); current_index^ += 1 { - current := document_text[current_index^]; + current := document_text[current_index^] if last^ == '\r' { - current_line^ += 1; + current_line^ += 1 if current_line^ == end_line { - last^ = current; - current_index^ += 1; - return true; + last^ = current + current_index^ += 1 + return true } } else if current == '\n' { - current_line^ += 1; + current_line^ += 1 if current_line^ == end_line { - last^ = current; - current_index^ += 1; - return true; + last^ = current + current_index^ += 1 + return true } } - last^ = document_text[current_index^]; + last^ = document_text[current_index^] } - return false; + return false } get_character_offset_u16_to_u8 :: proc(character_offset: int, document_text: []u8) -> int { - utf8_idx := 0; - utf16_idx := 0; + utf8_idx := 0 + utf16_idx := 0 for utf16_idx < character_offset { - r, w := utf8.decode_rune(document_text[utf8_idx:]); + r, w := utf8.decode_rune(document_text[utf8_idx:]) if r == '\n' || r == '\r' { - return utf8_idx; + return utf8_idx } else if w == 0 { - return utf8_idx; + return utf8_idx } else if r < 0x10000 { - utf16_idx += 1; + utf16_idx += 1 } else { - utf16_idx += 2; + utf16_idx += 2 } - utf8_idx += w; + utf8_idx += w } - return utf8_idx; + return utf8_idx } get_character_offset_u8_to_u16 :: proc(character_offset: int, document_text: []u8) -> int { - utf8_idx := 0; - utf16_idx := 0; + utf8_idx := 0 + utf16_idx := 0 for utf8_idx < character_offset { - r, w := utf8.decode_rune(document_text[utf8_idx:]); + r, w := utf8.decode_rune(document_text[utf8_idx:]) if r == '\n' || r == '\r' { - return utf16_idx; + return utf16_idx } else if w == 0 { - return utf16_idx; + return utf16_idx } else if r < 0x10000 { - utf16_idx += 1; + utf16_idx += 1 } else { - utf16_idx += 2; + utf16_idx += 2 } - utf8_idx += w; + utf8_idx += w } - return utf16_idx; + return utf16_idx } \ No newline at end of file diff --git a/src/common/sha1.odin b/src/common/sha1.odin index 4516467..4f1d62f 100644 --- a/src/common/sha1.odin +++ b/src/common/sha1.odin @@ -5,58 +5,58 @@ import "core:fmt" //ported version of https://llvm.org/doxygen/SHa1_8cpp_source.html rol :: proc (number: u32, bits: u32) -> u32 { - return number << bits | number >> (32 - bits); + return number << bits | number >> (32 - bits) } blk0 :: proc (buf: []u32, i: int) -> u32 { - return buf[i]; + return buf[i] } blk :: proc (buf: []u32, i: int) -> u32 { buf[i & 15] = rol(buf[(i + 13) & 15] ~ buf[(i + 8) & 15] ~ buf[(i + 2) & 15] ~ - buf[i & 15], 1); + buf[i & 15], 1) - return buf[i & 15]; + return buf[i & 15] } r0 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { - e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk0(buf, i) + 0x5a827999 + rol(a^, 5); - b^ = rol(b^, 30); + e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk0(buf, i) + 0x5a827999 + rol(a^, 5) + b^ = rol(b^, 30) } r1 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { - e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk(buf, i) + 0x5a827999 + rol(a^, 5); - b^ += rol(b^, 30); + e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk(buf, i) + 0x5a827999 + rol(a^, 5) + b^ += rol(b^, 30) } r2 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { - e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0x6ed9eba1 + rol(a^, 5); - b^ += rol(b^, 30); + e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0x6ed9eba1 + rol(a^, 5) + b^ += rol(b^, 30) } r3 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { - e^ += (((b^ | c^) & d^) | (b^ & c^)) + blk(buf, i) + 0x8F1bbcdc + rol(a^, 5); - b^ += rol(b^, 30); + e^ += (((b^ | c^) & d^) | (b^ & c^)) + blk(buf, i) + 0x8F1bbcdc + rol(a^, 5) + b^ += rol(b^, 30) } r4 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { - e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0xca62c1d6 + rol(a^, 5); - b^ += rol(b^, 30); + e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0xca62c1d6 + rol(a^, 5) + b^ += rol(b^, 30) } -SHA1_K0 :: 0x5a827999; -SHA1_K20 :: 0x6ed9eba1; -SHA1_K40 :: 0x8f1bbcdc; -SHA1_K60 :: 0xca62c1d6; +SHA1_K0 :: 0x5a827999 +SHA1_K20 :: 0x6ed9eba1 +SHA1_K40 :: 0x8f1bbcdc +SHA1_K60 :: 0xca62c1d6 -SEED_0 :: 0x67452301; -SEED_1 :: 0xefcdab89; -SEED_2 :: 0x98badcfe; -SEED_3 :: 0x10325476; -SEED_4 :: 0xc3d2e1f0; +SEED_0 :: 0x67452301 +SEED_1 :: 0xefcdab89 +SEED_2 :: 0x98badcfe +SEED_3 :: 0x10325476 +SEED_4 :: 0xc3d2e1f0 -BLOCK_LENGTH :: 64; -HASH_LENGTH :: 20; +BLOCK_LENGTH :: 64 +HASH_LENGTH :: 20 Sha1context :: struct { buf: struct #raw_union { @@ -69,222 +69,222 @@ Sha1context :: struct { } sha1_init :: proc (state_context: ^Sha1context) { - state_context.state[0] = SEED_0; - state_context.state[1] = SEED_1; - state_context.state[2] = SEED_2; - state_context.state[3] = SEED_3; - state_context.state[4] = SEED_4; - state_context.byte_count = 0; - state_context.buf_offset = 0; + state_context.state[0] = SEED_0 + state_context.state[1] = SEED_1 + state_context.state[2] = SEED_2 + state_context.state[3] = SEED_3 + state_context.state[4] = SEED_4 + state_context.byte_count = 0 + state_context.buf_offset = 0 } sha1_hash_block :: proc (state_context: ^Sha1context) { - a := state_context.state[0]; - b := state_context.state[1]; - c := state_context.state[2]; - d := state_context.state[3]; - e := state_context.state[4]; + a := state_context.state[0] + b := state_context.state[1] + c := state_context.state[2] + d := state_context.state[3] + e := state_context.state[4] // 4 rounds of 20 operations each. loop unrolled. - r0(&a, &b, &c, &d, &e, 0, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 1, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 2, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 3, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 4, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 5, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 6, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 7, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 8, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 9, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 10, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 11, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 12, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 13, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 14, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 15, state_context.buf.l[:]); - r1(&e, &a, &b, &c, &d, 16, state_context.buf.l[:]); - r1(&d, &e, &a, &b, &c, 17, state_context.buf.l[:]); - r1(&c, &d, &e, &a, &b, 18, state_context.buf.l[:]); - r1(&b, &c, &d, &e, &a, 19, state_context.buf.l[:]); - - r2(&a, &b, &c, &d, &e, 20, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 21, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 22, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 23, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 24, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 25, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 26, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 27, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 28, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 29, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 30, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 31, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 32, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 33, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 34, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 35, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 36, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 37, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 38, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 39, state_context.buf.l[:]); - - r3(&a, &b, &c, &d, &e, 40, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 41, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 42, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 43, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 44, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 45, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 46, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 47, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 48, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 49, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 50, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 51, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 52, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 53, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 54, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 55, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 56, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 57, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 58, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 59, state_context.buf.l[:]); - - r4(&a, &b, &c, &d, &e, 60, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 61, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 62, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 63, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 64, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 65, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 66, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 67, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 68, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 69, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 70, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 71, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 72, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 73, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 74, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 75, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 76, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 77, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 78, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 79, state_context.buf.l[:]); - - state_context.state[0] += a; - state_context.state[1] += b; - state_context.state[2] += c; - state_context.state[3] += d; - state_context.state[4] += e; + r0(&a, &b, &c, &d, &e, 0, state_context.buf.l[:]) + r0(&e, &a, &b, &c, &d, 1, state_context.buf.l[:]) + r0(&d, &e, &a, &b, &c, 2, state_context.buf.l[:]) + r0(&c, &d, &e, &a, &b, 3, state_context.buf.l[:]) + r0(&b, &c, &d, &e, &a, 4, state_context.buf.l[:]) + r0(&a, &b, &c, &d, &e, 5, state_context.buf.l[:]) + r0(&e, &a, &b, &c, &d, 6, state_context.buf.l[:]) + r0(&d, &e, &a, &b, &c, 7, state_context.buf.l[:]) + r0(&c, &d, &e, &a, &b, 8, state_context.buf.l[:]) + r0(&b, &c, &d, &e, &a, 9, state_context.buf.l[:]) + r0(&a, &b, &c, &d, &e, 10, state_context.buf.l[:]) + r0(&e, &a, &b, &c, &d, 11, state_context.buf.l[:]) + r0(&d, &e, &a, &b, &c, 12, state_context.buf.l[:]) + r0(&c, &d, &e, &a, &b, 13, state_context.buf.l[:]) + r0(&b, &c, &d, &e, &a, 14, state_context.buf.l[:]) + r0(&a, &b, &c, &d, &e, 15, state_context.buf.l[:]) + r1(&e, &a, &b, &c, &d, 16, state_context.buf.l[:]) + r1(&d, &e, &a, &b, &c, 17, state_context.buf.l[:]) + r1(&c, &d, &e, &a, &b, 18, state_context.buf.l[:]) + r1(&b, &c, &d, &e, &a, 19, state_context.buf.l[:]) + + r2(&a, &b, &c, &d, &e, 20, state_context.buf.l[:]) + r2(&e, &a, &b, &c, &d, 21, state_context.buf.l[:]) + r2(&d, &e, &a, &b, &c, 22, state_context.buf.l[:]) + r2(&c, &d, &e, &a, &b, 23, state_context.buf.l[:]) + r2(&b, &c, &d, &e, &a, 24, state_context.buf.l[:]) + r2(&a, &b, &c, &d, &e, 25, state_context.buf.l[:]) + r2(&e, &a, &b, &c, &d, 26, state_context.buf.l[:]) + r2(&d, &e, &a, &b, &c, 27, state_context.buf.l[:]) + r2(&c, &d, &e, &a, &b, 28, state_context.buf.l[:]) + r2(&b, &c, &d, &e, &a, 29, state_context.buf.l[:]) + r2(&a, &b, &c, &d, &e, 30, state_context.buf.l[:]) + r2(&e, &a, &b, &c, &d, 31, state_context.buf.l[:]) + r2(&d, &e, &a, &b, &c, 32, state_context.buf.l[:]) + r2(&c, &d, &e, &a, &b, 33, state_context.buf.l[:]) + r2(&b, &c, &d, &e, &a, 34, state_context.buf.l[:]) + r2(&a, &b, &c, &d, &e, 35, state_context.buf.l[:]) + r2(&e, &a, &b, &c, &d, 36, state_context.buf.l[:]) + r2(&d, &e, &a, &b, &c, 37, state_context.buf.l[:]) + r2(&c, &d, &e, &a, &b, 38, state_context.buf.l[:]) + r2(&b, &c, &d, &e, &a, 39, state_context.buf.l[:]) + + r3(&a, &b, &c, &d, &e, 40, state_context.buf.l[:]) + r3(&e, &a, &b, &c, &d, 41, state_context.buf.l[:]) + r3(&d, &e, &a, &b, &c, 42, state_context.buf.l[:]) + r3(&c, &d, &e, &a, &b, 43, state_context.buf.l[:]) + r3(&b, &c, &d, &e, &a, 44, state_context.buf.l[:]) + r3(&a, &b, &c, &d, &e, 45, state_context.buf.l[:]) + r3(&e, &a, &b, &c, &d, 46, state_context.buf.l[:]) + r3(&d, &e, &a, &b, &c, 47, state_context.buf.l[:]) + r3(&c, &d, &e, &a, &b, 48, state_context.buf.l[:]) + r3(&b, &c, &d, &e, &a, 49, state_context.buf.l[:]) + r3(&a, &b, &c, &d, &e, 50, state_context.buf.l[:]) + r3(&e, &a, &b, &c, &d, 51, state_context.buf.l[:]) + r3(&d, &e, &a, &b, &c, 52, state_context.buf.l[:]) + r3(&c, &d, &e, &a, &b, 53, state_context.buf.l[:]) + r3(&b, &c, &d, &e, &a, 54, state_context.buf.l[:]) + r3(&a, &b, &c, &d, &e, 55, state_context.buf.l[:]) + r3(&e, &a, &b, &c, &d, 56, state_context.buf.l[:]) + r3(&d, &e, &a, &b, &c, 57, state_context.buf.l[:]) + r3(&c, &d, &e, &a, &b, 58, state_context.buf.l[:]) + r3(&b, &c, &d, &e, &a, 59, state_context.buf.l[:]) + + r4(&a, &b, &c, &d, &e, 60, state_context.buf.l[:]) + r4(&e, &a, &b, &c, &d, 61, state_context.buf.l[:]) + r4(&d, &e, &a, &b, &c, 62, state_context.buf.l[:]) + r4(&c, &d, &e, &a, &b, 63, state_context.buf.l[:]) + r4(&b, &c, &d, &e, &a, 64, state_context.buf.l[:]) + r4(&a, &b, &c, &d, &e, 65, state_context.buf.l[:]) + r4(&e, &a, &b, &c, &d, 66, state_context.buf.l[:]) + r4(&d, &e, &a, &b, &c, 67, state_context.buf.l[:]) + r4(&c, &d, &e, &a, &b, 68, state_context.buf.l[:]) + r4(&b, &c, &d, &e, &a, 69, state_context.buf.l[:]) + r4(&a, &b, &c, &d, &e, 70, state_context.buf.l[:]) + r4(&e, &a, &b, &c, &d, 71, state_context.buf.l[:]) + r4(&d, &e, &a, &b, &c, 72, state_context.buf.l[:]) + r4(&c, &d, &e, &a, &b, 73, state_context.buf.l[:]) + r4(&b, &c, &d, &e, &a, 74, state_context.buf.l[:]) + r4(&a, &b, &c, &d, &e, 75, state_context.buf.l[:]) + r4(&e, &a, &b, &c, &d, 76, state_context.buf.l[:]) + r4(&d, &e, &a, &b, &c, 77, state_context.buf.l[:]) + r4(&c, &d, &e, &a, &b, 78, state_context.buf.l[:]) + r4(&b, &c, &d, &e, &a, 79, state_context.buf.l[:]) + + state_context.state[0] += a + state_context.state[1] += b + state_context.state[2] += c + state_context.state[3] += d + state_context.state[4] += e } sha1_add_uncounted :: proc (state_context: ^Sha1context, data: byte) { when ODIN_ENDIAN == .Big { - state_context.buf.c[state_context.buf_offset] = data; + state_context.buf.c[state_context.buf_offset] = data } else { - state_context.buf.c[state_context.buf_offset ~ 3] = data; + state_context.buf.c[state_context.buf_offset ~ 3] = data } - state_context.buf_offset += 1; + state_context.buf_offset += 1 if state_context.buf_offset == BLOCK_LENGTH { - sha1_hash_block(state_context); - state_context.buf_offset = 0; + sha1_hash_block(state_context) + state_context.buf_offset = 0 } } sha1_write_byte :: proc (state_context: ^Sha1context, data: byte) { - state_context.byte_count += 1; - sha1_add_uncounted(state_context, data); + state_context.byte_count += 1 + sha1_add_uncounted(state_context, data) } sha1_update :: proc (state_context: ^Sha1context, data: []byte) { - state_context.byte_count += cast(u32)len(data); + state_context.byte_count += cast(u32)len(data) - current_data := data; + current_data := data if state_context.buf_offset > 0 { - remainder := min(len(current_data), BLOCK_LENGTH - cast(int)state_context.buf_offset); + remainder := min(len(current_data), BLOCK_LENGTH - cast(int)state_context.buf_offset) for i := 0; i < remainder; i += 1 { - sha1_add_uncounted(state_context, current_data[i]); + sha1_add_uncounted(state_context, current_data[i]) } - current_data = current_data[remainder - 1:]; + current_data = current_data[remainder - 1:] } for len(current_data) >= BLOCK_LENGTH { - assert(state_context.buf_offset == 0); - assert(BLOCK_LENGTH % 4 == 0); + assert(state_context.buf_offset == 0) + assert(BLOCK_LENGTH % 4 == 0) - BLOCK_LENGTH_32 :: BLOCK_LENGTH / 4; + BLOCK_LENGTH_32 :: BLOCK_LENGTH / 4 for i := 0; i < BLOCK_LENGTH_32; i += 1 { - n := (transmute([]u32)current_data)[i]; + n := (transmute([]u32)current_data)[i] state_context.buf.l[i] = (((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | - ((n & 0xFF000000) >> 24)); + ((n & 0xFF000000) >> 24)) } - sha1_hash_block(state_context); + sha1_hash_block(state_context) - current_data = current_data[BLOCK_LENGTH - 1:]; + current_data = current_data[BLOCK_LENGTH - 1:] } for c in current_data { - sha1_add_uncounted(state_context, c); + sha1_add_uncounted(state_context, c) } } sha1_pad :: proc (state_context: ^Sha1context) { - sha1_add_uncounted(state_context, 0x80); + sha1_add_uncounted(state_context, 0x80) for state_context.buf_offset != 56 { - sha1_add_uncounted(state_context, 0x00); + sha1_add_uncounted(state_context, 0x00) } - sha1_add_uncounted(state_context, 0); // We're only using 32 bit lengths - sha1_add_uncounted(state_context, 0); // But SHA-1 supports 64 bit lengths - sha1_add_uncounted(state_context, 0); // So zero pad the top bits - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 29)); // Shifting to multiply by 8 - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 21)); // as SHA-1 supports bitstreams as well as - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 13)); // byte. - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 5)); - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count << 3)); + sha1_add_uncounted(state_context, 0) // We're only using 32 bit lengths + sha1_add_uncounted(state_context, 0) // But SHA-1 supports 64 bit lengths + sha1_add_uncounted(state_context, 0) // So zero pad the top bits + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 29)) // Shifting to multiply by 8 + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 21)) // as SHA-1 supports bitstreams as well as + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 13)) // byte. + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 5)) + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count << 3)) } sha1_final :: proc (state_context: ^Sha1context, result: ^[5]u32) { - sha1_pad(state_context); + sha1_pad(state_context) when ODIN_ENDIAN == .Big { for i := 0; i < 5; i += 1 { - result[i] = state_context.state[i]; + result[i] = state_context.state[i] } } else { for i := 0; i < 5; i += 1 { result[i] = (((state_context.state[i]) << 24) & 0xff000000) | (((state_context.state[i]) << 8) & 0x00ff0000) | (((state_context.state[i]) >> 8) & 0x0000ff00) | - (((state_context.state[i]) >> 24) & 0x000000ff); + (((state_context.state[i]) >> 24) & 0x000000ff) } } } sha1_hash :: proc (data: []byte) -> [20]byte { - sha1_context: Sha1context; - sha1_init(&sha1_context); - sha1_update(&sha1_context, data); + sha1_context: Sha1context + sha1_init(&sha1_context) + sha1_update(&sha1_context, data) - result: [20]byte; + result: [20]byte - sha1_final(&sha1_context, cast(^[5]u32)&result); + sha1_final(&sha1_context, cast(^[5]u32)&result) - ret: [20]byte; + ret: [20]byte - copy(ret[:], result[:]); + copy(ret[:], result[:]) - return ret; + return ret } diff --git a/src/common/uri.odin b/src/common/uri.odin index ee25393..d93eab3 100644 --- a/src/common/uri.odin +++ b/src/common/uri.odin @@ -17,116 +17,116 @@ Uri :: struct { parse_uri :: proc(value: string, allocator: mem.Allocator) -> (Uri, bool) { - uri: Uri; + uri: Uri - decoded, ok := decode_percent(value, allocator); + decoded, ok := decode_percent(value, allocator) if !ok { - return uri, false; + return uri, false } - starts := "file:///"; + starts := "file:///" - start_index := len(starts); + start_index := len(starts) if !starts_with(decoded, starts) { - return uri, false; + return uri, false } - when ODIN_OS != "windows" { - start_index -= 1; + when ODIN_OS != .Windows { + start_index -= 1 } - uri.uri = strings.clone(value, allocator); - uri.decode_full = decoded; - uri.path = decoded[start_index:]; + uri.uri = strings.clone(value, allocator) + uri.decode_full = decoded + uri.path = decoded[start_index:] - return uri, true; + return uri, true } //Note(Daniel, Again some really incomplete and scuffed uri writer) create_uri :: proc(path: string, allocator: mem.Allocator) -> Uri { - path_forward, _ := filepath.to_slash(path, context.temp_allocator); + path_forward, _ := filepath.to_slash(path, context.temp_allocator) - builder := strings.make_builder(allocator); + builder := strings.make_builder(allocator) //bad - when ODIN_OS == "windows" { - strings.write_string(&builder, "file:///"); + when ODIN_OS == .Windows { + strings.write_string(&builder, "file:///") } else { - strings.write_string(&builder, "file://"); + strings.write_string(&builder, "file://") } - strings.write_string(&builder, encode_percent(path_forward, context.temp_allocator)); + strings.write_string(&builder, encode_percent(path_forward, context.temp_allocator)) - uri: Uri; + uri: Uri - uri.uri = strings.to_string(builder); - uri.decode_full = strings.clone(path_forward, allocator); - uri.path = uri.decode_full; + uri.uri = strings.to_string(builder) + uri.decode_full = strings.clone(path_forward, allocator) + uri.path = uri.decode_full - return uri; + return uri } delete_uri :: proc(uri: Uri) { if uri.uri != "" { - delete(uri.uri); + delete(uri.uri) } if uri.decode_full != "" { - delete(uri.decode_full); + delete(uri.decode_full) } } encode_percent :: proc(value: string, allocator: mem.Allocator) -> string { - builder := strings.make_builder(allocator); + builder := strings.make_builder(allocator) - data := transmute([]u8)value; - index: int; + data := transmute([]u8)value + index: int for index < len(value) { - r, w := utf8.decode_rune(data[index:]); + r, w := utf8.decode_rune(data[index:]) if r > 127 || r == ':' { for i := 0; i < w; i += 1 { strings.write_string(&builder, strings.concatenate({"%", fmt.tprintf("%X", data[index + i])}, - context.temp_allocator)); + context.temp_allocator)) } } else { - strings.write_byte(&builder, data[index]); + strings.write_byte(&builder, data[index]) } - index += w; + index += w } - return strings.to_string(builder); + return strings.to_string(builder) } @(private) starts_with :: proc(value: string, starts_with: string) -> bool { if len(value) < len(starts_with) { - return false; + return false } for i := 0; i < len(starts_with); i += 1 { if value[i] != starts_with[i] { - return false; + return false } } - return true; + return true } @(private) decode_percent :: proc(value: string, allocator: mem.Allocator) -> (string, bool) { - builder := strings.make_builder(allocator); + builder := strings.make_builder(allocator) for i := 0; i < len(value); i += 1 { @@ -134,24 +134,24 @@ decode_percent :: proc(value: string, allocator: mem.Allocator) -> (string, bool if i + 2 < len(value) { - v, ok := strconv.parse_i64_of_base(value[i + 1:i + 3], 16); + v, ok := strconv.parse_i64_of_base(value[i + 1:i + 3], 16) if !ok { - strings.destroy_builder(&builder); - return "", false; + strings.destroy_builder(&builder) + return "", false } - strings.write_byte(&builder, cast(byte)v); + strings.write_byte(&builder, cast(byte)v) - i += 2; + i += 2 } else { - strings.destroy_builder(&builder); - return "", false; + strings.destroy_builder(&builder) + return "", false } } else { - strings.write_byte(&builder, value[i]); + strings.write_byte(&builder, value[i]) } } - return strings.to_string(builder), true; + return strings.to_string(builder), true } diff --git a/src/common/util_windows.odin b/src/common/util_windows.odin index 835348a..bf89c47 100644 --- a/src/common/util_windows.odin +++ b/src/common/util_windows.odin @@ -11,71 +11,71 @@ foreign import kernel32 "system:kernel32.lib" @(default_calling_convention = "std") foreign kernel32 { - @(link_name = "CreatePipe")create_pipe :: proc (hReadPipe, hWritePipe: ^win32.Handle, lpPipeAttributes: ^win32.Security_Attributes, nSize: i32) -> i32 ---; + @(link_name = "CreatePipe")create_pipe :: proc (hReadPipe, hWritePipe: ^win32.Handle, lpPipeAttributes: ^win32.Security_Attributes, nSize: i32) -> i32 --- } run_executable :: proc(command: string, stdout: ^[]byte) -> (u32, bool, []byte) { - stdout_read: win32.Handle; - stdout_write: win32.Handle; + stdout_read: win32.Handle + stdout_write: win32.Handle - command := strings.clone_to_cstring(command, context.temp_allocator); + command := strings.clone_to_cstring(command, context.temp_allocator) - attributes: win32.Security_Attributes; - attributes.length = size_of(win32.Security_Attributes); - attributes.inherit_handle = true; - attributes.security_descriptor = nil; + attributes: win32.Security_Attributes + attributes.length = size_of(win32.Security_Attributes) + attributes.inherit_handle = true + attributes.security_descriptor = nil if create_pipe(&stdout_read, &stdout_write, &attributes, 0) == 0 { - return 0, false, stdout[0:]; + return 0, false, stdout[0:] } if !win32.set_handle_information(stdout_read, win32.HANDLE_FLAG_INHERIT, 0) { - return 0, false, stdout[0:]; + return 0, false, stdout[0:] } - startup_info: win32.Startup_Info; - process_info: win32.Process_Information; + startup_info: win32.Startup_Info + process_info: win32.Process_Information - startup_info.cb = size_of(win32.Startup_Info); + startup_info.cb = size_of(win32.Startup_Info) - startup_info.stderr = stdout_write; - startup_info.stdout = stdout_write; - startup_info.flags |= win32.STARTF_USESTDHANDLES; + startup_info.stderr = stdout_write + startup_info.stdout = stdout_write + startup_info.flags |= win32.STARTF_USESTDHANDLES if !win32.create_process_a(nil, command, nil, nil, true, 0, nil, nil, &startup_info, &process_info) { - return 0, false, stdout[0:]; + return 0, false, stdout[0:] } - win32.close_handle(stdout_write); + win32.close_handle(stdout_write) - index: int; - read: i32; + index: int + read: i32 - read_buffer: [50]byte; + read_buffer: [50]byte - success: win32.Bool = true; + success: win32.Bool = true for success { - success = win32.read_file(stdout_read, &read_buffer[0], len(read_buffer), &read, nil); + success = win32.read_file(stdout_read, &read_buffer[0], len(read_buffer), &read, nil) if read > 0 && index + cast(int)read <= len(stdout) { - mem.copy(&stdout[index], &read_buffer[0], cast(int)read); + mem.copy(&stdout[index], &read_buffer[0], cast(int)read) } - index += cast(int)read; + index += cast(int)read } - stdout[index + 1] = 0; + stdout[index + 1] = 0 - exit_code: u32; + exit_code: u32 - win32.wait_for_single_object(process_info.process, win32.INFINITE); + win32.wait_for_single_object(process_info.process, win32.INFINITE) - win32.get_exit_code_process(process_info.process, &exit_code); + win32.get_exit_code_process(process_info.process, &exit_code) - win32.close_handle(stdout_read); + win32.close_handle(stdout_read) - return exit_code, true, stdout[0:index]; + return exit_code, true, stdout[0:index] } \ No newline at end of file diff --git a/src/index/build.odin b/src/index/build.odin index c8b1996..a7944f0 100644 --- a/src/index/build.odin +++ b/src/index/build.odin @@ -10,13 +10,14 @@ import "core:log" import "core:odin/tokenizer" import "core:strings" import "core:mem" +import "core:runtime" import "shared:common" -symbol_collection: SymbolCollection; +symbol_collection: SymbolCollection -files: [dynamic]string; +files: [dynamic]string platform_os: map[string]bool = { "windows" = true, @@ -26,135 +27,144 @@ platform_os: map[string]bool = { "freebsd" = true, "darwin" = true, "wasm32" = true, -}; +} + + +os_enum_to_string: map[runtime.Odin_OS_Type]string = { + .Windows = "windows", + .Darwin = "dawrin", + .Linux = "linux", + .Essence = "essence", + .FreeBSD = "freebsd", + .WASI = "wasi", + .JS = "js", + .Freestanding = "freestanding", +} -walk_static_index_build :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { +walk_static_index_build :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { if info.is_dir { - return 0, false; + return 0, false } if filepath.ext(info.name) != ".odin" { - return 0, false; + return 0, false } - last_underscore_index := strings.last_index(info.name, "_"); - last_dot_index := strings.last_index(info.name, "."); + last_underscore_index := strings.last_index(info.name, "_") + last_dot_index := strings.last_index(info.name, ".") if last_underscore_index + 1 < last_dot_index { - - name_between := info.name[last_underscore_index + 1:last_dot_index]; + name_between := info.name[last_underscore_index + 1:last_dot_index] if _, ok := platform_os[name_between]; ok { - if name_between != ODIN_OS { - return 0, false; + if name_between != os_enum_to_string[ODIN_OS] { + return 0, false } } } - forward, _ := filepath.to_slash(info.fullpath, context.temp_allocator); + forward, _ := filepath.to_slash(info.fullpath, context.temp_allocator) - append(&files, strings.clone(forward, context.allocator)); + append(&files, strings.clone(forward, context.allocator)) - return 0, false; + return 0, false } build_static_index :: proc(allocator := context.allocator, config: ^common.Config) { + symbol_collection = make_symbol_collection(allocator, config) - symbol_collection = make_symbol_collection(allocator, config); - - files = make([dynamic]string, context.allocator); + files = make([dynamic]string, context.allocator) for k, v in config.collections { - filepath.walk(v, walk_static_index_build); + filepath.walk(v, walk_static_index_build) } - when ODIN_OS == "windows" { - slashed, _ := filepath.to_slash(os.get_current_directory(context.temp_allocator), context.temp_allocator); + when ODIN_OS == .Windows { + slashed, _ := filepath.to_slash(os.get_current_directory(context.temp_allocator), context.temp_allocator) } else { - slashed, _ := filepath.to_slash(os.get_current_directory(), context.temp_allocator); + slashed, _ := filepath.to_slash(os.get_current_directory(), context.temp_allocator) } - when ODIN_OS == "windows" { - builtin_package := path.join(elems = {slashed, "builtin"}, allocator = context.temp_allocator); - append(&indexer.builtin_packages, strings.to_lower(builtin_package)); + when ODIN_OS == .Windows { + builtin_package := path.join(elems = {slashed, "builtin"}, allocator = context.temp_allocator) + append(&indexer.builtin_packages, strings.to_lower(builtin_package)) } else { - builtin_package := path.join(elems = {slashed, "builtin"}, allocator = context.allocator); - append(&indexer.builtin_packages, builtin_package); + builtin_package := path.join(elems = {slashed, "builtin"}, allocator = context.allocator) + append(&indexer.builtin_packages, builtin_package) } - filepath.walk(builtin_package, walk_static_index_build); + filepath.walk(builtin_package, walk_static_index_build) - temp_arena: mem.Arena; + temp_arena: mem.Arena - mem.init_arena(&temp_arena, make([]byte, mem.megabytes(100))); + mem.init_arena(&temp_arena, make([]byte, mem.megabytes(100))) - context.allocator = mem.arena_allocator(&temp_arena); + context.allocator = mem.arena_allocator(&temp_arena) for fullpath in files { - - data, ok := os.read_entire_file(fullpath, context.allocator); + data, ok := os.read_entire_file(fullpath, context.allocator) if !ok { - log.errorf("failed to read entire file for indexing %v", fullpath); - continue; + log.errorf("failed to read entire file for indexing %v", fullpath) + continue } p := parser.Parser { err = log_error_handler, warn = log_warning_handler, - }; + } //have to cheat the parser since it really wants to parse an entire package with the new changes... - dir := filepath.base(filepath.dir(fullpath, context.allocator)); + dir := filepath.base(filepath.dir(fullpath, context.allocator)) - pkg := new(ast.Package); - pkg.kind = .Normal; - pkg.fullpath = fullpath; - pkg.name = dir; + pkg := new(ast.Package) + pkg.kind = .Normal + pkg.fullpath = fullpath + pkg.name = dir if dir == "runtime" { - pkg.kind = .Runtime; + pkg.kind = .Runtime } file := ast.File { fullpath = fullpath, src = string(data), pkg = pkg, - }; + } - ok = parser.parse_file(&p, &file); + ok = parser.parse_file(&p, &file) if !ok { - log.info(pkg); - log.errorf("error in parse file for indexing %v", fullpath); + log.info(pkg) + log.errorf("error in parse file for indexing %v", fullpath) } - uri := common.create_uri(fullpath, context.allocator); + uri := common.create_uri(fullpath, context.allocator) //ERROR hover on uri does not show string - collect_symbols(&symbol_collection, file, uri.uri); + collect_symbols(&symbol_collection, file, uri.uri) - free_all(context.allocator); + free_all(context.allocator) - delete(fullpath, allocator); + delete(fullpath, allocator) } - delete(files); - delete(temp_arena.data); + delete(files) + delete(temp_arena.data) - indexer.static_index = make_memory_index(symbol_collection); + indexer.static_index = make_memory_index(symbol_collection) } free_static_index :: proc() { - delete_symbol_collection(symbol_collection); + delete_symbol_collection(symbol_collection) } log_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { - log.warnf("%v %v %v", pos, msg, args); + log.warnf("%v %v %v", pos, msg, args) } log_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { - log.warnf("%v %v %v", pos, msg, args); + log.warnf("%v %v %v", pos, msg, args) } diff --git a/src/index/clone.odin b/src/index/clone.odin index a9b6f33..24a1138 100644 --- a/src/index/clone.odin +++ b/src/index/clone.odin @@ -6,15 +6,24 @@ import "core:odin/tokenizer" import "core:odin/ast" import "core:strings" import "core:log" +import "core:intrinsics" +import "core:reflect" +_ :: intrinsics new_type :: proc($T: typeid, pos, end: tokenizer.Pos, allocator: mem.Allocator) -> ^T { - n, _ := mem.new(T, allocator); - n.pos = pos; - n.end = end; - n.derived = n^; - base: ^ast.Node = n; // dummy check - _ = base; // "Use" type to make -vet happy - return n; + n, _ := mem.new(T, allocator) + n.pos = pos + n.end = end + n.derived = n + base: ^ast.Node = n // dummy check + _ = base // "Use" type to make -vet happy + when intrinsics.type_has_field(T, "derived_expr") { + n.derived_expr = n + } + when intrinsics.type_has_field(T, "derived_stmt") { + n.derived_stmt = n + } + return n } clone_type :: proc { @@ -22,242 +31,223 @@ clone_type :: proc { clone_expr, clone_array, clone_dynamic_array, -}; +} clone_array :: proc(array: $A/[]^$T, allocator: mem.Allocator, unique_strings: ^map[string]string) -> A { if len(array) == 0 { - return nil; + return nil } - res := make(A, len(array), allocator); + res := make(A, len(array), allocator) for elem, i in array { - res[i] = cast(^T)clone_type(elem, allocator, unique_strings); + res[i] = cast(^T)clone_type(elem, allocator, unique_strings) } - return res; + return res } clone_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator, unique_strings: ^map[string]string) -> A { if len(array) == 0 { - return nil; + return nil } - res := make(A, len(array), allocator); + res := make(A, len(array), allocator) for elem, i in array { - res[i] = auto_cast clone_type(elem, allocator, unique_strings); + res[i] = auto_cast clone_type(elem, allocator, unique_strings) } - return res; + return res } clone_expr :: proc(node: ^ast.Expr, allocator: mem.Allocator, unique_strings: ^map[string]string) -> ^ast.Expr { - return cast(^ast.Expr)clone_node(node, allocator, unique_strings); + return cast(^ast.Expr)clone_node(node, allocator, unique_strings) } clone_node :: proc(node: ^ast.Node, allocator: mem.Allocator, unique_strings: ^map[string]string) -> ^ast.Node { - - using ast; - + using ast if node == nil { - return nil; + return nil } - size := size_of(Node); - align := align_of(Node); - ti := type_info_of(node.derived.id); + size := size_of(Node) + align := align_of(Node) + ti := reflect.union_variant_type_info(node.derived) if ti != nil { - size = ti.size; - align = ti.align; + elem := ti.variant.(reflect.Type_Info_Pointer).elem + size = elem.size + align = elem.align + } + + #partial switch in node.derived { + case ^Package, ^File: + panic("Cannot clone this node type") } - res := cast(^Node)mem.alloc(size, align, allocator); - src: rawptr = node; + res := cast(^Node)mem.alloc(size, align, allocator) + src: rawptr = node if node.derived != nil { - src = node.derived.data; + src = (^rawptr)(&node.derived)^ } - mem.copy(res, src, size); - res.derived.data = rawptr(res); + mem.copy(res, src, size) + res_ptr_any: any + res_ptr_any.data = &res + res_ptr_any.id = ti.id if unique_strings != nil && node.pos.file != "" { - res.pos.file = get_index_unique_string(unique_strings, allocator, node.pos.file); + res.pos.file = get_index_unique_string(unique_strings, allocator, node.pos.file) } else { - res.pos.file = node.pos.file; + res.pos.file = node.pos.file } if unique_strings != nil && node.end.file != "" { - res.end.file = get_index_unique_string(unique_strings, allocator, node.end.file); + res.end.file = get_index_unique_string(unique_strings, allocator, node.end.file) } else { - res.end.file = node.end.file; + res.end.file = node.end.file } - switch n in node.derived { - case Bad_Expr: - case Ident: - r := cast(^Ident)res; + reflect.set_union_value(res.derived, res_ptr_any) + + res_ptr := reflect.deref(res_ptr_any) + + if de := reflect.struct_field_value_by_name(res_ptr, "derived_expr", true); de != nil { + reflect.set_union_value(de, res_ptr_any) + } + if ds := reflect.struct_field_value_by_name(res_ptr, "derived_stmt", true); ds != nil { + reflect.set_union_value(ds, res_ptr_any) + } + + if res.derived != nil do #partial switch r in res.derived { + case ^Ident: + n := node.derived.(^Ident) + if unique_strings == nil { - r.name = strings.clone(n.name, allocator); + r.name = strings.clone(n.name, allocator) } else { - r.name = get_index_unique_string(unique_strings, allocator, n.name); + r.name = get_index_unique_string(unique_strings, allocator, n.name) } - case Implicit: - r := cast(^Implicit)res; + case ^Implicit: + n := node.derived.(^Implicit) if unique_strings == nil { - r.tok.text = strings.clone(n.tok.text, allocator); + r.tok.text = strings.clone(n.tok.text, allocator) } else { - r.tok.text = get_index_unique_string(unique_strings, allocator, n.tok.text); + r.tok.text = get_index_unique_string(unique_strings, allocator, n.tok.text) } - case Undef: - case Basic_Lit: - r := cast(^Basic_Lit)res; + case ^Undef: + case ^Basic_Lit: + n := node.derived.(^Basic_Lit) if unique_strings == nil { - r.tok.text = strings.clone(n.tok.text, allocator); + r.tok.text = strings.clone(n.tok.text, allocator) } else { - r.tok.text = get_index_unique_string(unique_strings, allocator, n.tok.text); + r.tok.text = get_index_unique_string(unique_strings, allocator, n.tok.text) } - case Basic_Directive: - r := cast(^Basic_Directive)res; + case ^Basic_Directive: + n := node.derived.(^Basic_Directive) if unique_strings == nil { - r.name = strings.clone(n.name, allocator); + r.name = strings.clone(n.name, allocator) } else { - r.name = get_index_unique_string(unique_strings, allocator, n.name); + r.name = get_index_unique_string(unique_strings, allocator, n.name) } - case Ellipsis: - r := cast(^Ellipsis)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - case Tag_Expr: - r := cast(^Tag_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - case Unary_Expr: - r := cast(^Unary_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - case Binary_Expr: - r := cast(^Binary_Expr)res; - r.left = clone_type(r.left, allocator, unique_strings); - r.right = clone_type(r.right, allocator, unique_strings); - case Paren_Expr: - r := cast(^Paren_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - case Selector_Expr: - r := cast(^Selector_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - r.field = auto_cast clone_type(r.field, allocator, unique_strings); - case Implicit_Selector_Expr: - r := cast(^Implicit_Selector_Expr)res; - r.field = auto_cast clone_type(r.field, allocator, unique_strings); - case Slice_Expr: - r := cast(^Slice_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - r.low = clone_type(r.low, allocator, unique_strings); - r.high = clone_type(r.high, allocator, unique_strings); - case Attribute: - r := cast(^Attribute)res; - r.elems = clone_type(r.elems, allocator, unique_strings); - case Distinct_Type: - r := cast(^Distinct_Type)res; - r.type = clone_type(r.type, allocator, unique_strings); - case Proc_Type: - r := cast(^Proc_Type)res; - r.params = auto_cast clone_type(r.params, allocator, unique_strings); - r.results = auto_cast clone_type(r.results, allocator, unique_strings); - case Pointer_Type: - r := cast(^Pointer_Type)res; - r.elem = clone_type(r.elem, allocator, unique_strings); - case Array_Type: - r := cast(^Array_Type)res; - r.len = clone_type(r.len, allocator, unique_strings); - r.elem = clone_type(r.elem, allocator, unique_strings); - r.tag = clone_type(r.tag, allocator, unique_strings); - case Dynamic_Array_Type: - r := cast(^Dynamic_Array_Type)res; - r.elem = clone_type(r.elem, allocator, unique_strings); - r.tag = clone_type(r.tag, allocator, unique_strings); - case Struct_Type: - r := cast(^Struct_Type)res; - r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings); - r.align = clone_type(r.align, allocator, unique_strings); - r.fields = auto_cast clone_type(r.fields, allocator, unique_strings); - r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings); - case Field: - r := cast(^Field)res; - r.names = clone_type(r.names, allocator, unique_strings); - r.type = clone_type(r.type, allocator, unique_strings); - r.default_value = clone_type(r.default_value, allocator, unique_strings); - case Field_List: - r := cast(^Field_List)res; - r.list = clone_type(r.list, allocator, unique_strings); - case Field_Value: - r := cast(^Field_Value)res; - r.field = clone_type(r.field, allocator, unique_strings); - r.value = clone_type(r.value, allocator, unique_strings); - case Union_Type: - r := cast(^Union_Type)res; - r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings); - r.align = clone_type(r.align, allocator, unique_strings); - r.variants = clone_type(r.variants, allocator, unique_strings); - r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings); - case Enum_Type: - r := cast(^Enum_Type)res; - r.base_type = clone_type(r.base_type, allocator, unique_strings); - r.fields = clone_type(r.fields, allocator, unique_strings); - case Bit_Set_Type: - r := cast(^Bit_Set_Type)res; - r.elem = clone_type(r.elem, allocator, unique_strings); - r.underlying = clone_type(r.underlying, allocator, unique_strings); - case Map_Type: - r := cast(^Map_Type)res; - r.key = clone_type(r.key, allocator, unique_strings); - r.value = clone_type(r.value, allocator, unique_strings); - case Call_Expr: - r := cast(^Call_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - r.args = clone_type(r.args, allocator, unique_strings); - case Typeid_Type: - r := cast(^Typeid_Type)res; - r.specialization = clone_type(r.specialization, allocator, unique_strings); - case Ternary_When_Expr: - r := cast(^Ternary_When_Expr)res; - r.x = clone_type(r.x, allocator, unique_strings); - r.cond = clone_type(r.cond, allocator, unique_strings); - r.y = clone_type(r.y, allocator, unique_strings); - case Poly_Type: - r := cast(^Poly_Type)res; - r.type = auto_cast clone_type(r.type, allocator, unique_strings); - r.specialization = clone_type(r.specialization, allocator, unique_strings); - case Proc_Group: - r := cast(^Proc_Group)res; - r.args = clone_type(r.args, allocator, unique_strings); - case Comp_Lit: - r := cast(^Comp_Lit)res; - r.type = clone_type(r.type, allocator, unique_strings); - r.elems = clone_type(r.elems, allocator, unique_strings); - case Proc_Lit: - r := cast(^Proc_Lit)res; - r.type = cast(^Proc_Type)clone_type(cast(^Node)r.type, allocator, unique_strings); - r.body = nil; - r.where_clauses = nil; - case Helper_Type: - r := cast(^Helper_Type)res; - r.type = clone_type(r.type, allocator, unique_strings); - case Type_Cast: - r := cast(^Type_Cast)res; - r.type = clone_type(r.type, allocator, unique_strings); - r.expr = clone_type(r.expr, allocator, unique_strings); - case Deref_Expr: - r := cast(^Deref_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - case Index_Expr: - r := cast(^Index_Expr)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - r.index = clone_type(r.index, allocator, unique_strings); - case Multi_Pointer_Type: - r := cast(^Multi_Pointer_Type)res; - r.elem = clone_type(r.elem, allocator, unique_strings); - case Matrix_Type: - r := cast(^Matrix_Type)res; - r.elem = clone_type(r.elem, allocator, unique_strings); - case Type_Assertion: - r := cast(^Type_Assertion)res; - r.expr = clone_type(r.expr, allocator, unique_strings); - r.type = clone_type(r.type, allocator, unique_strings); + case ^Ellipsis: + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Tag_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Unary_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Binary_Expr: + r.left = clone_type(r.left, allocator, unique_strings) + r.right = clone_type(r.right, allocator, unique_strings) + case ^Paren_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Selector_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + r.field = auto_cast clone_type(r.field, allocator, unique_strings) + case ^Implicit_Selector_Expr: + r.field = auto_cast clone_type(r.field, allocator, unique_strings) + case ^Slice_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + r.low = clone_type(r.low, allocator, unique_strings) + r.high = clone_type(r.high, allocator, unique_strings) + case ^Attribute: + r.elems = clone_type(r.elems, allocator, unique_strings) + case ^Distinct_Type: + r.type = clone_type(r.type, allocator, unique_strings) + case ^Proc_Type: + r.params = auto_cast clone_type(r.params, allocator, unique_strings) + r.results = auto_cast clone_type(r.results, allocator, unique_strings) + case ^Pointer_Type: + r.elem = clone_type(r.elem, allocator, unique_strings) + case ^Array_Type: + r.len = clone_type(r.len, allocator, unique_strings) + r.elem = clone_type(r.elem, allocator, unique_strings) + r.tag = clone_type(r.tag, allocator, unique_strings) + case ^Dynamic_Array_Type: + r.elem = clone_type(r.elem, allocator, unique_strings) + r.tag = clone_type(r.tag, allocator, unique_strings) + case ^Struct_Type: + r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings) + r.align = clone_type(r.align, allocator, unique_strings) + r.fields = auto_cast clone_type(r.fields, allocator, unique_strings) + r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings) + case ^Field: + r.names = clone_type(r.names, allocator, unique_strings) + r.type = clone_type(r.type, allocator, unique_strings) + r.default_value = clone_type(r.default_value, allocator, unique_strings) + case ^Field_List: + r.list = clone_type(r.list, allocator, unique_strings) + case ^Field_Value: + r.field = clone_type(r.field, allocator, unique_strings) + r.value = clone_type(r.value, allocator, unique_strings) + case ^Union_Type: + r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings) + r.align = clone_type(r.align, allocator, unique_strings) + r.variants = clone_type(r.variants, allocator, unique_strings) + r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings) + case ^Enum_Type: + r.base_type = clone_type(r.base_type, allocator, unique_strings) + r.fields = clone_type(r.fields, allocator, unique_strings) + case ^Bit_Set_Type: + r.elem = clone_type(r.elem, allocator, unique_strings) + r.underlying = clone_type(r.underlying, allocator, unique_strings) + case ^Map_Type: + r.key = clone_type(r.key, allocator, unique_strings) + r.value = clone_type(r.value, allocator, unique_strings) + case ^Call_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + r.args = clone_type(r.args, allocator, unique_strings) + case ^Typeid_Type: + r.specialization = clone_type(r.specialization, allocator, unique_strings) + case ^Ternary_When_Expr: + r.x = clone_type(r.x, allocator, unique_strings) + r.cond = clone_type(r.cond, allocator, unique_strings) + r.y = clone_type(r.y, allocator, unique_strings) + case ^Poly_Type: + r.type = auto_cast clone_type(r.type, allocator, unique_strings) + r.specialization = clone_type(r.specialization, allocator, unique_strings) + case ^Proc_Group: + r.args = clone_type(r.args, allocator, unique_strings) + case ^Comp_Lit: + r.type = clone_type(r.type, allocator, unique_strings) + r.elems = clone_type(r.elems, allocator, unique_strings) + case ^Proc_Lit: + r.type = cast(^Proc_Type)clone_type(cast(^Node)r.type, allocator, unique_strings) + r.body = nil + r.where_clauses = nil + case ^Helper_Type: + r.type = clone_type(r.type, allocator, unique_strings) + case ^Type_Cast: + r.type = clone_type(r.type, allocator, unique_strings) + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Deref_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + case ^Index_Expr: + r.expr = clone_type(r.expr, allocator, unique_strings) + r.index = clone_type(r.index, allocator, unique_strings) + case ^Multi_Pointer_Type: + r.elem = clone_type(r.elem, allocator, unique_strings) + case ^Matrix_Type: + r.elem = clone_type(r.elem, allocator, unique_strings) + case ^Type_Assertion: + r.expr = clone_type(r.expr, allocator, unique_strings) + r.type = clone_type(r.type, allocator, unique_strings) case: - panic(fmt.aprintf("Clone type Unhandled node kind: %T", node.derived)); + //fmt.logf("Unhandled node kind: %T", r) } - return res; + return res } diff --git a/src/index/collector.odin b/src/index/collector.odin index 49df1e6..495e2a3 100644 --- a/src/index/collector.odin +++ b/src/index/collector.odin @@ -22,20 +22,19 @@ SymbolCollection :: struct { get_index_unique_string :: proc { get_index_unique_string_collection, get_index_unique_string_collection_raw, -}; +} get_index_unique_string_collection :: proc(collection: ^SymbolCollection, s: string) -> string { - return get_index_unique_string_collection_raw(&collection.unique_strings, collection.allocator, s); + return get_index_unique_string_collection_raw(&collection.unique_strings, collection.allocator, s) } get_index_unique_string_collection_raw :: proc(unique_strings: ^map[string]string, allocator: mem.Allocator, s: string) -> string { - //i'm hashing this string way to much if _, ok := unique_strings[s]; !ok { - str := strings.clone(s, allocator); - unique_strings[str] = str; //yeah maybe I have to use some integer and hash it, tried that before but got name collisions. + str := strings.clone(s, allocator) + unique_strings[str] = str } - return unique_strings[s]; + return unique_strings[s] } make_symbol_collection :: proc(allocator := context.allocator, config: ^common.Config) -> SymbolCollection { @@ -44,42 +43,39 @@ make_symbol_collection :: proc(allocator := context.allocator, config: ^common.C config = config, symbols = make(map[uint]Symbol, 16, allocator), unique_strings = make(map[string]string, 16, allocator), - }; + } } delete_symbol_collection :: proc(collection: SymbolCollection) { - for k, v in collection.symbols { - free_symbol(v, collection.allocator); + free_symbol(v, collection.allocator) } for k, v in collection.unique_strings { - delete(v, collection.allocator); + delete(v, collection.allocator) } - delete(collection.symbols); - delete(collection.unique_strings); + delete(collection.symbols) + delete(collection.unique_strings) } collect_procedure_fields :: proc(collection: ^SymbolCollection, proc_type: ^ast.Proc_Type, arg_list: ^ast.Field_List, return_list: ^ast.Field_List, package_map: map[string]string) -> SymbolProcedureValue { - returns := make([dynamic]^ast.Field, 0, collection.allocator); - args := make([dynamic]^ast.Field, 0, collection.allocator); + returns := make([dynamic]^ast.Field, 0, collection.allocator) + args := make([dynamic]^ast.Field, 0, collection.allocator) if return_list != nil { - for ret in return_list.list { - cloned := cast(^ast.Field)clone_type(ret, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); - append(&returns, cloned); + cloned := cast(^ast.Field)clone_type(ret, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) + append(&returns, cloned) } } if arg_list != nil { - for arg in arg_list.list { - cloned := cast(^ast.Field)clone_type(arg, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); - append(&args, cloned); + cloned := cast(^ast.Field)clone_type(arg, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) + append(&args, cloned) } } @@ -87,27 +83,26 @@ collect_procedure_fields :: proc(collection: ^SymbolCollection, proc_type: ^ast. return_types = returns[:], arg_types = args[:], generic = proc_type.generic, - }; - return value; + } + return value } collect_struct_fields :: proc(collection: ^SymbolCollection, struct_type: ast.Struct_Type, package_map: map[string]string) -> SymbolStructValue { - names := make([dynamic]string, 0, collection.allocator); - types := make([dynamic]^ast.Expr, 0, collection.allocator); - usings := make(map[string]bool, 0, collection.allocator); + names := make([dynamic]string, 0, collection.allocator) + types := make([dynamic]^ast.Expr, 0, collection.allocator) + usings := make(map[string]bool, 0, collection.allocator) for field in struct_type.fields.list { - for n in field.names { - ident := n.derived.(ast.Ident); - append(&names, get_index_unique_string(collection, ident.name)); + ident := n.derived.(^ast.Ident) + append(&names, get_index_unique_string(collection, ident.name)) - cloned := clone_type(field.type, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); - append(&types, cloned); + cloned := clone_type(field.type, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) + append(&types, cloned) if .Using in field.flags { - usings[names[len(names) - 1]] = true; + usings[names[len(names) - 1]] = true } } } @@ -117,345 +112,345 @@ collect_struct_fields :: proc(collection: ^SymbolCollection, struct_type: ast.St types = types[:], usings = usings, poly = cast(^ast.Field_List)clone_type(struct_type.poly_params, collection.allocator, &collection.unique_strings), - }; + } - return value; + return value } collect_enum_fields :: proc(collection: ^SymbolCollection, fields: []^ast.Expr, package_map: map[string]string) -> SymbolEnumValue { - names := make([dynamic]string, 0, collection.allocator); + names := make([dynamic]string, 0, collection.allocator) //ERROR no hover on n in the for, but elsewhere is fine for n in fields { - if ident, ok := n.derived.(ast.Ident); ok { - append(&names, get_index_unique_string(collection, ident.name)); - } else if field, ok := n.derived.(ast.Field_Value); ok { - if ident, ok := field.field.derived.(ast.Ident); ok { - append(&names, get_index_unique_string(collection, ident.name)); - } else if binary, ok := field.field.derived.(ast.Binary_Expr); ok { - append(&names, get_index_unique_string(collection, binary.left.derived.(ast.Ident).name)); + if ident, ok := n.derived.(^ast.Ident); ok { + append(&names, get_index_unique_string(collection, ident.name)) + } else if field, ok := n.derived.(^ast.Field_Value); ok { + if ident, ok := field.field.derived.(^ast.Ident); ok { + append(&names, get_index_unique_string(collection, ident.name)) + } else if binary, ok := field.field.derived.(^ast.Binary_Expr); ok { + append(&names, get_index_unique_string(collection, binary.left.derived.(^ast.Ident).name)) } } } value := SymbolEnumValue { names = names[:], - }; + } - return value; + return value } collect_union_fields :: proc(collection: ^SymbolCollection, union_type: ast.Union_Type, package_map: map[string]string) -> SymbolUnionValue { - types := make([dynamic]^ast.Expr, 0, collection.allocator); + types := make([dynamic]^ast.Expr, 0, collection.allocator) for variant in union_type.variants { - cloned := clone_type(variant, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); - append(&types, cloned); + cloned := clone_type(variant, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) + append(&types, cloned) } value := SymbolUnionValue { types = types[:], poly = cast(^ast.Field_List)clone_type(union_type.poly_params, collection.allocator, &collection.unique_strings), - }; + } - return value; + return value } collect_bitset_field :: proc(collection: ^SymbolCollection, bitset_type: ast.Bit_Set_Type, package_map: map[string]string) -> SymbolBitSetValue { - cloned := clone_type(bitset_type.elem, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); + cloned := clone_type(bitset_type.elem, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) return SymbolBitSetValue { expr = cloned, - }; + } } collect_slice :: proc(collection: ^SymbolCollection, array: ast.Array_Type, package_map: map[string]string) -> SymbolFixedArrayValue { - elem := clone_type(array.elem, collection.allocator, &collection.unique_strings); - len := clone_type(array.len, collection.allocator, &collection.unique_strings); + elem := clone_type(array.elem, collection.allocator, &collection.unique_strings) + len := clone_type(array.len, collection.allocator, &collection.unique_strings) - replace_package_alias(elem, package_map, collection); - replace_package_alias(len, package_map, collection); + replace_package_alias(elem, package_map, collection) + replace_package_alias(len, package_map, collection) return SymbolFixedArrayValue { expr = elem, len = len, - }; + } } collect_array :: proc(collection: ^SymbolCollection, array: ast.Array_Type, package_map: map[string]string) -> SymbolSliceValue { - elem := clone_type(array.elem, collection.allocator, &collection.unique_strings); + elem := clone_type(array.elem, collection.allocator, &collection.unique_strings) - replace_package_alias(elem, package_map, collection); + replace_package_alias(elem, package_map, collection) return SymbolSliceValue { expr = elem, - }; + } } collect_map :: proc(collection: ^SymbolCollection, m: ast.Map_Type, package_map: map[string]string) -> SymbolMapValue { - key := clone_type(m.key, collection.allocator, &collection.unique_strings); - value := clone_type(m.value, collection.allocator, &collection.unique_strings); + key := clone_type(m.key, collection.allocator, &collection.unique_strings) + value := clone_type(m.value, collection.allocator, &collection.unique_strings) - replace_package_alias(key, package_map, collection); - replace_package_alias(value, package_map, collection); + replace_package_alias(key, package_map, collection) + replace_package_alias(value, package_map, collection) return SymbolMapValue { key = key, value = value, - }; + } } collect_dynamic_array :: proc(collection: ^SymbolCollection, array: ast.Dynamic_Array_Type, package_map: map[string]string) -> SymbolDynamicArrayValue { - elem := clone_type(array.elem, collection.allocator, &collection.unique_strings); + elem := clone_type(array.elem, collection.allocator, &collection.unique_strings) - replace_package_alias(elem, package_map, collection); + replace_package_alias(elem, package_map, collection) return SymbolDynamicArrayValue { expr = elem, - }; + } } collect_generic :: proc(collection: ^SymbolCollection, expr: ^ast.Expr, package_map: map[string]string, uri: string) -> SymbolGenericValue { //Bit hacky right now, but it's hopefully a temporary solution. //In the c package code it uses a documentation package(builtin). - if selector, ok := expr.derived.(ast.Selector_Expr); ok { - if ident, ok := selector.expr.derived.(ast.Ident); ok { + if selector, ok := expr.derived.(^ast.Selector_Expr); ok { + if ident, ok := selector.expr.derived.(^ast.Ident); ok { if ident.name == "builtin" && strings.contains(uri, "Odin/core/c/c.odin") { - cloned := clone_type(selector.field, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); + cloned := clone_type(selector.field, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) value := SymbolGenericValue { expr = cloned, - }; - return value; + } + return value } } } - cloned := clone_type(expr, collection.allocator, &collection.unique_strings); - replace_package_alias(cloned, package_map, collection); + cloned := clone_type(expr, collection.allocator, &collection.unique_strings) + replace_package_alias(cloned, package_map, collection) value := SymbolGenericValue { expr = cloned, - }; + } - return value; + return value } collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: string) -> common.Error { - forward, _ := filepath.to_slash(file.fullpath, context.temp_allocator); + forward, _ := filepath.to_slash(file.fullpath, context.temp_allocator) - when ODIN_OS == "windows" { - directory := strings.to_lower(path.dir(forward, context.temp_allocator), context.temp_allocator); + when ODIN_OS == .Windows { + directory := strings.to_lower(path.dir(forward, context.temp_allocator), context.temp_allocator) } else { - directory := path.dir(forward, context.temp_allocator); + directory := path.dir(forward, context.temp_allocator) } - package_map := get_package_mapping(file, collection.config, directory); + package_map := get_package_mapping(file, collection.config, directory) - exprs := common.collect_globals(file, true); + exprs := common.collect_globals(file, true) for expr in exprs { - symbol: Symbol; + symbol: Symbol - token: ast.Node; - token_type: SymbolType; + token: ast.Node + token_type: SymbolType - name := expr.name; + name := expr.name - col_expr := expr.expr; + col_expr := expr.expr - if helper, ok := col_expr.derived.(ast.Helper_Type); ok { + if helper, ok := col_expr.derived.(^ast.Helper_Type); ok { if helper.type != nil { - col_expr = helper.type; + col_expr = helper.type } } - if dist, ok := col_expr.derived.(ast.Distinct_Type); ok { + if dist, ok := col_expr.derived.(^ast.Distinct_Type); ok { if dist.type != nil { - col_expr = dist.type; + col_expr = dist.type } } - switch v in col_expr.derived { - case ast.Proc_Lit: - token = v; - token_type = .Function; + #partial switch v in col_expr.derived { + case ^ast.Proc_Lit: + token = v^ + token_type = .Function if v.type != nil { - symbol.value = collect_procedure_fields(collection, v.type, v.type.params, v.type.results, package_map); + symbol.value = collect_procedure_fields(collection, v.type, v.type.params, v.type.results, package_map) } - case ast.Proc_Type: - token = v; - token_type = .Function; - symbol.value = collect_procedure_fields(collection, cast(^ast.Proc_Type)col_expr, v.params, v.results, package_map); - case ast.Proc_Group: - token = v; - token_type = .Function; + case ^ast.Proc_Type: + token = v^ + token_type = .Function + symbol.value = collect_procedure_fields(collection, cast(^ast.Proc_Type)col_expr, v.params, v.results, package_map) + case ^ast.Proc_Group: + token = v^ + token_type = .Function symbol.value = SymbolProcedureGroupValue { group = clone_type(col_expr, collection.allocator, &collection.unique_strings), - }; - case ast.Struct_Type: - token = v; - token_type = .Struct; - symbol.value = collect_struct_fields(collection, v, package_map); - symbol.signature = "struct"; - case ast.Enum_Type: - token = v; - token_type = .Enum; - symbol.value = collect_enum_fields(collection, v.fields, package_map); - symbol.signature = "enum"; - case ast.Union_Type: - token = v; - token_type = .Union; - symbol.value = collect_union_fields(collection, v, package_map); - symbol.signature = "union"; - case ast.Bit_Set_Type: - token = v; - token_type = .Enum; - symbol.value = collect_bitset_field(collection, v, package_map); - symbol.signature = "bitset"; - case ast.Map_Type: - token = v; - token_type = .Variable; - symbol.value = collect_map(collection, v, package_map); - case ast.Array_Type: - token = v; - token_type = .Variable; + } + case ^ast.Struct_Type: + token = v^ + token_type = .Struct + symbol.value = collect_struct_fields(collection, v^, package_map) + symbol.signature = "struct" + case ^ast.Enum_Type: + token = v^ + token_type = .Enum + symbol.value = collect_enum_fields(collection, v.fields, package_map) + symbol.signature = "enum" + case ^ast.Union_Type: + token = v^ + token_type = .Union + symbol.value = collect_union_fields(collection, v^, package_map) + symbol.signature = "union" + case ^ast.Bit_Set_Type: + token = v^ + token_type = .Enum + symbol.value = collect_bitset_field(collection, v^, package_map) + symbol.signature = "bitset" + case ^ast.Map_Type: + token = v^ + token_type = .Variable + symbol.value = collect_map(collection, v^, package_map) + case ^ast.Array_Type: + token = v^ + token_type = .Variable if v.len == nil { - symbol.value = collect_slice(collection, v, package_map); + symbol.value = collect_slice(collection, v^, package_map) } else { - symbol.value = collect_array(collection, v, package_map); + symbol.value = collect_array(collection, v^, package_map) } - case ast.Dynamic_Array_Type: - token = v; - token_type = .Variable; - symbol.value = collect_dynamic_array(collection, v, package_map); - case ast.Basic_Lit: - token = v; - symbol.value = collect_generic(collection, col_expr, package_map, uri); + case ^ast.Dynamic_Array_Type: + token = v^ + token_type = .Variable + symbol.value = collect_dynamic_array(collection, v^, package_map) + case ^ast.Basic_Lit: + token = v^ + symbol.value = collect_generic(collection, col_expr, package_map, uri) if expr.mutable { - token_type = .Variable; + token_type = .Variable } else { - token_type = .Constant; + token_type = .Constant } - case ast.Ident: - token = v; - symbol.value = collect_generic(collection, col_expr, package_map, uri); + case ^ast.Ident: + token = v^ + symbol.value = collect_generic(collection, col_expr, package_map, uri) if expr.mutable { - token_type = .Variable; + token_type = .Variable } else { - token_type = .Unresolved; + token_type = .Unresolved } case: // default - symbol.value = collect_generic(collection, col_expr, package_map, uri); + symbol.value = collect_generic(collection, col_expr, package_map, uri) if expr.mutable { - token_type = .Variable; + token_type = .Variable } else { - token_type = .Unresolved; + token_type = .Unresolved } - token = expr.expr; + token = expr.expr } - symbol.range = common.get_token_range(token, file.src); - symbol.name = get_index_unique_string(collection, name); - symbol.pkg = get_index_unique_string(collection, directory); - symbol.type = token_type; - symbol.doc = common.get_doc(expr.docs, collection.allocator); + symbol.range = common.get_token_range(token, file.src) + symbol.name = get_index_unique_string(collection, name) + symbol.pkg = get_index_unique_string(collection, directory) + symbol.type = token_type + symbol.doc = common.get_doc(expr.docs, collection.allocator) if expr.deprecated { - symbol.flags |= {.Deprecated}; + symbol.flags |= {.Deprecated} } if expr.file_private { - symbol.flags |= {.PrivateFile}; + symbol.flags |= {.PrivateFile} } if expr.package_private { - symbol.flags |= {.PrivatePackage}; + symbol.flags |= {.PrivatePackage} } - when ODIN_OS == "windows" { - symbol.uri = get_index_unique_string(collection, strings.to_lower(uri, context.temp_allocator)); + when ODIN_OS == .Windows { + symbol.uri = get_index_unique_string(collection, strings.to_lower(uri, context.temp_allocator)) } else { - symbol.uri = get_index_unique_string(collection, uri); + symbol.uri = get_index_unique_string(collection, uri) } - cat := strings.concatenate({symbol.pkg, name}, context.temp_allocator); + cat := strings.concatenate({symbol.pkg, name}, context.temp_allocator) - id := get_symbol_id(cat); + id := get_symbol_id(cat) if v, ok := collection.symbols[id]; !ok || v.name == "" { - collection.symbols[id] = symbol; + collection.symbols[id] = symbol } else { - free_symbol(symbol, collection.allocator); + free_symbol(symbol, collection.allocator) } } - return .None; + return .None } /* Gets the map from import alias to absolute package directory */ get_package_mapping :: proc(file: ast.File, config: ^common.Config, directory: string) -> map[string]string { - package_map := make(map[string]string, 0, context.temp_allocator); + package_map := make(map[string]string, 0, context.temp_allocator) for imp, index in file.imports { //collection specified if i := strings.index(imp.fullpath, ":"); i != -1 { //ERROR hover on collection should show string - collection := imp.fullpath[1:i]; - p := imp.fullpath[i + 1:len(imp.fullpath) - 1]; + collection := imp.fullpath[1:i] + p := imp.fullpath[i + 1:len(imp.fullpath) - 1] - dir, ok := config.collections[collection]; + dir, ok := config.collections[collection] if !ok { - continue; + continue } - name: string; + name: string - when ODIN_OS == "windows" { - full := path.join(elems = {strings.to_lower(dir, context.temp_allocator), p}, allocator = context.temp_allocator); + when ODIN_OS == .Windows { + full := path.join(elems = {strings.to_lower(dir, context.temp_allocator), p}, allocator = context.temp_allocator) } else { - full := path.join(elems = {dir, p}, allocator = context.temp_allocator); + full := path.join(elems = {dir, p}, allocator = context.temp_allocator) } if imp.name.text != "" { - name = imp.name.text; + name = imp.name.text } else { - name = path.base(full, false, context.temp_allocator); + name = path.base(full, false, context.temp_allocator) } - when ODIN_OS == "windows" { - package_map[name] = strings.to_lower(full, context.temp_allocator); + when ODIN_OS == .Windows { + package_map[name] = strings.to_lower(full, context.temp_allocator) } else { - package_map[name] = full; + package_map[name] = full } } else { - name: string; + name: string - full := path.join(elems = {directory, imp.fullpath[1:len(imp.fullpath) - 1]}, allocator = context.temp_allocator); + full := path.join(elems = {directory, imp.fullpath[1:len(imp.fullpath) - 1]}, allocator = context.temp_allocator) - full = path.clean(full, context.temp_allocator); + full = path.clean(full, context.temp_allocator) if imp.name.text != "" { - name = imp.name.text; + name = imp.name.text } else { - name = path.base(full, false, context.temp_allocator); + name = path.base(full, false, context.temp_allocator) } - when ODIN_OS == "windows" { - package_map[name] = strings.to_lower(full, context.temp_allocator); + when ODIN_OS == .Windows { + package_map[name] = strings.to_lower(full, context.temp_allocator) } else { - package_map[name] = full; + package_map[name] = full } } } - return package_map; + return package_map } /* @@ -468,127 +463,125 @@ replace_package_alias :: proc { replace_package_alias_expr, replace_package_alias_array, replace_package_alias_dynamic_array, -}; +} replace_package_alias_array :: proc(array: $A/[]^$T, package_map: map[string]string, collection: ^SymbolCollection) { for elem, i in array { - replace_package_alias(elem, package_map, collection); + replace_package_alias(elem, package_map, collection) } } replace_package_alias_dynamic_array :: proc(array: $A/[dynamic]^$T, package_map: map[string]string, collection: ^SymbolCollection) { for elem, i in array { - replace_package_alias(elem, package_map, collection); + replace_package_alias(elem, package_map, collection) } } replace_package_alias_expr :: proc(node: ^ast.Expr, package_map: map[string]string, collection: ^SymbolCollection) { - replace_package_alias_node(node, package_map, collection); + replace_package_alias_node(node, package_map, collection) } replace_package_alias_node :: proc(node: ^ast.Node, package_map: map[string]string, collection: ^SymbolCollection) { - using ast; + using ast if node == nil { - return; + return } - switch n in node.derived { - case Bad_Expr: - case Ident: - case Implicit: - case Undef: - case Basic_Lit: - case Basic_Directive: - case Ellipsis: - replace_package_alias(n.expr, package_map, collection); - case Tag_Expr: - replace_package_alias(n.expr, package_map, collection); - case Unary_Expr: - replace_package_alias(n.expr, package_map, collection); - case Binary_Expr: - replace_package_alias(n.left, package_map, collection); - replace_package_alias(n.right, package_map, collection); - case Paren_Expr: - replace_package_alias(n.expr, package_map, collection); - case Selector_Expr: - - if _, ok := n.expr.derived.(Ident); ok { - - ident := &n.expr.derived.(Ident); + #partial switch n in node.derived { + case ^Bad_Expr: + case ^Ident: + case ^Implicit: + case ^Undef: + case ^Basic_Lit: + case ^Basic_Directive: + case ^Ellipsis: + replace_package_alias(n.expr, package_map, collection) + case ^Tag_Expr: + replace_package_alias(n.expr, package_map, collection) + case ^Unary_Expr: + replace_package_alias(n.expr, package_map, collection) + case ^Binary_Expr: + replace_package_alias(n.left, package_map, collection) + replace_package_alias(n.right, package_map, collection) + case ^Paren_Expr: + replace_package_alias(n.expr, package_map, collection) + case ^Selector_Expr: + if _, ok := n.expr.derived.(^Ident); ok { + ident := n.expr.derived.(^Ident) if package_name, ok := package_map[ident.name]; ok { - ident.name = get_index_unique_string(collection, package_name); + ident.name = get_index_unique_string(collection, package_name) } } else { - replace_package_alias(n.expr, package_map, collection); - replace_package_alias(n.field, package_map, collection); + replace_package_alias(n.expr, package_map, collection) + replace_package_alias(n.field, package_map, collection) } - case Implicit_Selector_Expr: - replace_package_alias(n.field, package_map, collection); - case Slice_Expr: - replace_package_alias(n.expr, package_map, collection); - replace_package_alias(n.low, package_map, collection); - replace_package_alias(n.high, package_map, collection); - case Attribute: - replace_package_alias(n.elems, package_map, collection); - case Distinct_Type: - replace_package_alias(n.type, package_map, collection); - case Proc_Type: - replace_package_alias(n.params, package_map, collection); - replace_package_alias(n.results, package_map, collection); - case Pointer_Type: - replace_package_alias(n.elem, package_map, collection); - case Array_Type: - replace_package_alias(n.len, package_map, collection); - replace_package_alias(n.elem, package_map, collection); - case Dynamic_Array_Type: - replace_package_alias(n.elem, package_map, collection); - case Struct_Type: - replace_package_alias(n.poly_params, package_map, collection); - replace_package_alias(n.align, package_map, collection); - replace_package_alias(n.fields, package_map, collection); - case Field: - replace_package_alias(n.names, package_map, collection); - replace_package_alias(n.type, package_map, collection); - replace_package_alias(n.default_value, package_map, collection); - case Field_List: - replace_package_alias(n.list, package_map, collection); - case Field_Value: - replace_package_alias(n.field, package_map, collection); - replace_package_alias(n.value, package_map, collection); - case Union_Type: - replace_package_alias(n.poly_params, package_map, collection); - replace_package_alias(n.align, package_map, collection); - replace_package_alias(n.variants, package_map, collection); - case Enum_Type: - replace_package_alias(n.base_type, package_map, collection); - replace_package_alias(n.fields, package_map, collection); - case Bit_Set_Type: - replace_package_alias(n.elem, package_map, collection); - replace_package_alias(n.underlying, package_map, collection); - case Map_Type: - replace_package_alias(n.key, package_map, collection); - replace_package_alias(n.value, package_map, collection); - case Call_Expr: - replace_package_alias(n.expr, package_map, collection); - replace_package_alias(n.args, package_map, collection); - case Typeid_Type: - replace_package_alias(n.specialization, package_map, collection); - case Poly_Type: - replace_package_alias(n.type, package_map, collection); - replace_package_alias(n.specialization, package_map, collection); - case Proc_Group: - replace_package_alias(n.args, package_map, collection); - case Comp_Lit: - replace_package_alias(n.type, package_map, collection); - replace_package_alias(n.elems, package_map, collection); - case Helper_Type: - replace_package_alias(n.type, package_map, collection); - case Proc_Lit: - case Multi_Pointer_Type: - replace_package_alias(n.elem, package_map, collection); + case ^Implicit_Selector_Expr: + replace_package_alias(n.field, package_map, collection) + case ^Slice_Expr: + replace_package_alias(n.expr, package_map, collection) + replace_package_alias(n.low, package_map, collection) + replace_package_alias(n.high, package_map, collection) + case ^Attribute: + replace_package_alias(n.elems, package_map, collection) + case ^Distinct_Type: + replace_package_alias(n.type, package_map, collection) + case ^Proc_Type: + replace_package_alias(n.params, package_map, collection) + replace_package_alias(n.results, package_map, collection) + case ^Pointer_Type: + replace_package_alias(n.elem, package_map, collection) + case ^Array_Type: + replace_package_alias(n.len, package_map, collection) + replace_package_alias(n.elem, package_map, collection) + case ^Dynamic_Array_Type: + replace_package_alias(n.elem, package_map, collection) + case ^Struct_Type: + replace_package_alias(n.poly_params, package_map, collection) + replace_package_alias(n.align, package_map, collection) + replace_package_alias(n.fields, package_map, collection) + case ^Field: + replace_package_alias(n.names, package_map, collection) + replace_package_alias(n.type, package_map, collection) + replace_package_alias(n.default_value, package_map, collection) + case ^Field_List: + replace_package_alias(n.list, package_map, collection) + case ^Field_Value: + replace_package_alias(n.field, package_map, collection) + replace_package_alias(n.value, package_map, collection) + case ^Union_Type: + replace_package_alias(n.poly_params, package_map, collection) + replace_package_alias(n.align, package_map, collection) + replace_package_alias(n.variants, package_map, collection) + case ^Enum_Type: + replace_package_alias(n.base_type, package_map, collection) + replace_package_alias(n.fields, package_map, collection) + case ^Bit_Set_Type: + replace_package_alias(n.elem, package_map, collection) + replace_package_alias(n.underlying, package_map, collection) + case ^Map_Type: + replace_package_alias(n.key, package_map, collection) + replace_package_alias(n.value, package_map, collection) + case ^Call_Expr: + replace_package_alias(n.expr, package_map, collection) + replace_package_alias(n.args, package_map, collection) + case ^Typeid_Type: + replace_package_alias(n.specialization, package_map, collection) + case ^Poly_Type: + replace_package_alias(n.type, package_map, collection) + replace_package_alias(n.specialization, package_map, collection) + case ^Proc_Group: + replace_package_alias(n.args, package_map, collection) + case ^Comp_Lit: + replace_package_alias(n.type, package_map, collection) + replace_package_alias(n.elems, package_map, collection) + case ^Helper_Type: + replace_package_alias(n.type, package_map, collection) + case ^Proc_Lit: + case ^Multi_Pointer_Type: + replace_package_alias(n.elem, package_map, collection) case: - log.warnf("Replace Unhandled node kind: %T", n); + log.warnf("Replace Unhandled node kind: %T", n) } } diff --git a/src/index/indexer.odin b/src/index/indexer.odin index 42b111c..a67c147 100644 --- a/src/index/indexer.odin +++ b/src/index/indexer.odin @@ -41,7 +41,7 @@ Indexer :: struct { dynamic_index: MemoryIndex, } -indexer: Indexer; +indexer: Indexer FuzzyResult :: struct { symbol: Symbol, @@ -50,62 +50,62 @@ FuzzyResult :: struct { lookup :: proc(name: string, pkg: string, loc := #caller_location) -> (Symbol, bool) { if symbol, ok := memory_index_lookup(&indexer.dynamic_index, name, pkg); ok { - log.infof("lookup dynamic name: %v pkg: %v, symbol %v location %v", name, pkg, symbol, loc); - return symbol, true; + log.infof("lookup dynamic name: %v pkg: %v, symbol %v location %v", name, pkg, symbol, loc) + return symbol, true } if symbol, ok := memory_index_lookup(&indexer.static_index, name, pkg); ok { - log.infof("lookup name: %v pkg: %v, symbol %v location %v", name, pkg, symbol, loc); - return symbol, true; + log.infof("lookup name: %v pkg: %v, symbol %v location %v", name, pkg, symbol, loc) + return symbol, true } - log.infof("lookup failed name: %v pkg: %v location %v", name, pkg, loc); - return {}, false; + log.infof("lookup failed name: %v pkg: %v location %v", name, pkg, loc) + return {}, false } fuzzy_search :: proc(name: string, pkgs: []string) -> ([]FuzzyResult, bool) { - dynamic_results, dynamic_ok := memory_index_fuzzy_search(&indexer.dynamic_index, name, pkgs); - static_results, static_ok := memory_index_fuzzy_search(&indexer.static_index, name, pkgs); - result := make([dynamic]FuzzyResult, context.temp_allocator); - files := make(map[string]bool, 0, context.temp_allocator); + dynamic_results, dynamic_ok := memory_index_fuzzy_search(&indexer.dynamic_index, name, pkgs) + static_results, static_ok := memory_index_fuzzy_search(&indexer.static_index, name, pkgs) + result := make([dynamic]FuzzyResult, context.temp_allocator) + files := make(map[string]bool, 0, context.temp_allocator) if !dynamic_ok || !static_ok { - return {}, false; + return {}, false } for r in dynamic_results { - files[r.symbol.uri] = true; - append(&result, r); + files[r.symbol.uri] = true + append(&result, r) } for r in static_results { if r.symbol.uri in files { - continue; + continue } - append(&result, r); + append(&result, r) } - sort.sort(fuzzy_sort_interface(&result)); + sort.sort(fuzzy_sort_interface(&result)) - return result[:], true; + return result[:], true } fuzzy_sort_interface :: proc(s: ^[dynamic]FuzzyResult) -> sort.Interface { return sort.Interface { collection = rawptr(s), len = proc(it: sort.Interface) -> int { - s := (^[dynamic]FuzzyResult)(it.collection); - return len(s^); + s := (^[dynamic]FuzzyResult)(it.collection) + return len(s^) }, less = proc(it: sort.Interface, i, j: int) -> bool { - s := (^[dynamic]FuzzyResult)(it.collection); - return s[i].score > s[j].score; + s := (^[dynamic]FuzzyResult)(it.collection) + return s[i].score > s[j].score }, swap = proc(it: sort.Interface, i, j: int) { - s := (^[dynamic]FuzzyResult)(it.collection); - s[i], s[j] = s[j], s[i]; + s := (^[dynamic]FuzzyResult)(it.collection) + s[i], s[j] = s[j], s[i] }, - }; + } } diff --git a/src/index/memory_index.odin b/src/index/memory_index.odin index e946811..d4e7e6e 100644 --- a/src/index/memory_index.odin +++ b/src/index/memory_index.odin @@ -22,44 +22,44 @@ make_memory_index :: proc(collection: SymbolCollection) -> MemoryIndex { return MemoryIndex { collection = collection, - }; + } } memory_index_lookup :: proc(index: ^MemoryIndex, name: string, pkg: string) -> (Symbol, bool) { - id := get_symbol_id(strings.concatenate({pkg, name}, context.temp_allocator)); - return index.collection.symbols[id]; + id := get_symbol_id(strings.concatenate({pkg, name}, context.temp_allocator)) + return index.collection.symbols[id] } memory_index_fuzzy_search :: proc(index: ^MemoryIndex, name: string, pkgs: []string) -> ([]FuzzyResult, bool) { - symbols := make([dynamic]FuzzyResult, 0, context.temp_allocator); + symbols := make([dynamic]FuzzyResult, 0, context.temp_allocator) - fuzzy_matcher := common.make_fuzzy_matcher(name); + fuzzy_matcher := common.make_fuzzy_matcher(name) - top := 20; + top := 20 for _, symbol in index.collection.symbols { if !exists_in_scope(symbol.pkg, pkgs) { - continue; + continue } if score, ok := common.fuzzy_match(fuzzy_matcher, symbol.name); ok == 1 { result := FuzzyResult { symbol = symbol, score = score, - }; + } - append(&symbols, result); + append(&symbols, result) } } - sort.sort(fuzzy_sort_interface(&symbols)); + sort.sort(fuzzy_sort_interface(&symbols)) if name == "" { - return symbols[:], true; + return symbols[:], true } else { - return symbols[:min(top, len(symbols))], true; + return symbols[:min(top, len(symbols))], true } } @@ -67,9 +67,9 @@ exists_in_scope :: proc(symbol_scope: string, scope: []string) -> bool { for s in scope { if strings.compare(symbol_scope, s) == 0 { - return true; + return true } } - return false; + return false } diff --git a/src/index/symbol.odin b/src/index/symbol.odin index 3ee808f..c00c08e 100644 --- a/src/index/symbol.odin +++ b/src/index/symbol.odin @@ -138,54 +138,54 @@ SymbolType :: enum { } new_clone_symbol :: proc(data: Symbol, allocator := context.allocator) -> (^Symbol) { - new_symbol := new(Symbol, allocator); - new_symbol^ = data; - new_symbol.value = data.value; - return new_symbol; + new_symbol := new(Symbol, allocator) + new_symbol^ = data + new_symbol.value = data.value + return new_symbol } free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) { if symbol.signature != "" && symbol.signature != "struct" && symbol.signature != "union" && symbol.signature != "enum" && symbol.signature != "bitset" { - delete(symbol.signature, allocator); + delete(symbol.signature, allocator) } if symbol.doc != "" { - delete(symbol.doc, allocator); + delete(symbol.doc, allocator) } #partial switch v in symbol.value { case SymbolProcedureValue: - common.free_ast(v.return_types, allocator); - common.free_ast(v.arg_types, allocator); + common.free_ast(v.return_types, allocator) + common.free_ast(v.arg_types, allocator) case SymbolStructValue: - delete(v.names, allocator); - common.free_ast(v.types, allocator); + delete(v.names, allocator) + common.free_ast(v.types, allocator) case SymbolGenericValue: - common.free_ast(v.expr, allocator); + common.free_ast(v.expr, allocator) case SymbolProcedureGroupValue: - common.free_ast(v.group, allocator); + common.free_ast(v.group, allocator) case SymbolEnumValue: - delete(v.names, allocator); + delete(v.names, allocator) case SymbolUnionValue: - common.free_ast(v.types, allocator); + common.free_ast(v.types, allocator) case SymbolBitSetValue: - common.free_ast(v.expr, allocator); + common.free_ast(v.expr, allocator) case SymbolDynamicArrayValue: - common.free_ast(v.expr, allocator); + common.free_ast(v.expr, allocator) case SymbolFixedArrayValue: - common.free_ast(v.expr, allocator); - common.free_ast(v.len, allocator); + common.free_ast(v.expr, allocator) + common.free_ast(v.len, allocator) case SymbolSliceValue: - common.free_ast(v.expr, allocator); + common.free_ast(v.expr, allocator) case SymbolBasicValue: - common.free_ast(v.ident, allocator); + common.free_ast(v.ident, allocator) } } get_symbol_id :: proc(str: string) -> uint { - ret := common.sha1_hash(transmute([]byte)str); - r := cast(^uint)slice.first_ptr(ret[:]); - return r^; + ret := common.sha1_hash(transmute([]byte)str) + r := cast(^uint)slice.first_ptr(ret[:]) + return r^ } diff --git a/src/main.odin b/src/main.odin index 69ad85b..b30cd5b 100644 --- a/src/main.odin +++ b/src/main.odin @@ -19,72 +19,72 @@ import "shared:server" import "shared:common" os_read :: proc(handle: rawptr, data: []byte) -> (int, int) { - ptr := cast(^os.Handle)handle; - a, b := os.read(ptr^, data); - return a, cast(int)b; + ptr := cast(^os.Handle)handle + a, b := os.read(ptr^, data) + return a, cast(int)b } os_write :: proc(handle: rawptr, data: []byte) -> (int, int) { - ptr := cast(^os.Handle)handle; - a, b := os.write(ptr^, data); - return a, cast(int)b; + ptr := cast(^os.Handle)handle + a, b := os.write(ptr^, data) + return a, cast(int)b } //Note(Daniel, Should look into handling errors without crashing from parsing) -verbose_logger: log.Logger; -file_logger: log.Logger; -file_logger_init: bool; -request_thread: ^thread.Thread; +verbose_logger: log.Logger +file_logger: log.Logger +file_logger_init: bool +request_thread: ^thread.Thread run :: proc(reader: ^server.Reader, writer: ^server.Writer) { - common.config.collections = make(map[string]string); + common.config.collections = make(map[string]string) - log.info("Starting Odin Language Server"); + log.info("Starting Odin Language Server") - common.config.running = true; + common.config.running = true request_thread_data := server.RequestThreadData { reader = reader, writer = writer, - }; + } - sync.mutex_init(&server.requests_mutex); - sync.semaphore_init(&server.requests_sempahore); + sync.mutex_init(&server.requests_mutex) + sync.semaphore_init(&server.requests_sempahore) - server.requests = make([dynamic]server.Request, context.allocator); - server.deletings = make([dynamic]server.Request, context.allocator); + server.requests = make([dynamic]server.Request, context.allocator) + server.deletings = make([dynamic]server.Request, context.allocator) - request_thread = thread.create_and_start_with_data(cast(rawptr)&request_thread_data, server.thread_request_main); + request_thread = thread.create_and_start_with_data(cast(rawptr)&request_thread_data, server.thread_request_main) for common.config.running { if common.config.file_log { if !file_logger_init { if fh, err := os.open("log.txt"); err == 0 { - file_logger = log.create_file_logger(fh, log.Level.Info); + file_logger = log.create_file_logger(fh, log.Level.Info) } } - context.logger = file_logger; + context.logger = file_logger } else if common.config.verbose { - context.logger = verbose_logger; + context.logger = verbose_logger } else { - context.logger = log.Logger {nil, nil, log.Level.Debug, nil}; + context.logger = log.Logger {nil, nil, log.Level.Debug, nil} } - server.consume_requests(&common.config, writer); + server.consume_requests(&common.config, writer) } for k, v in common.config.collections { - delete(k); - delete(v); + delete(k) + delete(v) } - delete(common.config.collections); - delete(common.config.workspace_folders); + delete(common.config.collections) + delete(common.config.workspace_folders) - server.document_storage_shutdown(); + server.document_storage_shutdown() - index.free_static_index(); + index.free_static_index() } end :: proc() { @@ -92,14 +92,14 @@ end :: proc() { main :: proc() { - reader := server.make_reader(os_read, cast(rawptr)&os.stdin); - writer := server.make_writer(os_write, cast(rawptr)&os.stdout); + reader := server.make_reader(os_read, cast(rawptr)&os.stdin) + writer := server.make_writer(os_write, cast(rawptr)&os.stdout) - verbose_logger := server.create_lsp_logger(&writer, log.Level.Error); + verbose_logger := server.create_lsp_logger(&writer, log.Level.Error) - context.logger = verbose_logger; + context.logger = verbose_logger - init_global_temporary_allocator(mem.megabytes(100)); + init_global_temporary_allocator(mem.megabytes(100)) - run(&reader, &writer); + run(&reader, &writer) } diff --git a/src/odin/printer/document.odin b/src/odin/printer/document.odin index 76c94ea..3f7bb69 100644 --- a/src/odin/printer/document.odin +++ b/src/odin/printer/document.odin @@ -219,7 +219,7 @@ fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool { case Document_Newline: if v.amount > 0 { consumed^ = start_width - width - return true; + return true } case Document_Cons: append(list, Tuple {indentation = data.indentation, mode = data.mode, document = v.rhs, alignment = data.alignment}) diff --git a/src/odin/printer/printer.odin b/src/odin/printer/printer.odin index 88c1c41..1438b34 100644 --- a/src/odin/printer/printer.odin +++ b/src/odin/printer/printer.odin @@ -71,7 +71,7 @@ Newline_Style :: enum { } -when ODIN_OS == "windows" { +when ODIN_OS == .Windows { default_style := Config { spaces = 4, newline_limit = 2, @@ -156,7 +156,7 @@ print :: proc(p: ^Printer, file: ^ast.File) -> string { p.source_position.line = 1 p.source_position.column = 1 - p.document = move_line(p, file.pkg_token.pos); + p.document = move_line(p, file.pkg_token.pos) p.document = cons(p.document, cons_with_nopl(text(file.pkg_token.text), text(file.pkg_name))) for decl in file.decls { diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin index 84a6b9c..f67dcee 100644 --- a/src/odin/printer/visit.odin +++ b/src/odin/printer/visit.odin @@ -202,13 +202,13 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do return visit_disabled(p, decl) } - switch v in &decl.derived { - case Expr_Stmt: + #partial switch v in decl.derived { + case ^Expr_Stmt: document := move_line(p, decl.pos) return cons(document, visit_expr(p, v.expr)) - case When_Stmt: + case ^When_Stmt: return visit_stmt(p, cast(^Stmt)decl) - case Foreign_Import_Decl: + case ^Foreign_Import_Decl: document := empty() if len(v.attributes) > 0 { document = cons(document, visit_attributes(p, &v.attributes, v.pos)) @@ -235,7 +235,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do } return document - case Foreign_Block_Decl: + case ^Foreign_Block_Decl: document := empty() if len(v.attributes) > 0 { document = cons(document, visit_attributes(p, &v.attributes, v.pos)) @@ -245,7 +245,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do document = cons(document, cons_with_opl(text("foreign"), visit_expr(p, v.foreign_library))) document = cons_with_nopl(document, visit_stmt(p, v.body)) return document - case Import_Decl: + case ^Import_Decl: document := move_line(p, decl.pos) if v.name.text != "" { @@ -260,7 +260,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do document = cons(document, text(v.fullpath)) } return document - case Value_Decl: + case ^Value_Decl: document := empty() if len(v.attributes) > 0 { document = cons(document, visit_attributes(p, &v.attributes, v.pos)) @@ -321,7 +321,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do @(private) is_values_binary :: proc(p: ^Printer, list: []^ast.Expr) -> bool { for expr in list { - if _, bin := expr.derived.(ast.Binary_Expr); bin { + if _, bin := expr.derived.(^ast.Binary_Expr); bin { return true } } @@ -384,7 +384,7 @@ visit_enum_exprs :: proc(p: ^Printer, enum_type: ast.Enum_Type, options := List_ if (.Enforce_Newline in options) { alignment := get_possible_enum_alignment(p, enum_type.fields) - if value, ok := expr.derived.(ast.Field_Value); ok && alignment > 0 { + if value, ok := expr.derived.(^ast.Field_Value); ok && alignment > 0 { document = cons(document, cons_with_nopl(visit_expr(p, value.field), cons_with_nopl(cons(repeat_space(alignment - get_node_length(value.field)), text_position(p, "=", value.sep)), visit_expr(p, value.value)))) } else { document = group(cons(document, visit_expr(p, expr, .Generic, options))) @@ -429,7 +429,7 @@ visit_union_exprs :: proc(p: ^Printer, union_type: ast.Union_Type, options := Li if (.Enforce_Newline in options) { alignment := get_possible_enum_alignment(p, union_type.variants) - if value, ok := expr.derived.(ast.Field_Value); ok && alignment > 0 { + if value, ok := expr.derived.(^ast.Field_Value); ok && alignment > 0 { document = cons(document, cons_with_nopl(visit_expr(p, value.field), cons_with_nopl(cons(repeat_space(alignment - get_node_length(value.field)), text_position(p, "=", value.sep)), visit_expr(p, value.value)))) } else { document = group(cons(document, visit_expr(p, expr, .Generic, options))) @@ -473,7 +473,7 @@ visit_comp_lit_exprs :: proc(p: ^Printer, comp_lit: ast.Comp_Lit, options := Lis if (.Enforce_Newline in options) { alignment := get_possible_comp_lit_alignment(p, comp_lit.elems) - if value, ok := expr.derived.(ast.Field_Value); ok && alignment > 0 { + if value, ok := expr.derived.(^ast.Field_Value); ok && alignment > 0 { document = cons(document, cons_with_nopl(visit_expr(p, value.field), cons_with_nopl(cons(repeat_space(alignment - get_node_length(value.field)), text_position(p, "=", value.sep)), visit_expr(p, value.value)))) } else { document = group(cons(document, visit_expr(p, expr, .Generic, options))) @@ -535,23 +535,23 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener return visit_disabled(p, stmt) } - switch v in stmt.derived { - case Import_Decl: + #partial switch v in stmt.derived { + case ^Import_Decl: return visit_decl(p, cast(^Decl)stmt, true) - case Value_Decl: + case ^Value_Decl: return visit_decl(p, cast(^Decl)stmt, true) - case Foreign_Import_Decl: + case ^Foreign_Import_Decl: return visit_decl(p, cast(^Decl)stmt, true) - case Foreign_Block_Decl: + case ^Foreign_Block_Decl: return visit_decl(p, cast(^Decl)stmt, true) } - switch v in stmt.derived { - case Using_Stmt: + #partial switch v in stmt.derived { + case ^Using_Stmt: document := move_line(p, v.pos) document = cons(document, cons_with_nopl(text("using"), visit_exprs(p, v.list, {.Add_Comma}))) return document - case Block_Stmt: + case ^Block_Stmt: document := move_line(p, v.pos) @@ -586,7 +586,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener document = cons(document, visit_end_brace(p, v.end)) } return document - case If_Stmt: + case ^If_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -619,14 +619,14 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener set_source_position(p, v.else_stmt.pos) - if _, ok := v.else_stmt.derived.(ast.If_Stmt); ok { + if _, ok := v.else_stmt.derived.(^ast.If_Stmt); ok { document = cons_with_opl(document, cons_with_nopl(text("else"), visit_stmt(p, v.else_stmt))) } else { document = cons_with_opl(document, cons_with_nopl(text("else"), visit_stmt(p, v.else_stmt))) } } return document - case Switch_Stmt: + case ^Switch_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -650,7 +650,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener document = cons_with_opl(document, visit_expr(p, v.cond)) document = cons_with_nopl(document, visit_stmt(p, v.body, .Switch_Stmt)) return document - case Case_Clause: + case ^Case_Clause: document := move_line(p, v.pos) document = cons(document, text("case")) @@ -666,7 +666,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener } return document - case Type_Switch_Stmt: + case ^Type_Switch_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -682,13 +682,13 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener document = cons_with_nopl(document, visit_stmt(p, v.tag)) document = cons_with_nopl(document, visit_stmt(p, v.body, .Switch_Stmt)) return document - case Assign_Stmt: + case ^Assign_Stmt: document := move_line(p, v.pos) assign_document := group(cons_with_nopl(visit_exprs(p, v.lhs, {.Add_Comma, .Glue}), text(v.op.text))) if block_stmt { - if should_align_assignment_stmt(p, v) { + if should_align_assignment_stmt(p, v^) { assign_document = fill_group(cons(assign_document, align(cons(break_with_space(), visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt))))) } else { assign_document = fill_group(cons(assign_document, cons(break_with_space(), visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt)))) @@ -697,11 +697,11 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener assign_document = cons_with_nopl(assign_document, visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt)) } return cons(document, group(assign_document)) - case Expr_Stmt: + case ^Expr_Stmt: document := move_line(p, v.pos) document = cons(document, visit_expr(p, v.expr)) return document - case For_Stmt: + case ^For_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -711,19 +711,19 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener for_document := text("for") if v.init != nil { - set_source_position(p, v.init.pos); + set_source_position(p, v.init.pos) for_document = cons_with_nopl(for_document, cons(group(visit_stmt(p, v.init)), text(";"))) } else if v.post != nil { for_document = cons_with_nopl(for_document, text(";")) } if v.cond != nil { - set_source_position(p, v.cond.pos); + set_source_position(p, v.cond.pos) for_document = cons_with_opl(for_document, fill_group(visit_expr(p, v.cond))) } if v.post != nil { - set_source_position(p, v.post.pos); + set_source_position(p, v.post.pos) for_document = cons(for_document, text(";")) for_document = cons_with_opl(for_document, group(visit_stmt(p, v.post))) } else if v.post == nil && v.cond != nil && v.init != nil { @@ -737,7 +737,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener set_source_position(p, v.body.end) return document - case Inline_Range_Stmt: + case ^Inline_Range_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -762,7 +762,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener set_source_position(p, v.body.end) return document - case Range_Stmt: + case ^Range_Stmt: document := move_line(p, v.pos) if v.label != nil { @@ -788,7 +788,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener set_source_position(p, v.body.end) return document - case Return_Stmt: + case ^Return_Stmt: document := move_line(p, v.pos) document = cons(document, text("return")) @@ -798,12 +798,12 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener } return document - case Defer_Stmt: + case ^Defer_Stmt: document := move_line(p, v.pos) document = cons(document, text("defer")) document = cons_with_nopl(document, visit_stmt(p, v.stmt)) return document - case When_Stmt: + case ^When_Stmt: document := move_line(p, v.pos) document = cons(document, cons_with_nopl(text("when"), visit_expr(p, v.cond))) @@ -820,7 +820,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener document = cons_with_nopl(document, cons_with_nopl(text("else"), visit_stmt(p, v.else_stmt))) } return document - case Branch_Stmt: + case ^Branch_Stmt: document := move_line(p, v.pos) document = cons(document, text(v.tok.text)) @@ -846,7 +846,7 @@ should_align_comp_lit :: proc(p: ^Printer, comp_lit: ast.Comp_Lit) -> bool { } for expr in comp_lit.elems { - if _, ok := expr.derived.(ast.Field_Value); ok { + if _, ok := expr.derived.(^ast.Field_Value); ok { return true } } @@ -859,11 +859,11 @@ contains_comments_in_range :: proc(p: ^Printer, pos: tokenizer.Pos, end: tokeniz for i := p.latest_comment_index; i < len(p.comments); i += 1 { for c in p.comments[i].list { if pos.offset <= c.pos.offset && c.pos.offset <= end.offset { - return true; + return true } } } - return false; + return false } @(private) @@ -873,7 +873,7 @@ should_align_assignment_stmt :: proc(p: ^Printer, stmt: ast.Assign_Stmt) -> bool } for expr in stmt.rhs { - if _, ok := stmt.rhs[0].derived.(ast.Binary_Expr); ok { + if _, ok := stmt.rhs[0].derived.(^ast.Binary_Expr); ok { return true } } @@ -913,8 +913,8 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = set_source_position(p, expr.end) } - switch v in expr.derived { - case Inline_Asm_Expr: + #partial switch v in expr.derived { + case ^Inline_Asm_Expr: document := cons(text_token(p, v.tok), text("(")) document = cons(document, visit_exprs(p, v.param_types, {.Add_Comma})) document = cons(document, text(")")) @@ -926,11 +926,11 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, text(",")) document = cons(document, visit_expr(p, v.constraints_string)) document = cons(document, text("}")) - case Undef: + case ^Undef: return text("---") - case Auto_Cast: + case ^Auto_Cast: return cons_with_nopl(text_token(p, v.op), visit_expr(p, v.expr)) - case Ternary_If_Expr: + case ^Ternary_If_Expr: if v.op1.text == "if" { document := visit_expr(p, v.x) document = cons_with_nopl(document, text_token(p, v.op1)) @@ -946,31 +946,31 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons_with_nopl(document, visit_expr(p, v.y)) return document } - case Ternary_When_Expr: + case ^Ternary_When_Expr: document := visit_expr(p, v.cond) document = cons_with_nopl(document, text_token(p, v.op1)) document = cons_with_nopl(document, visit_expr(p, v.x)) document = cons_with_nopl(document, text_token(p, v.op2)) document = cons_with_nopl(document, visit_expr(p, v.y)) return document - case Or_Else_Expr: + case ^Or_Else_Expr: document := visit_expr(p, v.x) document = cons_with_opl(document, text_token(p, v.token)) document = cons_with_opl(document, visit_expr(p, v.y)) return document - case Or_Return_Expr: + case ^Or_Return_Expr: return cons_with_opl(visit_expr(p, v.expr), text_token(p, v.token)) - case Selector_Call_Expr: + case ^Selector_Call_Expr: document := visit_expr(p, v.call.expr) document = cons(document, text("(")) document = cons(document, visit_exprs(p, v.call.args, {.Add_Comma})) document = cons(document, text(")")) return document - case Ellipsis: + case ^Ellipsis: return cons(text(".."), visit_expr(p, v.expr)) - case Relative_Type: + case ^Relative_Type: return cons_with_opl(visit_expr(p, v.tag), visit_expr(p, v.type)) - case Slice_Expr: + case ^Slice_Expr: document := visit_expr(p, v.expr) document = cons(document, text("[")) document = cons(document, visit_expr(p, v.low)) @@ -981,32 +981,32 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = } document = cons(document, text("]")) return document - case Ident: + case ^Ident: if .Enforce_Poly_Names in options { return cons(text("$"), text(v.name)) } else { return text_position(p, v.name, v.pos) } - case Deref_Expr: + case ^Deref_Expr: return cons(visit_expr(p, v.expr), text_token(p, v.op)) - case Type_Cast: + case ^Type_Cast: document := cons(text_token(p, v.tok), text("(")) document = cons(document, visit_expr(p, v.type)) document = cons(document, text(")")) document = cons(document, visit_expr(p, v.expr)) return document - case Basic_Directive: + case ^Basic_Directive: return cons(text_token(p, v.tok), text_position(p, v.name, v.pos)) - case Distinct_Type: + case ^Distinct_Type: return cons_with_opl(text_position(p, "distinct", v.pos), visit_expr(p, v.type)) - case Dynamic_Array_Type: + case ^Dynamic_Array_Type: document := visit_expr(p, v.tag) document = cons(document, text("[")) document = cons(document, text("dynamic")) document = cons(document, text("]")) document = cons(document, visit_expr(p, v.elem)) return document - case Bit_Set_Type: + case ^Bit_Set_Type: document := text_position(p, "bit_set", v.pos) document = cons(document, text("[")) document = cons(document, visit_expr(p, v.elem)) @@ -1017,7 +1017,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, text("]")) return document - case Union_Type: + case ^Union_Type: document := text_position(p, "union", v.pos) document = cons(document, visit_poly_params(p, v.poly_params)) @@ -1034,13 +1034,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = } else { document = cons_with_opl(document, visit_begin_brace(p, v.pos, .Generic)) set_source_position(p, v.variants[0].pos) - document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.pos), visit_union_exprs(p, v, {.Add_Comma, .Trailing, .Enforce_Newline})))) + document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.pos), visit_union_exprs(p, v^, {.Add_Comma, .Trailing, .Enforce_Newline})))) set_source_position(p, v.end) document = cons(document, cons(newline(1), text_position(p, "}", v.end))) } return document - case Enum_Type: + case ^Enum_Type: document := text_position(p, "enum", v.pos) if v.base_type != nil { @@ -1053,7 +1053,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = } else { document = cons(document, cons(break_with_space(), visit_begin_brace(p, v.pos, .Generic))) set_source_position(p, v.fields[0].pos) - document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.open), visit_enum_exprs(p, v, {.Add_Comma, .Trailing, .Enforce_Newline})))) + document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.open), visit_enum_exprs(p, v^, {.Add_Comma, .Trailing, .Enforce_Newline})))) set_source_position(p, v.end) document = cons(document, cons(newline(1), text_position(p, "}", v.end))) @@ -1061,7 +1061,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = set_source_position(p, v.end) return document - case Struct_Type: + case ^Struct_Type: document := text_position(p, "struct", v.pos) document = cons(document, visit_poly_params(p, v.poly_params)) @@ -1097,7 +1097,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = set_source_position(p, v.end) return document - case Proc_Lit: + case ^Proc_Lit: document := empty() switch v.inlining { case .None: @@ -1118,38 +1118,38 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = } return document - case Proc_Type: - return group(visit_proc_type(p, v)) - case Basic_Lit: + case ^Proc_Type: + return group(visit_proc_type(p, v^)) + case ^Basic_Lit: return text_token(p, v.tok) - case Binary_Expr: - return visit_binary_expr(p, v) - case Implicit_Selector_Expr: + case ^Binary_Expr: + return visit_binary_expr(p, v^) + case ^Implicit_Selector_Expr: return cons(text("."), text_position(p, v.field.name, v.field.pos)) - case Call_Expr: + case ^Call_Expr: document := visit_expr(p, v.expr) document = cons(document, text("(")) document = cons(document, nest(p.indentation_count, cons(break_with(""), visit_call_exprs(p, v.args, v.ellipsis.kind == .Ellipsis)))) document = cons(document, cons(break_with(""), text(")"))) return group(document) - case Typeid_Type: + case ^Typeid_Type: document := text("typeid") if v.specialization != nil { document = cons(document, cons(text("/"), visit_expr(p, v.specialization))) } return document - case Selector_Expr: + case ^Selector_Expr: return cons(visit_expr(p, v.expr), cons(text_token(p, v.op), visit_expr(p, v.field))) - case Paren_Expr: + case ^Paren_Expr: return cons(text("("), cons(visit_expr(p, v.expr), text(")"))) - case Index_Expr: + case ^Index_Expr: document := visit_expr(p, v.expr) document = cons(document, text("[")) document = cons(document, fill_group(align(visit_expr(p, v.index)))) document = cons(document, text("]")) return document - case Proc_Group: + case ^Proc_Group: document := text_token(p, v.tok) if len(v.args) != 0 { @@ -1163,18 +1163,18 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, text("}")) } return document - case Comp_Lit: + case ^Comp_Lit: document := empty() if v.type != nil { document = cons(document, visit_expr(p, v.type)) } //If we call from the value declartion, we want it to be nicely newlined and aligned - if (should_align_comp_lit(p, v) || contains_comments_in_range(p, v.pos, v.end)) && (called_from == .Value_Decl || called_from == .Assignment_Stmt) && len(v.elems) != 0 { + if (should_align_comp_lit(p, v^) || contains_comments_in_range(p, v.pos, v.end)) && (called_from == .Value_Decl || called_from == .Assignment_Stmt) && len(v.elems) != 0 { document = cons_with_opl(document, visit_begin_brace(p, v.pos, .Generic)) set_source_position(p, v.open) - document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.elems[0].pos), visit_comp_lit_exprs(p, v, {.Add_Comma, .Trailing, .Enforce_Newline})))) + document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.elems[0].pos), visit_comp_lit_exprs(p, v^, {.Add_Comma, .Trailing, .Enforce_Newline})))) set_source_position(p, v.end) document = cons(document, cons(newline(1), text_position(p, "}", v.end))) @@ -1186,15 +1186,15 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = } return document - case Unary_Expr: + case ^Unary_Expr: return cons(text_token(p, v.op), visit_expr(p, v.expr)) - case Field_Value: + case ^Field_Value: document := cons_with_nopl(visit_expr(p, v.field), cons_with_nopl(text_position(p, "=", v.sep), visit_expr(p, v.value))) return document - case Type_Assertion: + case ^Type_Assertion: document := visit_expr(p, v.expr) - if unary, ok := v.type.derived.(Unary_Expr); ok && unary.op.text == "?" { + if unary, ok := v.type.derived.(^Unary_Expr); ok && unary.op.text == "?" { document = cons(document, cons(text("."), visit_expr(p, v.type))) } else { document = cons(document, text(".")) @@ -1203,13 +1203,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, text(")")) } return document - case Pointer_Type: + case ^Pointer_Type: return cons(text("^"), visit_expr(p, v.elem)) - case Multi_Pointer_Type: + case ^Multi_Pointer_Type: return cons(text("[^]"), visit_expr(p, v.elem)) - case Implicit: + case ^Implicit: return text_token(p, v.tok) - case Poly_Type: + case ^Poly_Type: document := cons(text("$"), visit_expr(p, v.type)) if v.specialization != nil { @@ -1217,22 +1217,22 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, visit_expr(p, v.specialization)) } return document - case Array_Type: + case ^Array_Type: document := visit_expr(p, v.tag) document = cons(document, text("[")) document = cons(document, visit_expr(p, v.len)) document = cons(document, text("]")) document = cons(document, visit_expr(p, v.elem)) return document - case Map_Type: + case ^Map_Type: document := cons(text("map"), text("[")) document = cons(document, visit_expr(p, v.key)) document = cons(document, text("]")) document = cons(document, visit_expr(p, v.value)) return document - case Helper_Type: + case ^Helper_Type: return visit_expr(p, v.type) - case Matrix_Type: + case ^Matrix_Type: document := text_position(p, "matrix", v.pos) document = cons(document, text("[")) document = cons(document, visit_expr(p, v.row_count)) @@ -1241,7 +1241,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type = document = cons(document, text("]")) document = cons(document, visit_expr(p, v.elem)) return document - case Matrix_Index_Expr: + case ^Matrix_Index_Expr: document := visit_expr(p, v.expr) document = cons(document, text("[")) document = cons(document, visit_expr(p, v.row_index)) @@ -1289,9 +1289,9 @@ visit_block_stmts :: proc(p: ^Printer, stmts: []^ast.Stmt, split := false) -> ^D document := empty() for stmt, i in stmts { - last_index := max(0, i-1); + last_index := max(0, i-1) if stmts[last_index].end.line == stmt.pos.line && i != 0 { - document = cons(document, break_with(";")); + document = cons(document, break_with(";")) } document = cons(document, group(visit_stmt(p, stmt, .Generic, false, true))) } @@ -1414,7 +1414,7 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type) -> ^Document { use_parens = true } else if len(proc_type.results.list) == 1 { for name in proc_type.results.list[0].names { - if ident, ok := name.derived.(ast.Ident); ok { + if ident, ok := name.derived.(^ast.Ident); ok { if ident.name != "_" { use_parens = true } @@ -1442,14 +1442,14 @@ visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) -> ^Document { lhs: ^Document rhs: ^Document - if v, ok := binary.left.derived.(ast.Binary_Expr); ok { - lhs = visit_binary_expr(p, v) + if v, ok := binary.left.derived.(^ast.Binary_Expr); ok { + lhs = visit_binary_expr(p, v^) } else { lhs = visit_expr(p, binary.left) } - if v, ok := binary.right.derived.(ast.Binary_Expr); ok { - rhs = visit_binary_expr(p, v) + if v, ok := binary.right.derived.(^ast.Binary_Expr); ok { + rhs = visit_binary_expr(p, v^) } else { rhs = visit_expr(p, binary.right) } @@ -1522,12 +1522,12 @@ visit_signature_list :: proc(p: ^Printer, list: ^ast.Field_List, remove_blank := for field, i in list.list { - flag := visit_field_flag(p, field.flags); + flag := visit_field_flag(p, field.flags) named := false for name in field.names { - if ident, ok := name.derived.(ast.Ident); ok { + if ident, ok := name.derived.(^ast.Ident); ok { //for some reason the parser uses _ to mean empty if ident.name != "_" || !remove_blank { named = true @@ -1578,14 +1578,14 @@ repeat_space :: proc(amount: int) -> ^Document { } get_node_length :: proc(node: ^ast.Node) -> int { - switch v in node.derived { - case ast.Ident: + #partial switch v in node.derived { + case ^ast.Ident: return len(v.name) - case ast.Basic_Lit: + case ^ast.Basic_Lit: return len(v.tok.text) - case ast.Implicit_Selector_Expr: + case ^ast.Implicit_Selector_Expr: return len(v.field.name) + 1 - case ast.Binary_Expr: + case ^ast.Binary_Expr: return 0 case: panic(fmt.aprintf("unhandled get_node_length case %v", node.derived)) @@ -1615,14 +1615,13 @@ get_possible_comp_lit_alignment :: proc(p: ^Printer, exprs: []^ast.Expr) -> int longest_name := 0 for expr in exprs { - - value, ok := expr.derived.(ast.Field_Value) + value, ok := expr.derived.(^ast.Field_Value) if !ok { return 0 } - if _, ok := value.value.derived.(ast.Comp_Lit); ok { + if _, ok := value.value.derived.(^ast.Comp_Lit); ok { return 0 } @@ -1636,8 +1635,7 @@ get_possible_enum_alignment :: proc(p: ^Printer, exprs: []^ast.Expr) -> int { longest_name := 0 for expr in exprs { - - value, ok := expr.derived.(ast.Field_Value) + value, ok := expr.derived.(^ast.Field_Value) if !ok { return 0 diff --git a/src/server/check.odin b/src/server/check.odin index ab6dfb2..8273084 100644 --- a/src/server/check.odin +++ b/src/server/check.odin @@ -18,49 +18,49 @@ import "core:text/scanner" import "shared:common" -when ODIN_OS == "windows" { +when ODIN_OS == .Windows { is_package :: proc(file: string, pkg: string) { } check :: proc(uri: common.Uri, writer: ^Writer, config: ^common.Config) { - data := make([]byte, mem.kilobytes(10), context.temp_allocator); + data := make([]byte, mem.kilobytes(10), context.temp_allocator) - buffer: []byte; - code: u32; - ok: bool; + buffer: []byte + code: u32 + ok: bool - collection_builder := strings.make_builder(context.temp_allocator); + collection_builder := strings.make_builder(context.temp_allocator) for k, v in common.config.collections { if k == "" || k == "core" || k == "vendor" { - continue; + continue } - strings.write_string(&collection_builder, fmt.aprintf("-collection:%v=%v ", k, v)); + strings.write_string(&collection_builder, fmt.aprintf("-collection:%v=%v ", k, v)) } - command: string; + command: string if config.odin_command != "" { - command = config.odin_command; + command = config.odin_command } else { - command = "odin"; + command = "odin" } if code, ok, buffer = common.run_executable(fmt.tprintf("%v check %s %s -no-entry-point %s", command, path.dir(uri.path, context.temp_allocator), strings.to_string(collection_builder), config.checker_args), &data); !ok { - log.errorf("Odin check failed with code %v for file %v", code, uri.path); - return; + log.errorf("Odin check failed with code %v for file %v", code, uri.path) + return } - s: scanner.Scanner; + s: scanner.Scanner - scanner.init(&s, string(buffer)); + scanner.init(&s, string(buffer)) - s.whitespace = {'\t', ' '}; + s.whitespace = {'\t', ' '} - current: rune; + current: rune ErrorSeperator :: struct { message: string, @@ -69,101 +69,101 @@ when ODIN_OS == "windows" { uri: string, } - error_seperators := make([dynamic]ErrorSeperator, context.temp_allocator); + error_seperators := make([dynamic]ErrorSeperator, context.temp_allocator) //find all the signatures string(digit:digit) loop: for scanner.peek(&s) != scanner.EOF { - error: ErrorSeperator; + error: ErrorSeperator - source_pos := s.src_pos; + source_pos := s.src_pos if source_pos == 1 { - source_pos = 0; + source_pos = 0 } for scanner.peek(&s) != '(' { - n := scanner.scan(&s); + n := scanner.scan(&s) if n == scanner.EOF { - break loop; + break loop } } - error.uri = string(buffer[source_pos:s.src_pos-1]); + error.uri = string(buffer[source_pos:s.src_pos-1]) - left_paren := scanner.scan(&s); + left_paren := scanner.scan(&s) if left_paren != '(' { - break loop; + break loop } - lhs_digit := scanner.scan(&s); + lhs_digit := scanner.scan(&s) if lhs_digit != scanner.Int { - break loop; + break loop } - line, column: int; - ok: bool; + line, column: int + ok: bool - line, ok = strconv.parse_int(scanner.token_text(&s)); + line, ok = strconv.parse_int(scanner.token_text(&s)) if !ok { - break loop; + break loop } - seperator := scanner.scan(&s); + seperator := scanner.scan(&s) if seperator != ':' { - break loop; + break loop } rhs_digit := scanner.scan(&s) if rhs_digit != scanner.Int { - break loop; + break loop } - column, ok = strconv.parse_int(scanner.token_text(&s)); + column, ok = strconv.parse_int(scanner.token_text(&s)) if !ok { - break loop; + break loop } - right_paren := scanner.scan(&s); + right_paren := scanner.scan(&s) if right_paren != ')' { - break loop; + break loop } - source_pos = s.src_pos; + source_pos = s.src_pos for scanner.peek(&s) != '\n' { - n := scanner.scan(&s); + n := scanner.scan(&s) if n == scanner.EOF { - break; + break } } if source_pos == s.src_pos { - continue; + continue } - error.message = string(buffer[source_pos:s.src_pos-1]); - error.column = column; - error.line = line; + error.message = string(buffer[source_pos:s.src_pos-1]) + error.column = column + error.line = line - append(&error_seperators, error); + append(&error_seperators, error) } - errors := make(map[string][dynamic]Diagnostic, 0, context.temp_allocator); + errors := make(map[string][dynamic]Diagnostic, 0, context.temp_allocator) for error in error_seperators { if error.uri not_in errors { - errors[error.uri] = make([dynamic]Diagnostic, context.temp_allocator); + errors[error.uri] = make([dynamic]Diagnostic, context.temp_allocator) } append(&errors[error.uri], Diagnostic { @@ -180,48 +180,48 @@ when ODIN_OS == "windows" { }, }, message = error.message, - }); + }) } - matches, err := filepath.glob(fmt.tprintf("%v/*.odin", path.dir(uri.path, context.temp_allocator))); + matches, err := filepath.glob(fmt.tprintf("%v/*.odin", path.dir(uri.path, context.temp_allocator))) if err == .None { for match in matches { - uri := common.create_uri(match, context.temp_allocator); + uri := common.create_uri(match, context.temp_allocator) params := NotificationPublishDiagnosticsParams { uri = uri.uri, diagnostics = {}, - }; + } notifaction := Notification { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = params, - }; + } if writer != nil { - send_notification(notifaction, writer); + send_notification(notifaction, writer) } } } for k, v in errors { - uri := common.create_uri(k, context.temp_allocator); + uri := common.create_uri(k, context.temp_allocator) params := NotificationPublishDiagnosticsParams { uri = uri.uri, diagnostics = v[:], - }; + } notifaction := Notification { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = params, - }; + } if writer != nil { - send_notification(notifaction, writer); + send_notification(notifaction, writer) } } } diff --git a/src/server/completion.odin b/src/server/completion.odin index 59df7a3..ae9d4e3 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -35,64 +35,64 @@ Completion_Type :: enum { } get_completion_list :: proc(document: ^common.Document, position: common.Position, completion_context: CompletionContext) -> (CompletionList, bool) { - using analysis; + using analysis - list: CompletionList; + list: CompletionList - position_context, ok := get_document_position_context(document, position, .Completion); + position_context, ok := get_document_position_context(document, position, .Completion) if !ok || position_context.abort_completion { - return list, true; + return list, true } if position_context.import_stmt == nil && strings.contains_any(completion_context.triggerCharacter, "/:\"") { - return list, true; + return list, true } - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) - ast_context.current_package = ast_context.document_package; - ast_context.value_decl = position_context.value_decl; + ast_context.current_package = ast_context.document_package + ast_context.value_decl = position_context.value_decl if position_context.function != nil { - get_locals(document.ast, position_context.function, &ast_context, &position_context); + get_locals(document.ast, position_context.function, &ast_context, &position_context) } - completion_type: Completion_Type = .Identifier; + completion_type: Completion_Type = .Identifier if position_context.comp_lit != nil && is_lhs_comp_lit(&position_context) { - completion_type = .Comp_Lit; + completion_type = .Comp_Lit } if position_context.selector != nil { - completion_type = .Selector; + completion_type = .Selector } if position_context.tag != nil { - completion_type = .Directive; + completion_type = .Directive } if position_context.implicit { - completion_type = .Implicit; + completion_type = .Implicit } if position_context.import_stmt != nil { - completion_type = .Package; + completion_type = .Package } if position_context.switch_type_stmt != nil && position_context.case_clause != nil { - if assign, ok := position_context.switch_type_stmt.tag.derived.(ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { + if assign, ok := position_context.switch_type_stmt.tag.derived.(^ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { - ast_context.use_globals = true; - ast_context.use_locals = true; + ast_context.use_globals = true + ast_context.use_locals = true if symbol, ok := resolve_type_expression(&ast_context, assign.rhs[0]); ok { if union_value, ok := symbol.value.(index.SymbolUnionValue); ok { - completion_type = .Switch_Type; + completion_type = .Switch_Type } } } @@ -100,22 +100,22 @@ get_completion_list :: proc(document: ^common.Document, position: common.Positio switch completion_type { case .Comp_Lit: - get_comp_lit_completion(&ast_context, &position_context, &list); + get_comp_lit_completion(&ast_context, &position_context, &list) case .Identifier: - get_identifier_completion(&ast_context, &position_context, &list); + get_identifier_completion(&ast_context, &position_context, &list) case .Implicit: - get_implicit_completion(&ast_context, &position_context, &list); + get_implicit_completion(&ast_context, &position_context, &list) case .Selector: - get_selector_completion(&ast_context, &position_context, &list); + get_selector_completion(&ast_context, &position_context, &list) case .Switch_Type: - get_type_switch_completion(&ast_context, &position_context, &list); + get_type_switch_completion(&ast_context, &position_context, &list) case .Directive: - get_directive_completion(&ast_context, &position_context, &list); + get_directive_completion(&ast_context, &position_context, &list) case .Package: - get_package_completion(&ast_context, &position_context, &list); + get_package_completion(&ast_context, &position_context, &list) } - return list, true; + return list, true } get_attribute_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { @@ -124,9 +124,9 @@ get_attribute_completion :: proc(ast_context: ^analysis.AstContext, position_con get_directive_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - list.isIncomplete = false; + list.isIncomplete = false - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) /* Right now just return all the possible completions, but later on I should give the context specific ones @@ -151,28 +151,28 @@ get_directive_completion :: proc(ast_context: ^analysis.AstContext, position_con "procedure", "load", "partial", - }; + } for elem in directive_list { item := CompletionItem { detail = elem, label = elem, kind = .Constant, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; + list.items = items[:] } get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) if position_context.parent_comp_lit.type == nil { - return; + return } if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { @@ -180,11 +180,11 @@ get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_cont #partial switch v in comp_symbol.value { case index.SymbolStructValue: for name, i in v.names { - ast_context.current_package = comp_symbol.pkg; + ast_context.current_package = comp_symbol.pkg if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok { if field_exists_in_comp_lit(position_context.comp_lit, name) { - continue; + continue } item := CompletionItem { @@ -192,126 +192,126 @@ get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v.%v: %v", comp_symbol.name, name, common.node_to_string(v.types[i])), documentation = resolved.doc, - }; + } - append(&items, item); + append(&items, item) } } } } } - list.items = items[:]; + list.items = items[:] } get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package - selector: index.Symbol; - ok: bool; + selector: index.Symbol + ok: bool - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true - selector, ok = resolve_type_expression(ast_context, position_context.selector); + selector, ok = resolve_type_expression(ast_context, position_context.selector) if !ok { - return; + return } //if (selector.type != .Variable && selector.type != .Package && selector.type != .Enum && selector.name != "") || (selector.type == .Variable && selector.type == .Enum) { if selector.type != .Variable && selector.type != .Package { - return; + return } 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 } - field: string; + field: string if position_context.field != nil { - switch v in position_context.field.derived { - case ast.Ident: - field = v.name; + #partial switch v in position_context.field.derived { + case ^ast.Ident: + field = v.name } } if s, ok := selector.value.(index.SymbolProcedureValue); ok { if len(s.return_types) == 1 { if selector, ok = resolve_type_expression(ast_context, s.return_types[0].type); !ok { - return; + return } } } #partial switch v in selector.value { case index.SymbolFixedArrayValue: - list.isIncomplete = true; + list.isIncomplete = true - containsColor := 1; - containsCoord := 1; + containsColor := 1 + containsCoord := 1 - expr_len := 0; + expr_len := 0 - if basic, ok := v.len.derived.(ast.Basic_Lit); ok { + if basic, ok := v.len.derived.(^ast.Basic_Lit); ok { if expr_len, ok = strconv.parse_int(basic.tok.text); !ok { - expr_len = 0; + expr_len = 0 } } if field != "" { for i := 0; i < len(field); i += 1 { - c := field[i]; + c := field[i] if _, ok := swizzle_color_components[c]; ok { - containsColor += 1; + containsColor += 1 } else if _, ok := swizzle_coord_components[c]; ok { - containsCoord += 1; + containsCoord += 1 } } } if containsColor == 1 && containsCoord == 1 { - save := expr_len; + save := expr_len for k in swizzle_color_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: %v", field, k, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } - expr_len = save; + expr_len = save for k in swizzle_coord_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: %v", field, k, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } @@ -319,90 +319,90 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont for k in swizzle_color_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: [%v]%v", field, k, containsColor, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } else if containsCoord > 1 { for k in swizzle_coord_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: [%v]%v", field, k, containsCoord, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } case index.SymbolUnionValue: - list.isIncomplete = false; + list.isIncomplete = false for type in v.types { if symbol, ok := resolve_type_expression(ast_context, type); ok { - base := path.base(symbol.pkg, false, context.temp_allocator); + base := path.base(symbol.pkg, false, context.temp_allocator) item := CompletionItem { kind = .EnumMember, detail = fmt.tprintf("%v", selector.name), documentation = symbol.doc, - }; + } if symbol.pkg == ast_context.document_package || base == "runtime" { - item.label = fmt.aprintf("(%v)", common.node_to_string(type)); + item.label = fmt.aprintf("(%v)", common.node_to_string(type)) } else { - item.label = fmt.aprintf("(%v.%v)", path.base(symbol.pkg, false, context.temp_allocator), common.node_to_string(type)); + item.label = fmt.aprintf("(%v.%v)", path.base(symbol.pkg, false, context.temp_allocator), common.node_to_string(type)) } - append(&items, item); + append(&items, item) } } case index.SymbolEnumValue: - list.isIncomplete = false; + list.isIncomplete = false for name in v.names { item := CompletionItem { label = name, kind = .EnumMember, detail = fmt.tprintf("%v.%v", selector.name, name), - }; + } - append(&items, item); + append(&items, item) } case index.SymbolStructValue: - list.isIncomplete = false; + list.isIncomplete = false for name, i in v.names { 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 } if symbol, ok := resolve_type_expression(ast_context, v.types[i]); ok { - if expr, ok := position_context.selector.derived.(ast.Selector_Expr); ok { + if expr, ok := position_context.selector.derived.(^ast.Selector_Expr); ok { if expr.op.text == "->" && symbol.type != .Function { - continue; + continue } } if position_context.arrow && symbol.type != .Function { - continue; + continue } item := CompletionItem { @@ -410,9 +410,9 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v.%v: %v", selector.name, name, type_to_string(ast_context, v.types[i])), documentation = symbol.doc, - }; + } - append(&items, item); + append(&items, item) } else { //just give some generic symbol with name. item := CompletionItem { @@ -420,75 +420,75 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v: %v", name, common.node_to_string(v.types[i])), documentation = symbol.doc, - }; + } - append(&items, item); + append(&items, item) } } case index.SymbolPackageValue: - list.isIncomplete = true; + list.isIncomplete = true if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok { for search in searched { - symbol := search.symbol; + symbol := search.symbol - resolve_unresolved_symbol(ast_context, &symbol); - build_procedure_symbol_signature(&symbol); + resolve_unresolved_symbol(ast_context, &symbol) + build_procedure_symbol_signature(&symbol) item := CompletionItem { label = symbol.name, kind = cast(CompletionItemKind)symbol.type, detail = concatenate_symbol_information(ast_context, symbol, true), documentation = symbol.doc, - }; + } if symbol.type == .Function { - item.insertText = fmt.tprintf("%v($0)", item.label); - item.insertTextFormat = .Snippet; - item.command.command = "editor.action.triggerParameterHints"; - item.deprecated = .Deprecated in symbol.flags; + item.insertText = fmt.tprintf("%v($0)", item.label) + item.insertTextFormat = .Snippet + item.command.command = "editor.action.triggerParameterHints" + item.deprecated = .Deprecated in symbol.flags } - append(&items, item); + append(&items, item) } } else { - log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg); - return; + log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg) + return } } - list.items = items[:]; + list.items = items[:] } get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = false; + list.isIncomplete = false - selector: index.Symbol; + selector: index.Symbol - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true 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 } //enum switch infer if position_context.switch_stmt != nil && position_context.case_clause != nil && position_context.switch_stmt.cond != nil { - used_enums := make(map[string]bool, 5, context.temp_allocator); + used_enums := make(map[string]bool, 5, context.temp_allocator) - if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok { + if block, ok := position_context.switch_stmt.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - if case_clause, ok := stmt.derived.(ast.Case_Clause); ok { + if case_clause, ok := stmt.derived.(^ast.Case_Clause); ok { for name in case_clause.list { - if implicit, ok := name.derived.(ast.Implicit_Selector_Expr); ok { - used_enums[implicit.field.name] = true; + if implicit, ok := name.derived.(^ast.Implicit_Selector_Expr); ok { + used_enums[implicit.field.name] = true } } } @@ -498,20 +498,20 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont if enum_value, ok := unwrap_enum(ast_context, position_context.switch_stmt.cond); ok { for name in enum_value.names { if name in used_enums { - continue; + continue } item := CompletionItem { label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } @@ -527,13 +527,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -549,13 +549,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -563,13 +563,17 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont //infer bitset and enums based on the identifier comp_lit, i.e. a := My_Struct { my_ident = . } if position_context.comp_lit != nil { if position_context.parent_comp_lit.type == nil { - return; + return } - field_name: string; + field_name: string if position_context.field_value != nil { - field_name = position_context.field_value.field.derived.(ast.Ident).name; + if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { + field_name = field.name + } else { + return + } } if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { @@ -577,27 +581,27 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont if s, ok := comp_symbol.value.(index.SymbolStructValue); ok { //We can either have the final - elem_index := -1; + elem_index := -1 for elem, i in comp_lit.elems { if position_in_node(elem, position_context.position) { - elem_index = i; + elem_index = i } } - type: ^ast.Expr; + type: ^ast.Expr for name, i in s.names { if name != field_name { - continue; + continue } - type = s.types[i]; - break; + type = s.types[i] + break } if type == nil && len(s.types) > elem_index { - type = s.types[elem_index]; + type = s.types[elem_index] } if enum_value, ok := unwrap_enum(ast_context, type); ok { @@ -606,13 +610,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = enum_name, kind = .EnumMember, detail = enum_name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } else if bitset_symbol, ok := resolve_type_expression(ast_context, type); ok { if value, ok := unwrap_bitset(ast_context, bitset_symbol); ok { for name in value.names { @@ -621,12 +625,12 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -635,15 +639,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont } if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") { - context_node: ^ast.Expr; - enum_node: ^ast.Expr; + context_node: ^ast.Expr + enum_node: ^ast.Expr if position_in_node(position_context.binary.right, position_context.position) { - context_node = position_context.binary.right; - enum_node = position_context.binary.left; + context_node = position_context.binary.right + enum_node = position_context.binary.left } else if position_in_node(position_context.binary.left, position_context.position) { - context_node = position_context.binary.left; - enum_node = position_context.binary.right; + context_node = position_context.binary.left + enum_node = position_context.binary.right } if context_node != nil && enum_node != nil { @@ -653,34 +657,34 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil { - rhs_index: int; + rhs_index: int for elem in position_context.assign.rhs { if position_in_node(elem, position_context.position) { - break; + break } else { //procedures are the only types that can return more than one value if symbol, ok := resolve_type_expression(ast_context, elem); ok { if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok { if procedure.return_types == nil { - return; + return } - rhs_index += len(procedure.return_types); + rhs_index += len(procedure.return_types) } else { - rhs_index += 1; + rhs_index += 1 } } } @@ -693,37 +697,37 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.returns != nil && position_context.function != nil { - return_index: int; + return_index: int if position_context.returns.results == nil { - return; + return } for result, i in position_context.returns.results { if position_in_node(result, position_context.position) { - return_index = i; - break; + return_index = i + break } } if position_context.function.type == nil { - return; + return } if position_context.function.type.results == nil { - return; + return } if len(position_context.function.type.results.list) > return_index { @@ -733,24 +737,24 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.call != nil { - if call, ok := position_context.call.derived.(ast.Call_Expr); ok { - parameter_index, parameter_ok := find_position_in_call_param(ast_context, call); + if call, ok := position_context.call.derived.(^ast.Call_Expr); ok { + parameter_index, parameter_ok := find_position_in_call_param(ast_context, call^) if symbol, ok := resolve_type_expression(ast_context, call.expr); ok && parameter_ok { if proc_value, ok := symbol.value.(index.SymbolProcedureValue); ok { if len(proc_value.arg_types) <= parameter_index { - return; + return } if enum_value, ok := unwrap_enum(ast_context, proc_value.arg_types[parameter_index].type); ok { @@ -759,13 +763,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -774,11 +778,11 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont } get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = true; + list.isIncomplete = true CombinedResult :: struct { score: f32, @@ -789,51 +793,51 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co pkg: string, signature: string, flags: index.SymbolFlags, - }; + } combined_sort_interface :: proc(s: ^[dynamic]CombinedResult) -> sort.Interface { return sort.Interface { collection = rawptr(s), len = proc(it: sort.Interface) -> int { - s := (^[dynamic]CombinedResult)(it.collection); - return len(s^); + s := (^[dynamic]CombinedResult)(it.collection) + return len(s^) }, less = proc(it: sort.Interface, i, j: int) -> bool { - s := (^[dynamic]CombinedResult)(it.collection); - return s[i].score > s[j].score; + s := (^[dynamic]CombinedResult)(it.collection) + return s[i].score > s[j].score }, swap = proc(it: sort.Interface, i, j: int) { - s := (^[dynamic]CombinedResult)(it.collection); - s[i], s[j] = s[j], s[i]; + s := (^[dynamic]CombinedResult)(it.collection) + s[i], s[j] = s[j], s[i] }, - }; - }; + } + } - combined := make([dynamic]CombinedResult); + combined := make([dynamic]CombinedResult) - lookup := ""; + lookup := "" if position_context.identifier != nil { - if ident, ok := position_context.identifier.derived.(ast.Ident); ok { - lookup = ident.name; + if ident, ok := position_context.identifier.derived.(^ast.Ident); ok { + lookup = ident.name } } - pkgs := make([dynamic]string, context.temp_allocator); + pkgs := make([dynamic]string, context.temp_allocator) - usings := get_using_packages(ast_context); + usings := get_using_packages(ast_context) for u in usings { - append(&pkgs, u); + append(&pkgs, u) } - append(&pkgs, ast_context.document_package); + append(&pkgs, ast_context.document_package) if results, ok := index.fuzzy_search(lookup, pkgs[:]); ok { for r in results { - r := r; - resolve_unresolved_symbol(ast_context, &r.symbol); - build_procedure_symbol_signature(&r.symbol); + r := r + resolve_unresolved_symbol(ast_context, &r.symbol) + build_procedure_symbol_signature(&r.symbol) if r.symbol.uri != ast_context.uri { append(&combined, CombinedResult { score = r.score, @@ -843,36 +847,36 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = r.symbol.flags, signature = r.symbol.signature, pkg = r.symbol.pkg, - }); + }) } } } - matcher := common.make_fuzzy_matcher(lookup); + matcher := common.make_fuzzy_matcher(lookup) global: for k, v in ast_context.globals { if position_context.global_lhs_stmt { - break; + break } //combined is sorted and should do binary search instead. for result in combined { if result.name == k { - continue global; + continue global } } - 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 - ident := index.new_type(ast.Ident, v.expr.pos, v.expr.end, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, v.expr.pos, v.expr.end, context.temp_allocator) + ident.name = k if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.signature = get_signature(ast_context, ident^, symbol); + symbol.signature = get_signature(ast_context, ident^, symbol) - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { append(&combined, CombinedResult { @@ -883,7 +887,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, pkg = symbol.pkg, signature = symbol.signature, - }); + }) } } } @@ -891,22 +895,22 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co for _, local in ast_context.locals { for k, v in local { if position_context.global_lhs_stmt { - break; + break } - local_offset := get_local_offset(ast_context, position_context.position, k); + local_offset := get_local_offset(ast_context, position_context.position, k) - 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 - ident := index.new_type(ast.Ident, {offset = local_offset}, {offset = local_offset}, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, {offset = local_offset}, {offset = local_offset}, context.temp_allocator) + ident.name = k if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.signature = get_signature(ast_context, ident^, symbol); + symbol.signature = get_signature(ast_context, ident^, symbol) - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { append(&combined, CombinedResult { @@ -917,7 +921,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, pkg = symbol.pkg, signature = symbol.signature, - }); + }) } } } @@ -925,13 +929,13 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co for pkg in ast_context.imports { if position_context.global_lhs_stmt { - break; + break } symbol := index.Symbol { name = pkg.base, type = .Package, - }; + } if score, ok := common.fuzzy_match(matcher, symbol.name); ok == 1 { append(&combined, CombinedResult { @@ -942,7 +946,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } @@ -950,7 +954,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co symbol := index.Symbol { name = keyword, type = .Keyword, - }; + } if score, ok := common.fuzzy_match(matcher, keyword); ok == 1 { append(&combined, CombinedResult { @@ -961,7 +965,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } @@ -969,7 +973,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co symbol := index.Symbol { name = keyword, type = .Keyword, - }; + } if score, ok := common.fuzzy_match(matcher, keyword); ok == 1 { append(&combined, CombinedResult { @@ -980,29 +984,29 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } if common.config.enable_snippets { for k, v in snippets { if score, ok := common.fuzzy_match(matcher, k); ok == 1 { - append(&combined, CombinedResult {score = score * 1.1, snippet = v, name = k}); + append(&combined, CombinedResult {score = score * 1.1, snippet = v, name = k}) } } } - sort.sort(combined_sort_interface(&combined)); + sort.sort(combined_sort_interface(&combined)) //hard code for now - top_results := combined[0:(min(50, len(combined)))]; + top_results := combined[0:(min(50, len(combined)))] for result in top_results { - result := result; + result := result //Skip procedures when the position is in proc decl if position_in_proc_decl(position_context) && result.type == .Function && common.config.enable_procedure_context { - continue; + continue } if result.snippet.insert != "" { @@ -1012,72 +1016,72 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co kind = .Snippet, detail = result.snippet.detail, insertTextFormat = .Snippet, - }; + } - edits := make([dynamic]TextEdit, context.temp_allocator); + edits := make([dynamic]TextEdit, context.temp_allocator) for pkg in result.snippet.packages { - edit, ok := get_core_insert_package_if_non_existent(ast_context, pkg); + edit, ok := get_core_insert_package_if_non_existent(ast_context, pkg) if ok { - append(&edits, edit); + append(&edits, edit) } } - item.additionalTextEdits = edits[:]; + item.additionalTextEdits = edits[:] - append(&items, item); + append(&items, item) } else { item := CompletionItem { label = result.name, documentation = result.doc, - }; + } - item.kind = cast(CompletionItemKind)result.type; + item.kind = cast(CompletionItemKind)result.type if result.type == .Function { - item.insertText = fmt.tprintf("%v($0)", item.label); - item.insertTextFormat = .Snippet; - item.deprecated = .Deprecated in result.flags; - item.command.command = "editor.action.triggerParameterHints"; + item.insertText = fmt.tprintf("%v($0)", item.label) + item.insertTextFormat = .Snippet + item.deprecated = .Deprecated in result.flags + item.command.command = "editor.action.triggerParameterHints" } - item.detail = concatenate_symbol_information(ast_context, result.pkg, result.name, result.signature, result.type, true); + item.detail = concatenate_symbol_information(ast_context, result.pkg, result.name, result.signature, result.type, true) - append(&items, item); + append(&items, item) } } - list.items = items[:]; + list.items = items[:] } get_package_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = false; + list.isIncomplete = false - fullpath_length := len(position_context.import_stmt.fullpath); + fullpath_length := len(position_context.import_stmt.fullpath) if fullpath_length <= 1 { - return; + return } - without_quotes := position_context.import_stmt.fullpath[1:fullpath_length-1]; - absolute_path := without_quotes; - colon_index := strings.index(without_quotes, ":"); + without_quotes := position_context.import_stmt.fullpath[1:fullpath_length-1] + absolute_path := without_quotes + colon_index := strings.index(without_quotes, ":") if colon_index >= 0 { - c := without_quotes[0:colon_index]; + c := without_quotes[0:colon_index] if colon_index+1 < len(without_quotes) { - absolute_path = filepath.join(elems = {common.config.collections[c], filepath.dir(without_quotes[colon_index+1:], context.temp_allocator)}, allocator = context.temp_allocator); + absolute_path = filepath.join(elems = {common.config.collections[c], filepath.dir(without_quotes[colon_index+1:], context.temp_allocator)}, allocator = context.temp_allocator) } else { - absolute_path = common.config.collections[c]; + absolute_path = common.config.collections[c] } } else { - import_file_dir := filepath.dir(position_context.import_stmt.pos.file, context.temp_allocator); - import_dir := filepath.dir(without_quotes, context.temp_allocator); - absolute_path = filepath.join(elems = {import_file_dir, import_dir}, allocator = context.temp_allocator); + import_file_dir := filepath.dir(position_context.import_stmt.pos.file, context.temp_allocator) + import_dir := filepath.dir(without_quotes, context.temp_allocator) + absolute_path = filepath.join(elems = {import_file_dir, import_dir}, allocator = context.temp_allocator) } if !strings.contains(position_context.import_stmt.fullpath, "/") && !strings.contains(position_context.import_stmt.fullpath, ":") { @@ -1087,9 +1091,9 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte detail = "collection", label = key, kind = .Module, - }; + } - append(&items, item); + append(&items, item) } } @@ -1099,103 +1103,103 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte detail = pkg, label = filepath.base(pkg), kind = .Folder, - }; + } if item.label[0] == '.' { - continue; + continue } - append(&items, item); + append(&items, item) } - list.items = items[:]; + list.items = items[:] } search_for_packages :: proc(fullpath: string) -> [] string { - packages := make([dynamic]string, context.temp_allocator); + packages := make([dynamic]string, context.temp_allocator) - fh, err := os.open(fullpath); + fh, err := os.open(fullpath) if err != 0 { - return {}; + return {} } if files, err := os.read_dir(fh, 0, context.temp_allocator); err == 0 { for file in files { if file.is_dir { - append(&packages, file.fullpath); + append(&packages, file.fullpath) } } } - return packages[:]; + return packages[:] } get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); - list.isIncomplete = false; + items := make([dynamic]CompletionItem, context.temp_allocator) + list.isIncomplete = false - used_unions := make(map[string]bool, 5, context.temp_allocator); + used_unions := make(map[string]bool, 5, context.temp_allocator) - if block, ok := position_context.switch_type_stmt.body.derived.(ast.Block_Stmt); ok { + if block, ok := position_context.switch_type_stmt.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - if case_clause, ok := stmt.derived.(ast.Case_Clause); ok { + if case_clause, ok := stmt.derived.(^ast.Case_Clause); ok { for name in case_clause.list { - if ident, ok := name.derived.(ast.Ident); ok { - used_unions[ident.name] = true; + if ident, ok := name.derived.(^ast.Ident); ok { + used_unions[ident.name] = true } } } } } - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true - if assign, ok := position_context.switch_type_stmt.tag.derived.(ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { + if assign, ok := position_context.switch_type_stmt.tag.derived.(^ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { if union_value, ok := unwrap_union(ast_context, assign.rhs[0]); ok { for type, i in union_value.types { - name := common.node_to_string(type); + name := common.node_to_string(type) if name in used_unions { - continue; + continue } if symbol, ok := resolve_type_expression(ast_context, union_value.types[i]); ok { item := CompletionItem { kind = .EnumMember, - }; + } if symbol.pkg == ast_context.document_package { - item.label = fmt.aprintf("%v", common.node_to_string(union_value.types[i])); - item.detail = item.label; + item.label = fmt.aprintf("%v", common.node_to_string(union_value.types[i])) + item.detail = item.label } else { - item.label = fmt.aprintf("%v.%v", path.base(symbol.pkg, false, context.temp_allocator), name); - item.detail = item.label; + item.label = fmt.aprintf("%v.%v", path.base(symbol.pkg, false, context.temp_allocator), name) + item.detail = item.label } - append(&items, item); + append(&items, item) } } } } - list.items = items[:]; + list.items = items[:] } get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContext, pkg: string) -> (TextEdit, bool) { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) for imp in ast_context.imports { if imp.base == pkg { - return {}, false; + return {}, false } } - strings.write_string(&builder, fmt.tprintf("import \"core:%v\"", pkg)); + strings.write_string(&builder, fmt.tprintf("import \"core:%v\"", pkg)) return { newText = strings.to_string(builder), @@ -1209,7 +1213,7 @@ get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContex character = 0, }, }, - }, true; + }, true } bitset_operators: map[string]bool = { @@ -1219,7 +1223,7 @@ bitset_operators: map[string]bool = { "<" = true, ">" = true, "==" = true, -}; +} bitset_assignment_operators: map[string]bool = { "|=" = true, @@ -1228,14 +1232,14 @@ bitset_assignment_operators: map[string]bool = { "<=" = true, ">=" = true, "=" = true, -}; +} is_bitset_binary_operator :: proc(op: string) -> bool { - return op in bitset_operators; + return op in bitset_operators } is_bitset_assignment_operator :: proc(op: string) -> bool { - return op in bitset_assignment_operators; + return op in bitset_assignment_operators } language_keywords: []string = { @@ -1280,14 +1284,14 @@ language_keywords: []string = { "using", "or_return", "or_else", -}; +} swizzle_color_components: map[u8]bool = { 'r' = true, 'g' = true, 'b' = true, 'a' = true, -}; +} swizzle_coord_components: map[u8]bool = { 'x' = true, diff --git a/src/server/definition.odin b/src/server/definition.odin index 116fbd9..cfa2c49 100644 --- a/src/server/definition.odin +++ b/src/server/definition.odin @@ -20,123 +20,120 @@ import "shared:index" import "shared:analysis" get_definition_location :: proc(document: ^common.Document, position: common.Position) -> ([]common.Location, bool) { - using analysis; + using analysis - locations := make([dynamic]common.Location, context.temp_allocator); + locations := make([dynamic]common.Location, context.temp_allocator) - location: common.Location; + location: common.Location - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - uri: string; + uri: string - position_context, ok := get_document_position_context(document, position, .Definition); + position_context, ok := get_document_position_context(document, position, .Definition) if !ok { - log.warn("Failed to get position context"); - return {}, false; + log.warn("Failed to get position context") + return {}, false } - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) if position_context.function != nil { - get_locals(document.ast, position_context.function, &ast_context, &position_context); + get_locals(document.ast, position_context.function, &ast_context, &position_context) } if position_context.selector != nil { - //if the base selector is the client wants to go to. - if base, ok := position_context.selector.derived.(ast.Ident); ok && position_context.identifier != nil { - - ident := position_context.identifier.derived.(ast.Ident); + if base, ok := position_context.selector.derived.(^ast.Ident); ok && position_context.identifier != nil { + ident := position_context.identifier.derived.(^ast.Ident) if ident.name == base.name { - - if resolved, ok := resolve_location_identifier(&ast_context, ident); ok { - location.range = resolved.range; + if resolved, ok := resolve_location_identifier(&ast_context, ident^); ok { + location.range = resolved.range if resolved.uri == "" { - location.uri = document.uri.uri; + location.uri = document.uri.uri } else { - location.uri = resolved.uri; + location.uri = resolved.uri } - append(&locations, location); + append(&locations, location) - return locations[:], true; + return locations[:], true } else { - return {}, false; + return {}, false } } } //otherwise it's the field the client wants to go to. - selector: index.Symbol; + selector: index.Symbol - 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 - selector, ok = resolve_type_expression(&ast_context, position_context.selector); + selector, ok = resolve_type_expression(&ast_context, position_context.selector) if !ok { - return {}, false; + return {}, false } - field: string; + field: string if position_context.field != nil { - switch v in position_context.field.derived { - case ast.Ident: - field = v.name; + #partial switch v in position_context.field.derived { + case ^ast.Ident: + field = v.name } } - uri = selector.uri; + uri = selector.uri #partial switch v in selector.value { case index.SymbolEnumValue: - location.range = selector.range; + location.range = selector.range case index.SymbolStructValue: for name, i in v.names { if strings.compare(name, field) == 0 { - location.range = common.get_token_range(v.types[i]^, document.ast.src); + location.range = common.get_token_range(v.types[i]^, document.ast.src) } } case index.SymbolPackageValue: if symbol, ok := index.lookup(field, selector.pkg); ok { - location.range = symbol.range; - uri = symbol.uri; + location.range = symbol.range + uri = symbol.uri } else { - return {}, false; + return {}, false } } if !ok { - return {}, false; + return {}, false } } else if position_context.identifier != nil { - if resolved, ok := resolve_location_identifier(&ast_context, position_context.identifier.derived.(ast.Ident)); ok { - location.range = resolved.range; - uri = resolved.uri; + if resolved, ok := resolve_location_identifier(&ast_context, position_context.identifier.derived.(^ast.Ident)^); ok { + location.range = resolved.range + uri = resolved.uri } else { - return {}, false; + return {}, false } } else { - return {}, false; + return {}, false } //if the symbol is generated by the ast we don't set the uri. if uri == "" { - location.uri = document.uri.uri; + location.uri = document.uri.uri } else { - location.uri = uri; + location.uri = uri } append(&locations, location) - return locations[:], true; + return locations[:], true } \ No newline at end of file diff --git a/src/server/document_links.odin b/src/server/document_links.odin index 9295c33..ec1cecb 100644 --- a/src/server/document_links.odin +++ b/src/server/document_links.odin @@ -20,23 +20,23 @@ import "shared:index" import "shared:analysis" get_document_links :: proc(document: ^common.Document) -> ([]DocumentLink, bool) { - using analysis; + using analysis - links := make([dynamic]DocumentLink, 0, context.temp_allocator); + links := make([dynamic]DocumentLink, 0, context.temp_allocator) for imp in document.ast.imports { if len(imp.relpath.text) <= 1 { - continue; + continue } - e := strings.split(imp.relpath.text[1:len(imp.relpath.text)-1], ":", context.temp_allocator); + e := strings.split(imp.relpath.text[1:len(imp.relpath.text)-1], ":", context.temp_allocator) if len(e) != 2 { - continue; + continue } if e[0] != "core" { - continue; + continue } //Temporarly assuming non unicode @@ -53,16 +53,16 @@ get_document_links :: proc(document: ^common.Document) -> ([]DocumentLink, bool) }, } - range := common.get_token_range(node, string(document.text)); + range := common.get_token_range(node, string(document.text)) link := DocumentLink { range = range, target = fmt.tprintf("https://pkg.odin-lang.org/%v/%v", e[0], e[1]), tooltip = "Documentation", - }; + } - append(&links, link); + append(&links, link) } - return links[:], true; + return links[:], true } diff --git a/src/server/document_symbols.odin b/src/server/document_symbols.odin index 7105465..667b94a 100644 --- a/src/server/document_symbols.odin +++ b/src/server/document_symbols.odin @@ -21,22 +21,22 @@ import "shared:analysis" get_document_symbols :: proc(document: ^common.Document) -> []DocumentSymbol { - using analysis; + using analysis - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) - symbols := make([dynamic]DocumentSymbol, context.temp_allocator); + symbols := make([dynamic]DocumentSymbol, context.temp_allocator) - package_symbol: DocumentSymbol; + package_symbol: DocumentSymbol if len(document.ast.decls) == 0 { - return {}; + return {} } - package_symbol.kind = .Package; - package_symbol.name = path.base(document.package_name, false, context.temp_allocator); + package_symbol.kind = .Package + package_symbol.name = path.base(document.package_name, false, context.temp_allocator) package_symbol.range = { start = { line = document.ast.decls[0].pos.line, @@ -44,35 +44,35 @@ get_document_symbols :: proc(document: ^common.Document) -> []DocumentSymbol { end = { line = document.ast.decls[len(document.ast.decls) - 1].end.line, }, - }; - package_symbol.selectionRange = package_symbol.range; + } + package_symbol.selectionRange = package_symbol.range - children_symbols := make([dynamic]DocumentSymbol, context.temp_allocator); + children_symbols := make([dynamic]DocumentSymbol, context.temp_allocator) for k, global in ast_context.globals { - symbol: DocumentSymbol; - symbol.range = common.get_token_range(global.expr, ast_context.file.src); - symbol.selectionRange = symbol.range; - symbol.name = k; - - switch v in global.expr.derived { - case ast.Struct_Type: - symbol.kind = .Struct; - case ast.Proc_Lit, ast.Proc_Group: - symbol.kind = .Function; - case ast.Enum_Type, ast.Union_Type: - symbol.kind = .Enum; + symbol: DocumentSymbol + symbol.range = common.get_token_range(global.expr, ast_context.file.src) + symbol.selectionRange = symbol.range + symbol.name = k + + #partial switch v in global.expr.derived { + case ^ast.Struct_Type: + symbol.kind = .Struct + case ^ast.Proc_Lit, ^ast.Proc_Group: + symbol.kind = .Function + case ^ast.Enum_Type, ^ast.Union_Type: + symbol.kind = .Enum case: - symbol.kind = .Variable; + symbol.kind = .Variable } - append(&children_symbols, symbol); + append(&children_symbols, symbol) } - package_symbol.children = children_symbols[:]; + package_symbol.children = children_symbols[:] - append(&symbols, package_symbol); + append(&symbols, package_symbol) - return symbols[:]; + return symbols[:] } diff --git a/src/server/documents.odin b/src/server/documents.odin index 07800e0..3bb4a01 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -27,58 +27,58 @@ DocumentStorage :: struct { free_allocators: [dynamic]^common.Scratch_Allocator, } -document_storage: DocumentStorage; +document_storage: DocumentStorage document_storage_shutdown :: proc() { for k, v in document_storage.documents { - delete(k); + delete(k) } for alloc in document_storage.free_allocators { - common.scratch_allocator_destroy(alloc); - free(alloc); + common.scratch_allocator_destroy(alloc) + free(alloc) } - delete(document_storage.free_allocators); - delete(document_storage.documents); + delete(document_storage.free_allocators) + delete(document_storage.documents) } document_get_allocator :: proc() -> ^common.Scratch_Allocator { if len(document_storage.free_allocators) > 0 { - return pop(&document_storage.free_allocators); + return pop(&document_storage.free_allocators) } else { - allocator := new(common.Scratch_Allocator); - common.scratch_allocator_init(allocator, mem.megabytes(1)); - return allocator; + allocator := new(common.Scratch_Allocator) + common.scratch_allocator_init(allocator, mem.megabytes(1)) + return allocator } } document_free_allocator :: proc(allocator: ^common.Scratch_Allocator) { - append(&document_storage.free_allocators, allocator); + append(&document_storage.free_allocators, allocator) } document_get :: proc(uri_string: string) -> ^common.Document { - uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator) if !parsed_ok { - return nil; + return nil } - document := &document_storage.documents[uri.path]; + document := &document_storage.documents[uri.path] if document == nil { - log.errorf("Failed to get document %v", uri.path); - return nil; + log.errorf("Failed to get document %v", uri.path) + return nil } - intrinsics.atomic_add(&document.operating_on, 1); + intrinsics.atomic_add(&document.operating_on, 1) - return document; + return document } document_release :: proc(document: ^common.Document) { if document != nil { - intrinsics.atomic_sub(&document.operating_on, 1); + intrinsics.atomic_sub(&document.operating_on, 1) } } @@ -87,27 +87,27 @@ document_release :: proc(document: ^common.Document) { */ document_open :: proc(uri_string: string, text: string, config: ^common.Config, writer: ^Writer) -> common.Error { - uri, parsed_ok := common.parse_uri(uri_string, context.allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.allocator) if !parsed_ok { - log.error("Failed to parse uri"); - return .ParseError; + log.error("Failed to parse uri") + return .ParseError } if document := &document_storage.documents[uri.path]; document != nil { if document.client_owned { - log.errorf("Client called open on an already open document: %v ", document.uri.path); - return .InvalidRequest; + log.errorf("Client called open on an already open document: %v ", document.uri.path) + return .InvalidRequest } - document.uri = uri; - document.client_owned = true; - document.text = transmute([]u8)text; - document.used_text = len(document.text); - document.allocator = document_get_allocator(); + document.uri = uri + document.client_owned = true + document.text = transmute([]u8)text + document.used_text = len(document.text) + document.allocator = document_get_allocator() if err := document_refresh(document, config, writer); err != .None { - return err; + return err } } else { document := common.Document { @@ -116,142 +116,142 @@ document_open :: proc(uri_string: string, text: string, config: ^common.Config, client_owned = true, used_text = len(text), allocator = document_get_allocator(), - }; + } if err := document_refresh(&document, config, writer); err != .None { - return err; + return err } - document_storage.documents[strings.clone(uri.path)] = document; + document_storage.documents[strings.clone(uri.path)] = document } - delete(uri_string); + delete(uri_string) - return .None; + return .None } /* Function that applies changes to the given document through incremental syncronization */ document_apply_changes :: proc(uri_string: string, changes: [dynamic]TextDocumentContentChangeEvent, config: ^common.Config, writer: ^Writer) -> common.Error { - uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator) if !parsed_ok { - return .ParseError; + return .ParseError } - document := &document_storage.documents[uri.path]; + document := &document_storage.documents[uri.path] if !document.client_owned { - log.errorf("Client called change on an document not opened: %v ", document.uri.path); - return .InvalidRequest; + log.errorf("Client called change on an document not opened: %v ", document.uri.path) + return .InvalidRequest } for change in changes { //for some reason sublime doesn't seem to care even if i tell it to do incremental sync if range, ok := change.range.(common.Range); ok { - absolute_range, ok := common.get_absolute_range(range, document.text[:document.used_text]); + absolute_range, ok := common.get_absolute_range(range, document.text[:document.used_text]) if !ok { - return .ParseError; + return .ParseError } //lower bound is before the change - lower := document.text[:absolute_range.start]; + lower := document.text[:absolute_range.start] //new change between lower and upper - middle := change.text; + middle := change.text //upper bound is after the change - upper := document.text[absolute_range.end:document.used_text]; + upper := document.text[absolute_range.end:document.used_text] //total new size needed - document.used_text = len(lower) + len(change.text) + len(upper); + document.used_text = len(lower) + len(change.text) + len(upper) //Reduce the amount of allocation by allocating more memory than needed if document.used_text > len(document.text) { - new_text := make([]u8, document.used_text * 2); + new_text := make([]u8, document.used_text * 2) //join the 3 splices into the text - copy(new_text, lower); - copy(new_text[len(lower):], middle); - copy(new_text[len(lower) + len(middle):], upper); + copy(new_text, lower) + copy(new_text[len(lower):], middle) + copy(new_text[len(lower) + len(middle):], upper) - delete(document.text); + delete(document.text) - document.text = new_text; + document.text = new_text } else { //order matters here, we need to make sure we swap the data already in the text before the middle - copy(document.text, lower); - copy(document.text[len(lower) + len(middle):], upper); - copy(document.text[len(lower):], middle); + copy(document.text, lower) + copy(document.text[len(lower) + len(middle):], upper) + copy(document.text[len(lower):], middle) } } else { - document.used_text = len(change.text); + document.used_text = len(change.text) if document.used_text > len(document.text) { - new_text := make([]u8, document.used_text * 2); - copy(new_text, change.text); - delete(document.text); - document.text = new_text; + new_text := make([]u8, document.used_text * 2) + copy(new_text, change.text) + delete(document.text) + document.text = new_text } else { - copy(document.text, change.text); + copy(document.text, change.text) } } } //log.info(string(document.text[:document.used_text])); - return document_refresh(document, config, writer); + return document_refresh(document, config, writer) } document_close :: proc(uri_string: string) -> common.Error { - log.infof("document_close: %v", uri_string); + log.infof("document_close: %v", uri_string) - uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator) if !parsed_ok { - return .ParseError; + return .ParseError } - document := &document_storage.documents[uri.path]; + document := &document_storage.documents[uri.path] if document == nil || !document.client_owned { - log.errorf("Client called close on a document that was never opened: %v ", document.uri.path); - return .InvalidRequest; + log.errorf("Client called close on a document that was never opened: %v ", document.uri.path) + return .InvalidRequest } - free_all(common.scratch_allocator(document.allocator)); - document_free_allocator(document.allocator); + free_all(common.scratch_allocator(document.allocator)) + document_free_allocator(document.allocator) - document.allocator = nil; - document.client_owned = false; + document.allocator = nil + document.client_owned = false - common.delete_uri(document.uri); + common.delete_uri(document.uri) - delete(document.text); + delete(document.text) - document.used_text = 0; + document.used_text = 0 - return .None; + return .None } document_refresh :: proc(document: ^common.Document, config: ^common.Config, writer: ^Writer) -> common.Error { - errors, ok := parse_document(document, config); + errors, ok := parse_document(document, config) if !ok { - return .ParseError; + return .ParseError } if writer != nil && len(errors) > 0 { - document.diagnosed_errors = true; + document.diagnosed_errors = true params := NotificationPublishDiagnosticsParams { uri = document.uri.uri, diagnostics = make([]Diagnostic, len(errors), context.temp_allocator), - }; + } for error, i in errors { params.diagnostics[i] = Diagnostic { @@ -268,16 +268,16 @@ document_refresh :: proc(document: ^common.Document, config: ^common.Config, wri severity = DiagnosticSeverity.Error, code = "test", message = error.message, - }; + } } notifaction := Notification { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = params, - }; + } - send_notification(notifaction, writer); + send_notification(notifaction, writer) } if writer != nil && len(errors) == 0 { @@ -291,31 +291,31 @@ document_refresh :: proc(document: ^common.Document, config: ^common.Config, wri uri = document.uri.uri, diagnostics = make([]Diagnostic, len(errors), context.temp_allocator), }, - }; + } - document.diagnosed_errors = false; + document.diagnosed_errors = false - send_notification(notifaction, writer); + send_notification(notifaction, writer) } } //We only resolve the entire file, if we are dealing with the heavy features that require the entire file resolved. //This gives the user a choice to use "fast mode" with only completion and gotos. if config.enable_semantic_tokens || config.enable_inlay_hints { - resolve_entire_file(document); + resolve_entire_file(document) } - return .None; + return .None } -current_errors: [dynamic]ParserError; +current_errors: [dynamic]ParserError parser_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { error := ParserError { line = pos.line,column = pos.column,file = pos.file, offset = pos.offset,message = fmt.tprintf(msg, ..args), - }; - append(¤t_errors, error); + } + append(¤t_errors, error) } parse_document :: proc(document: ^common.Document, config: ^common.Config) -> ([]ParserError, bool) { @@ -323,92 +323,92 @@ parse_document :: proc(document: ^common.Document, config: ^common.Config) -> ([ err = parser_error_handler, warn = common.parser_warning_handler, flags = {.Optional_Semicolons}, - }; + } - current_errors = make([dynamic]ParserError, context.temp_allocator); + current_errors = make([dynamic]ParserError, context.temp_allocator) - free_all(common.scratch_allocator(document.allocator)); + free_all(common.scratch_allocator(document.allocator)) - context.allocator = common.scratch_allocator(document.allocator); + context.allocator = common.scratch_allocator(document.allocator) //have to cheat the parser since it really wants to parse an entire package with the new changes... - pkg := new(ast.Package); - pkg.kind = .Normal; - pkg.fullpath = document.uri.path; + pkg := new(ast.Package) + pkg.kind = .Normal + pkg.fullpath = document.uri.path document.ast = ast.File { fullpath = document.uri.path, src = string(document.text[:document.used_text]), pkg = pkg, - }; + } - parser.parse_file(&p, &document.ast); + parser.parse_file(&p, &document.ast) - imports := make([dynamic]common.Package); + imports := make([dynamic]common.Package) - when ODIN_OS == "windows" { - document.package_name = strings.to_lower(path.dir(document.uri.path, context.temp_allocator)); + when ODIN_OS == .Windows { + document.package_name = strings.to_lower(path.dir(document.uri.path, context.temp_allocator)) } else { - document.package_name = path.dir(document.uri.path); + document.package_name = path.dir(document.uri.path) } for imp, index in document.ast.imports { if i := strings.index(imp.fullpath, "\""); i == -1 { - continue; + continue } //collection specified if i := strings.index(imp.fullpath, ":"); i != -1 && i > 1 && i < len(imp.fullpath) - 1 { if len(imp.fullpath) < 2 { - continue; + continue } - collection := imp.fullpath[1:i]; - p := imp.fullpath[i + 1:len(imp.fullpath) - 1]; + collection := imp.fullpath[1:i] + p := imp.fullpath[i + 1:len(imp.fullpath) - 1] - dir, ok := config.collections[collection]; + dir, ok := config.collections[collection] if !ok { - continue; + continue } - import_: common.Package; + import_: common.Package - when ODIN_OS == "windows" { - import_.name = strings.clone(path.join(elems = {strings.to_lower(dir, context.temp_allocator), p}, allocator = context.temp_allocator)); + when ODIN_OS == .Windows { + import_.name = strings.clone(path.join(elems = {strings.to_lower(dir, context.temp_allocator), p}, allocator = context.temp_allocator)) } else { - import_.name = strings.clone(path.join(elems = {dir, p}, allocator = context.temp_allocator)); + import_.name = strings.clone(path.join(elems = {dir, p}, allocator = context.temp_allocator)) } if imp.name.text != "" { - import_.base = imp.name.text; + import_.base = imp.name.text } else { - import_.base = path.base(import_.name, false); + import_.base = path.base(import_.name, false) } - append(&imports, import_); + append(&imports, import_) } else { //relative if len(imp.fullpath) < 2 { - continue; + continue } - import_: common.Package; - import_.name = path.join(elems = {document.package_name, imp.fullpath[1:len(imp.fullpath) - 1]}, allocator = context.temp_allocator); - import_.name = path.clean(import_.name); + import_: common.Package + import_.name = path.join(elems = {document.package_name, imp.fullpath[1:len(imp.fullpath) - 1]}, allocator = context.temp_allocator) + import_.name = path.clean(import_.name) if imp.name.text != "" { - import_.base = imp.name.text; + import_.base = imp.name.text } else { - import_.base = path.base(import_.name, false); + import_.base = path.base(import_.name, false) } - append(&imports, import_); + append(&imports, import_) } } - document.imports = imports[:]; + document.imports = imports[:] - return current_errors[:], true; + return current_errors[:], true } diff --git a/src/server/format.odin b/src/server/format.odin index 1bf4892..5829793 100644 --- a/src/server/format.odin +++ b/src/server/format.odin @@ -19,39 +19,39 @@ DocumentFormattingParams :: struct { get_complete_format :: proc(document: ^common.Document, config: ^common.Config) -> ([]TextEdit, bool) { - style := printer.default_style; - style.max_characters = config.formatter.characters; - style.tabs = config.formatter.tabs; + style := printer.default_style + style.max_characters = config.formatter.characters + style.tabs = config.formatter.tabs - prnt := printer.make_printer(style, context.temp_allocator); + prnt := printer.make_printer(style, context.temp_allocator) if document.ast.syntax_error_count > 0 { - return {}, true; + return {}, true } if len(document.text) == 0 { - return {}, true; + return {}, true } - src := printer.print(&prnt, &document.ast); + src := printer.print(&prnt, &document.ast) - end_line := 0; - end_charcter := 0; + end_line := 0 + end_charcter := 0 - last := document.text[0]; - line := 0; + last := document.text[0] + line := 0 for current_index := 0; current_index < len(document.text); current_index += 1 { - current := document.text[current_index]; + current := document.text[current_index] if last == '\r' && current == '\n' { - line += 1; - current_index += 1; + line += 1 + current_index += 1 } else if current == '\n' { - line += 1; + line += 1 } - last = current; + last = current } edit := TextEdit { @@ -66,11 +66,11 @@ get_complete_format :: proc(document: ^common.Document, config: ^common.Config) line = line+1, }, }, - }; + } - edits := make([dynamic]TextEdit, context.temp_allocator); + edits := make([dynamic]TextEdit, context.temp_allocator) - append(&edits, edit); + append(&edits, edit) - return edits[:], true; + return edits[:], true } diff --git a/src/server/hover.odin b/src/server/hover.odin index e7c5dba..5dd6acf 100644 --- a/src/server/hover.odin +++ b/src/server/hover.odin @@ -18,158 +18,158 @@ import "shared:index" import "shared:analysis" write_hover_content :: proc(ast_context: ^analysis.AstContext, symbol: index.Symbol) -> MarkupContent { - using analysis; + using analysis - content: MarkupContent; + content: MarkupContent - symbol := symbol; + symbol := symbol if untyped, ok := symbol.value.(index.SymbolUntypedValue); ok { switch untyped.type { - case .String: symbol.signature = "string"; - case .Bool: symbol.signature = "bool"; - case .Float: symbol.signature = "float"; - case .Integer: symbol.signature = "int"; + case .String: symbol.signature = "string" + case .Bool: symbol.signature = "bool" + case .Float: symbol.signature = "float" + case .Integer: symbol.signature = "int" } } - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) - cat := concatenate_symbol_information(ast_context, symbol, false); + cat := concatenate_symbol_information(ast_context, symbol, false) if cat != "" { - content.kind = "markdown"; - content.value = fmt.tprintf("```odin\n %v\n```\n%v", cat, symbol.doc); + content.kind = "markdown" + content.value = fmt.tprintf("```odin\n %v\n```\n%v", cat, symbol.doc) } else { - content.kind = "plaintext"; + content.kind = "plaintext" } - return content; + return content } get_hover_information :: proc(document: ^common.Document, position: common.Position) -> (Hover, bool) { - using analysis; + using analysis hover := Hover { contents = { kind = "plaintext", }, - }; + } - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - position_context, ok := get_document_position_context(document, position, .Hover); + position_context, ok := get_document_position_context(document, position, .Hover) - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) if position_context.function != nil { - get_locals(document.ast, position_context.function, &ast_context, &position_context); + get_locals(document.ast, position_context.function, &ast_context, &position_context) } if position_context.identifier != nil { - if ident, ok := position_context.identifier.derived.(ast.Ident); ok { + if ident, ok := position_context.identifier.derived.(^ast.Ident); ok { if _, ok := common.keyword_map[ident.name]; ok { - hover.contents.kind = "plaintext"; - hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src); - return hover, true; + hover.contents.kind = "plaintext" + hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src) + return hover, true } } } if position_context.selector != nil && position_context.identifier != nil { - hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src); + hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src) - 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 //if the base selector is the client wants to go to. - if base, ok := position_context.selector.derived.(ast.Ident); ok && position_context.identifier != nil { + if base, ok := position_context.selector.derived.(^ast.Ident); ok && position_context.identifier != nil { - ident := position_context.identifier.derived.(ast.Ident); + ident := position_context.identifier.derived.(^ast.Ident)^ if ident.name == base.name { if resolved, ok := resolve_type_identifier(&ast_context, ident); ok { - resolved.signature = get_signature(&ast_context, ident, resolved); - resolved.name = ident.name; + resolved.signature = get_signature(&ast_context, ident, resolved) + resolved.name = ident.name if resolved.type == .Variable { - resolved.pkg = ast_context.document_package; + resolved.pkg = ast_context.document_package } - hover.contents = write_hover_content(&ast_context, resolved); - return hover, true; + hover.contents = write_hover_content(&ast_context, resolved) + return hover, true } } } - selector: index.Symbol; - selector, ok = resolve_type_expression(&ast_context, position_context.selector); + selector: index.Symbol + selector, ok = resolve_type_expression(&ast_context, position_context.selector) if !ok { - return hover, true; + return hover, true } - field: string; + field: string if position_context.field != nil { - switch v in position_context.field.derived { - case ast.Ident: - field = v.name; + #partial switch v in position_context.field.derived { + case ^ast.Ident: + field = v.name } } - hover.range = common.get_token_range(position_context.identifier^, document.ast.src); + hover.range = common.get_token_range(position_context.identifier^, document.ast.src) #partial switch v in selector.value { case index.SymbolStructValue: for name, i in v.names { if strings.compare(name, field) == 0 { if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { - symbol.name = name; //TODO refractor - never set symbol name after creation - change writer_hover_content - symbol.pkg = selector.name; - symbol.signature = common.node_to_string(v.types[i]); - hover.contents = write_hover_content(&ast_context, symbol); - return hover, true; + symbol.name = name //TODO refractor - never set symbol name after creation - change writer_hover_content + symbol.pkg = selector.name + symbol.signature = common.node_to_string(v.types[i]) + hover.contents = write_hover_content(&ast_context, symbol) + return hover, true } } } case index.SymbolPackageValue: if position_context.field != nil { - if ident, ok := position_context.field.derived.(ast.Ident); ok { - ast_context.current_package = selector.pkg; - if symbol, ok := resolve_type_identifier(&ast_context, ident); ok { - hover.contents = write_hover_content(&ast_context, symbol); - return hover, true; + if ident, ok := position_context.field.derived.(^ast.Ident); ok { + ast_context.current_package = selector.pkg + if symbol, ok := resolve_type_identifier(&ast_context, ident^); ok { + hover.contents = write_hover_content(&ast_context, symbol) + return hover, true } } } } } else if position_context.identifier != nil { - 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 - ident := position_context.identifier.derived.(ast.Ident); + ident := position_context.identifier.derived.(^ast.Ident)^ - hover.range = common.get_token_range(position_context.identifier^, document.ast.src); + hover.range = common.get_token_range(position_context.identifier^, document.ast.src) if resolved, ok := resolve_type_identifier(&ast_context, ident); ok { - resolved.signature = get_signature(&ast_context, ident, resolved); - resolved.name = ident.name; + resolved.signature = get_signature(&ast_context, ident, resolved) + resolved.name = ident.name if resolved.type == .Variable { - resolved.pkg = ast_context.document_package; + resolved.pkg = ast_context.document_package } - hover.contents = write_hover_content(&ast_context, resolved); - return hover, true; + hover.contents = write_hover_content(&ast_context, resolved) + return hover, true } } - return hover, true; + return hover, true } diff --git a/src/server/inlay_hints.odin b/src/server/inlay_hints.odin index 1e7d2c3..ae3d9a0 100644 --- a/src/server/inlay_hints.odin +++ b/src/server/inlay_hints.odin @@ -9,11 +9,11 @@ import "shared:index" //document get_inlay_hints :: proc(document: ^common.Document, symbols: map[uintptr]index.Symbol) -> ([]InlayHint, bool) { - using analysis; + using analysis - hints := make([dynamic]InlayHint, context.temp_allocator); + hints := make([dynamic]InlayHint, context.temp_allocator) - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) Visit_Data :: struct { calls: [dynamic]^ast.Node, @@ -21,20 +21,20 @@ get_inlay_hints :: proc(document: ^common.Document, symbols: map[uintptr]index.S data := Visit_Data { calls = make([dynamic]^ast.Node, context.temp_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; + data := cast(^Visit_Data)visitor.data - if call, ok := node.derived.(ast.Call_Expr); ok { - append(&data.calls, node); + if call, ok := node.derived.(^ast.Call_Expr); ok { + append(&data.calls, node) } - return visitor; + return visitor } visitor := ast.Visitor { @@ -43,17 +43,17 @@ get_inlay_hints :: proc(document: ^common.Document, symbols: map[uintptr]index.S } for decl in document.ast.decls { - ast.walk(&visitor, decl); + ast.walk(&visitor, decl) } loop: for node_call in &data.calls { symbol_arg_count := 0 - call := node_call.derived.(ast.Call_Expr); + call := node_call.derived.(^ast.Call_Expr) for arg in call.args { - if _, ok := arg.derived.(ast.Field); ok { - continue loop; + if _, ok := arg.derived.(^ast.Field); ok { + continue loop } } @@ -62,23 +62,23 @@ get_inlay_hints :: proc(document: ^common.Document, symbols: map[uintptr]index.S for arg in symbol_call.arg_types { for name in arg.names { if symbol_arg_count >= len(call.args) { - continue loop; + continue loop } - if ident, ok := name.derived.(ast.Ident); ok { + if ident, ok := name.derived.(^ast.Ident); ok { hint := InlayHint { kind = "parameter", label = fmt.tprintf("%v = ", ident.name), range = common.get_token_range(call.args[symbol_arg_count], string(document.text)), } - append(&hints, hint); + append(&hints, hint) } - symbol_arg_count += 1; + symbol_arg_count += 1 } } } } } - return hints[:], true; + return hints[:], true } \ No newline at end of file diff --git a/src/server/lens.odin b/src/server/lens.odin index 9d80d0c..93827f5 100644 --- a/src/server/lens.odin +++ b/src/server/lens.odin @@ -22,22 +22,22 @@ CodeLens :: struct { get_code_lenses :: proc(document: ^common.Document, position: common.Position) -> ([]CodeLens, bool) { - using analysis; + using analysis - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) - symbols := make([dynamic]CodeLens, context.temp_allocator); + symbols := make([dynamic]CodeLens, context.temp_allocator) if len(document.ast.decls) == 0 { - return {}, true; + return {}, true } for name, global in ast_context.globals { - if proc_lit, ok := global.expr.derived.(ast.Proc_Lit); ok { + if proc_lit, ok := global.expr.derived.(^ast.Proc_Lit); ok { @@ -47,7 +47,7 @@ get_code_lenses :: proc(document: ^common.Document, position: common.Position) - } - return {}, false; + return {}, false } diff --git a/src/server/log.odin b/src/server/log.odin index cf83979..7ed3da9 100644 --- a/src/server/log.odin +++ b/src/server/log.odin @@ -12,27 +12,27 @@ Default_Console_Logger_Opts :: log.Options { .Short_File_Path, .Line, .Procedure, -} | log.Full_Timestamp_Opts; +} | log.Full_Timestamp_Opts Lsp_Logger_Data :: struct { writer: ^Writer, } create_lsp_logger :: proc(writer: ^Writer, lowest := log.Level.Debug, opt := Default_Console_Logger_Opts) -> log.Logger { - data := new(Lsp_Logger_Data); - data.writer = writer; - return log.Logger {lsp_logger_proc, data, lowest, opt}; + data := new(Lsp_Logger_Data) + data.writer = writer + return log.Logger {lsp_logger_proc, data, lowest, opt} } destroy_lsp_logger :: proc(log: ^log.Logger) { - free(log.data); + free(log.data) } lsp_logger_proc :: proc(logger_data: rawptr, level: log.Level, text: string, options: log.Options, location := #caller_location) { - data := cast(^Lsp_Logger_Data)logger_data; + data := cast(^Lsp_Logger_Data)logger_data - message := fmt.tprintf("%s", text); + message := fmt.tprintf("%s", text) notification := Notification { jsonrpc = "2.0", @@ -41,7 +41,7 @@ lsp_logger_proc :: proc(logger_data: rawptr, level: log.Level, text: string, opt type = 1, message = message, }, - }; + } - send_notification(notification, data.writer); + send_notification(notification, data.writer) } diff --git a/src/server/reader.odin b/src/server/reader.odin index a05e147..be0d4ae 100644 --- a/src/server/reader.odin +++ b/src/server/reader.odin @@ -4,7 +4,7 @@ import "core:os" import "core:mem" import "core:strings" -ReaderFn :: proc(_: rawptr, _: []byte) -> (int, int); +ReaderFn :: proc(_: rawptr, _: []byte) -> (int, int) Reader :: struct { reader_fn: ReaderFn, @@ -12,61 +12,61 @@ Reader :: struct { } make_reader :: proc(reader_fn: ReaderFn, reader_context: rawptr) -> Reader { - return Reader {reader_context = reader_context, reader_fn = reader_fn}; + return Reader {reader_context = reader_context, reader_fn = reader_fn} } read_u8 :: proc(reader: ^Reader) -> (u8, bool) { - value: [1]byte; + value: [1]byte - read, err := reader.reader_fn(reader.reader_context, value[:]); + read, err := reader.reader_fn(reader.reader_context, value[:]) if (err != 0 || read != 1) { - return 0, false; + return 0, false } - return value[0], true; + return value[0], true } read_until_delimiter :: proc(reader: ^Reader, delimiter: u8, builder: ^strings.Builder) -> bool { for true { - value, success := read_u8(reader); + value, success := read_u8(reader) if (!success) { - return false; + return false } - strings.write_byte(builder, value); + strings.write_byte(builder, value) if (value == delimiter) { - break; + break } } - return true; + return true } read_sized :: proc(reader: ^Reader, data: []u8) -> (ok: bool) { - ok = true; - size := len(data); - n := 0; + ok = true + size := len(data) + n := 0 for n < size && ok { - read: int; - err_code: int; + read: int + err_code: int - read, err_code = reader.reader_fn(reader.reader_context, data[n:]); + read, err_code = reader.reader_fn(reader.reader_context, data[n:]) - ok = err_code == 0; + ok = err_code == 0 - n += read; + n += read } if n >= size { - ok = true; + ok = true } - return; + return } diff --git a/src/server/requests.odin b/src/server/requests.odin index b06f4cd..00af132 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -63,7 +63,7 @@ make_response_message :: proc (id: RequestId, params: ResponseParams) -> Respons jsonrpc = "2.0", id = id, result = params, - }; + } } make_response_message_error :: proc (id: RequestId, error: ResponseError) -> ResponseMessageError { @@ -72,7 +72,7 @@ make_response_message_error :: proc (id: RequestId, error: ResponseError) -> Res jsonrpc = "2.0", id = id, error = error, - }; + } } RequestThreadData :: struct { @@ -87,157 +87,157 @@ Request :: struct { } -requests_sempahore: sync.Semaphore; -requests_mutex: sync.Mutex; +requests_sempahore: sync.Semaphore +requests_mutex: sync.Mutex -requests: [dynamic]Request; -deletings: [dynamic]Request; +requests: [dynamic]Request +deletings: [dynamic]Request thread_request_main :: proc(data: rawptr) { - request_data := cast(^RequestThreadData)data; + request_data := cast(^RequestThreadData)data for common.config.running { - header, success := read_and_parse_header(request_data.reader); + header, success := read_and_parse_header(request_data.reader) if (!success) { - log.error("Failed to read and parse header"); - return; + log.error("Failed to read and parse header") + return } - value: json.Value; - value, success = read_and_parse_body(request_data.reader, header); + value: json.Value + value, success = read_and_parse_body(request_data.reader, header) if (!success) { - log.error("Failed to read and parse body"); - return; + log.error("Failed to read and parse body") + return } - root, ok := value.(json.Object); + root, ok := value.(json.Object) if !ok { - log.error("No root object"); - return; + log.error("No root object") + return } - id: RequestId; - id_value: json.Value; - id_value, ok = root["id"]; + id: RequestId + id_value: json.Value + id_value, ok = root["id"] if ok { #partial switch v in id_value { case json.String: - id = v; + id = v case json.Integer: - id = v; + id = v case: - id = 0; + id = 0 } } - sync.mutex_lock(&requests_mutex); + sync.mutex_lock(&requests_mutex) - method := root["method"].(json.String); + method := root["method"].(json.String) if method == "$/cancelRequest" { - append(&deletings, Request { id = id }); + append(&deletings, Request { id = id }) } else if method in notification_map { - append(&requests, Request { value = root, is_notification = true}); - sync.semaphore_post(&requests_sempahore); + append(&requests, Request { value = root, is_notification = true}) + sync.semaphore_post(&requests_sempahore) } else { - append(&requests, Request { id = id, value = root}); - sync.semaphore_post(&requests_sempahore); + append(&requests, Request { id = id, value = root}) + sync.semaphore_post(&requests_sempahore) } - sync.mutex_unlock(&requests_mutex); + sync.mutex_unlock(&requests_mutex) - free_all(context.temp_allocator); + free_all(context.temp_allocator) } } read_and_parse_header :: proc (reader: ^Reader) -> (Header, bool) { - header: Header; + header: Header - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) - found_content_length := false; + found_content_length := false for true { - strings.reset_builder(&builder); + strings.reset_builder(&builder) if !read_until_delimiter(reader, '\n', &builder) { - log.error("Failed to read with delimiter"); - return header, false; + log.error("Failed to read with delimiter") + return header, false } - message := strings.to_string(builder); + message := strings.to_string(builder) if len(message) == 0 || message[len(message) - 2] != '\r' { - log.error("No carriage return"); - return header, false; + log.error("No carriage return") + return header, false } if len(message) == 2 { - break; + break } - index := strings.last_index_byte(message, ':'); + index := strings.last_index_byte(message, ':') if index == -1 { - log.error("Failed to find semicolon"); - return header, false; + log.error("Failed to find semicolon") + return header, false } - header_name := message[0:index]; - header_value := message[len(header_name) + 2:len(message) - 2]; + header_name := message[0:index] + header_value := message[len(header_name) + 2:len(message) - 2] if strings.compare(header_name, "Content-Length") == 0 { if len(header_value) == 0 { - log.error("Header value has no length"); - return header, false; + log.error("Header value has no length") + return header, false } - value, ok := strconv.parse_int(header_value); + value, ok := strconv.parse_int(header_value) if !ok { - log.error("Failed to parse content length value"); - return header, false; + log.error("Failed to parse content length value") + return header, false } - header.content_length = value; + header.content_length = value - found_content_length = true; + found_content_length = true } else if strings.compare(header_name, "Content-Type") == 0 { if len(header_value) == 0 { - log.error("Header value has no length"); - return header, false; + log.error("Header value has no length") + return header, false } } } - return header, found_content_length; + return header, found_content_length } read_and_parse_body :: proc (reader: ^Reader, header: Header) -> (json.Value, bool) { - value: json.Value; + value: json.Value - data := make([]u8, header.content_length, context.temp_allocator); + data := make([]u8, header.content_length, context.temp_allocator) if !read_sized(reader, data) { - log.error("Failed to read body"); - return value, false; + log.error("Failed to read body") + return value, false } - err: json.Error; + err: json.Error - value, err = json.parse(data = data, allocator = context.allocator, parse_integers = true); + value, err = json.parse(data = data, allocator = context.allocator, parse_integers = true) if (err != json.Error.None) { - log.error("Failed to parse body"); - return value, false; + log.error("Failed to parse body") + return value, false } - return value, true; + return value, true } call_map : map [string] proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error = @@ -260,7 +260,7 @@ call_map : map [string] proc(json.Value, RequestId, ^common.Config, ^Writer) -> "textDocument/formatting" = request_format_document, "odin/inlayHints" = request_inlay_hint, "textDocument/documentLink" = request_document_links, -}; +} notification_map: map [string] bool = { "textDocument/didOpen" = true, @@ -271,52 +271,52 @@ notification_map: map [string] bool = { } consume_requests :: proc (config: ^common.Config, writer: ^Writer) -> bool { - temp_requests := make([dynamic]Request, 0, context.temp_allocator); + temp_requests := make([dynamic]Request, 0, context.temp_allocator) - sync.mutex_lock(&requests_mutex); + sync.mutex_lock(&requests_mutex) for d in deletings { - delete_index := -1; + delete_index := -1 for request, i in requests { if request.id == d.id { - delete_index := i; - break; + delete_index := i + break } } if delete_index != -1 { - cancel(requests[delete_index].value, requests[delete_index].id, writer, config); - ordered_remove(&requests, delete_index); + cancel(requests[delete_index].value, requests[delete_index].id, writer, config) + ordered_remove(&requests, delete_index) } } for request in requests { - append(&temp_requests, request); + append(&temp_requests, request) } - sync.mutex_unlock(&requests_mutex); + sync.mutex_unlock(&requests_mutex) - request_index := 0; + request_index := 0 for ; request_index < len(temp_requests); request_index += 1 { - request := temp_requests[request_index]; - call(request.value, request.id, writer, config); + request := temp_requests[request_index] + call(request.value, request.id, writer, config) } - sync.mutex_lock(&requests_mutex); + sync.mutex_lock(&requests_mutex) for i := 0; i < request_index; i += 1 { - pop_front(&requests); + pop_front(&requests) } - sync.mutex_unlock(&requests_mutex); + sync.mutex_unlock(&requests_mutex) if request_index != len(temp_requests) { - sync.semaphore_post(&requests_sempahore); + sync.semaphore_post(&requests_sempahore) } - sync.semaphore_wait_for(&requests_sempahore); + sync.semaphore_wait_for(&requests_sempahore) - return true; + return true } @@ -324,47 +324,47 @@ cancel :: proc(value: json.Value, id: RequestId, writer: ^Writer, config: ^commo response := make_response_message( id = id, params = ResponseParams {}, - ); + ) - send_response(response, writer); + send_response(response, writer) } call :: proc(value: json.Value, id: RequestId, writer: ^Writer, config: ^common.Config) { - root := value.(json.Object); - method := root["method"].(json.String); + root := value.(json.Object) + method := root["method"].(json.String) if fn, ok := call_map[method]; !ok { - response := make_response_message_error(id = id, error = ResponseError {code = .MethodNotFound, message = ""}); - send_error(response, writer); + response := make_response_message_error(id = id, error = ResponseError {code = .MethodNotFound, message = ""}) + send_error(response, writer) } else { - err := fn(root["params"], id, config, writer); + err := fn(root["params"], id, config, writer) if err != .None { response := make_response_message_error( id = id, error = ResponseError {code = err, message = ""}, - ); - send_error(response, writer); + ) + send_error(response, writer) } } } request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - initialize_params: RequestInitializeParams; + initialize_params: RequestInitializeParams if unmarshal(params, initialize_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - config.workspace_folders = make([dynamic]common.WorkspaceFolder); + config.workspace_folders = make([dynamic]common.WorkspaceFolder) for s in initialize_params.workspaceFolders { - append(&config.workspace_folders, s); + append(&config.workspace_folders, s) } read_ols_config :: proc(file: string, config: ^common.Config, uri: common.Uri) { @@ -381,111 +381,111 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C if unmarshal(value, ols_config, context.temp_allocator) == .None { - config.thread_count = ols_config.thread_pool_count; - config.enable_document_symbols = ols_config.enable_document_symbols; - config.enable_hover = ols_config.enable_hover; + config.thread_count = ols_config.thread_pool_count + config.enable_document_symbols = ols_config.enable_document_symbols + config.enable_hover = ols_config.enable_hover config.enable_format = true // ols_config.enable_format; - config.enable_semantic_tokens = ols_config.enable_semantic_tokens; - config.enable_procedure_context = ols_config.enable_procedure_context; - config.enable_snippets = ols_config.enable_snippets; - config.verbose = ols_config.verbose; - config.file_log = ols_config.file_log; - config.formatter = ols_config.formatter; - config.odin_command = strings.clone(ols_config.odin_command, context.allocator); - config.checker_args = ols_config.checker_args; - config.enable_inlay_hints = ols_config.enable_inlay_hints; + config.enable_semantic_tokens = ols_config.enable_semantic_tokens + config.enable_procedure_context = ols_config.enable_procedure_context + config.enable_snippets = ols_config.enable_snippets + config.verbose = ols_config.verbose + config.file_log = ols_config.file_log + config.formatter = ols_config.formatter + config.odin_command = strings.clone(ols_config.odin_command, context.allocator) + config.checker_args = ols_config.checker_args + config.enable_inlay_hints = ols_config.enable_inlay_hints for p in ols_config.collections { - forward_path, _ := filepath.to_slash(p.path, context.temp_allocator); + forward_path, _ := filepath.to_slash(p.path, context.temp_allocator) if filepath.is_abs(p.path) { - config.collections[strings.clone(p.name)] = strings.clone(forward_path); + config.collections[strings.clone(p.name)] = strings.clone(forward_path) } else { - config.collections[strings.clone(p.name)] = path.join(elems = {uri.path, forward_path}, allocator = context.allocator); + config.collections[strings.clone(p.name)] = path.join(elems = {uri.path, forward_path}, allocator = context.allocator) } } if ok := "" in config.collections; !ok { - config.collections[""] = strings.clone(uri.path); + config.collections[""] = strings.clone(uri.path) } } else { - log.errorf("Failed to unmarshal %v", file); + log.errorf("Failed to unmarshal %v", file) } } else { - log.errorf("Failed to parse json %v", file); + log.errorf("Failed to parse json %v", file) } } else { - log.errorf("Failed to read/find %v", file); + log.errorf("Failed to read/find %v", file) } } - project_uri := ""; + project_uri := "" if len(config.workspace_folders) > 0 { - project_uri = config.workspace_folders[0].uri; + project_uri = config.workspace_folders[0].uri } else if initialize_params.rootUri != "" { - project_uri = initialize_params.rootUri; + project_uri = initialize_params.rootUri } if uri, ok := common.parse_uri(project_uri, context.temp_allocator); ok { - ols_config_path := path.join(elems = {uri.path, "ols.json"}, allocator = context.temp_allocator); - read_ols_config(ols_config_path, config, uri); + ols_config_path := path.join(elems = {uri.path, "ols.json"}, allocator = context.temp_allocator) + read_ols_config(ols_config_path, config, uri) } - when ODIN_OS == "windows" { - odin_core_env := os.get_env("ODIN_ROOT", context.temp_allocator); + when ODIN_OS == .Windows { + odin_core_env := os.get_env("ODIN_ROOT", context.temp_allocator) } else { - odin_core_env, _ := os.getenv("ODIN_ROOT"); + odin_core_env, _ := os.getenv("ODIN_ROOT") } if "core" not_in config.collections && odin_core_env != "" { - forward_path, _ := filepath.to_slash(odin_core_env, context.temp_allocator); - config.collections["core"] = path.join(elems = {forward_path, "core"}, allocator = context.allocator); + forward_path, _ := filepath.to_slash(odin_core_env, context.temp_allocator) + config.collections["core"] = path.join(elems = {forward_path, "core"}, allocator = context.allocator) } if "vendor" not_in config.collections && odin_core_env != "" { - forward_path, _ := filepath.to_slash(odin_core_env, context.temp_allocator); - config.collections["vendor"] = path.join(elems = {forward_path, "vendor"}, allocator = context.allocator); + forward_path, _ := filepath.to_slash(odin_core_env, context.temp_allocator) + config.collections["vendor"] = path.join(elems = {forward_path, "vendor"}, allocator = context.allocator) } for format in initialize_params.capabilities.textDocument.hover.contentFormat { if format == "markdown" { - config.hover_support_md = true; + config.hover_support_md = true } } for format in initialize_params.capabilities.textDocument.completion.documentationFormat { if format == "markdown" { - config.completion_support_md = true; + config.completion_support_md = true } } - config.enable_snippets &= initialize_params.capabilities.textDocument.completion.completionItem.snippetSupport; - config.signature_offset_support = initialize_params.capabilities.textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport; + config.enable_snippets &= initialize_params.capabilities.textDocument.completion.completionItem.snippetSupport + config.signature_offset_support = initialize_params.capabilities.textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport - completionTriggerCharacters := []string {".", ">", "#", "\"", "/", ":"}; - signatureTriggerCharacters := []string {"(", ","}; - signatureRetriggerCharacters := []string {","}; + completionTriggerCharacters := []string {".", ">", "#", "\"", "/", ":"} + signatureTriggerCharacters := []string {"(", ","} + signatureRetriggerCharacters := []string {","} - token_type := type_info_of(SemanticTokenTypes).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum); - token_modifier := type_info_of(SemanticTokenModifiers).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum); + token_type := type_info_of(SemanticTokenTypes).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum) + token_modifier := type_info_of(SemanticTokenModifiers).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum) - token_types := make([]string, len(token_type.names), context.temp_allocator); - token_modifiers := make([]string, len(token_modifier.names), context.temp_allocator); + token_types := make([]string, len(token_type.names), context.temp_allocator) + token_modifiers := make([]string, len(token_modifier.names), context.temp_allocator) for name, i in token_type.names { if name == "EnumMember" { - token_types[i] = "enumMember"; + token_types[i] = "enumMember" } else { - token_types[i] = strings.to_lower(name, context.temp_allocator); + token_types[i] = strings.to_lower(name, context.temp_allocator) } } for name, i in token_modifier.names { - token_modifiers[i] = strings.to_lower(name, context.temp_allocator); + token_modifiers[i] = strings.to_lower(name, context.temp_allocator) } response := make_response_message( @@ -523,335 +523,335 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C resolveProvider = false, }, }, - }, id = id); + }, id = id) - send_response(response, writer); + send_response(response, writer) /* Temp index here, but should be some background thread that starts the indexing */ - index.indexer.dynamic_index = index.make_memory_index(index.make_symbol_collection(context.allocator, config)); + index.indexer.dynamic_index = index.make_memory_index(index.make_symbol_collection(context.allocator, config)) - index.build_static_index(context.allocator, config); + index.build_static_index(context.allocator, config) /* Add runtime package */ if core, ok := config.collections["core"]; ok { - when ODIN_OS == "windows" { - append(&index.indexer.builtin_packages, path.join(strings.to_lower(core, context.temp_allocator), "runtime")); + when ODIN_OS == .Windows { + append(&index.indexer.builtin_packages, path.join(strings.to_lower(core, context.temp_allocator), "runtime")) } else { - append(&index.indexer.builtin_packages, path.join(core, "runtime")); + append(&index.indexer.builtin_packages, path.join(core, "runtime")) } } - log.info("Finished indexing"); + log.info("Finished indexing") - return .None; + return .None } request_initialized :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - return .None; + return .None } request_shutdown :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - response := make_response_message(params = nil, id = id); + response := make_response_message(params = nil, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_definition :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - definition_params: TextDocumentPositionParams; + definition_params: TextDocumentPositionParams if unmarshal(params, definition_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(definition_params.textDocument.uri); + document := document_get(definition_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - locations, ok2 := get_definition_location(document, definition_params.position); + locations, ok2 := get_definition_location(document, definition_params.position) if !ok2 { - log.warn("Failed to get definition location"); + log.warn("Failed to get definition location") } if len(locations) == 1 { - response := make_response_message(params = locations[0], id = id); - send_response(response, writer); + response := make_response_message(params = locations[0], id = id) + send_response(response, writer) } else { - response := make_response_message(params = locations, id = id); - send_response(response, writer); + response := make_response_message(params = locations, id = id) + send_response(response, writer) } - return .None; + return .None } request_completion :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - completition_params: CompletionParams; + completition_params: CompletionParams if unmarshal(params, completition_params, context.temp_allocator) != .None { - log.error("Failed to unmarshal completion request"); - return .ParseError; + log.error("Failed to unmarshal completion request") + return .ParseError } - document := document_get(completition_params.textDocument.uri); + document := document_get(completition_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - list: CompletionList; - list, ok = get_completion_list(document, completition_params.position, completition_params.context_); + list: CompletionList + list, ok = get_completion_list(document, completition_params.position, completition_params.context_) if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = list, id = id); + response := make_response_message(params = list, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_signature_help :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - signature_params: SignatureHelpParams; + signature_params: SignatureHelpParams if unmarshal(params, signature_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(signature_params.textDocument.uri); + document := document_get(signature_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - help: SignatureHelp; - help, ok = get_signature_information(document, signature_params.position); + help: SignatureHelp + help, ok = get_signature_information(document, signature_params.position) if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = help, id = id); + response := make_response_message(params = help, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_format_document :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - format_params: DocumentFormattingParams; + format_params: DocumentFormattingParams if unmarshal(params, format_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(format_params.textDocument.uri); + document := document_get(format_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - edit: []TextEdit; - edit, ok = get_complete_format(document, config); + edit: []TextEdit + edit, ok = get_complete_format(document, config) if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = edit, id = id); + response := make_response_message(params = edit, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } notification_exit :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - config.running = false; - return .None; + config.running = false + return .None } notification_did_open :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - log.error("Failed to parse open document notification"); - return .ParseError; + log.error("Failed to parse open document notification") + return .ParseError } - open_params: DidOpenTextDocumentParams; + open_params: DidOpenTextDocumentParams if unmarshal(params, open_params, context.allocator) != .None { - log.error("Failed to parse open document notification"); - return .ParseError; + log.error("Failed to parse open document notification") + return .ParseError } if n := document_open(open_params.textDocument.uri, open_params.textDocument.text, config, writer); n != .None { - return .InternalError; + return .InternalError } - return .None; + return .None } notification_did_change :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - change_params: DidChangeTextDocumentParams; + change_params: DidChangeTextDocumentParams if unmarshal(params, change_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document_apply_changes(change_params.textDocument.uri, change_params.contentChanges, config, writer); + document_apply_changes(change_params.textDocument.uri, change_params.contentChanges, config, writer) - return .None; + return .None } notification_did_close :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - close_params: DidCloseTextDocumentParams; + close_params: DidCloseTextDocumentParams if unmarshal(params, close_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } if n := document_close(close_params.textDocument.uri); n != .None { - return .InternalError; + return .InternalError } - return .None; + return .None } notification_did_save :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - save_params: DidSaveTextDocumentParams; + save_params: DidSaveTextDocumentParams if unmarshal(params, save_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - uri: common.Uri; + uri: common.Uri if uri, ok = common.parse_uri(save_params.textDocument.uri, context.temp_allocator); !ok { - return .ParseError; + return .ParseError } - fullpath := uri.path; + fullpath := uri.path p := parser.Parser { err = index.log_error_handler, warn = index.log_warning_handler, - }; + } - dir := filepath.base(filepath.dir(fullpath, context.temp_allocator)); + dir := filepath.base(filepath.dir(fullpath, context.temp_allocator)) - pkg := new(ast.Package); - pkg.kind = .Normal; - pkg.fullpath = fullpath; - pkg.name = dir; + pkg := new(ast.Package) + pkg.kind = .Normal + pkg.fullpath = fullpath + pkg.name = dir if dir == "runtime" { - pkg.kind = .Runtime; + pkg.kind = .Runtime } file := ast.File { fullpath = fullpath, src = save_params.text, pkg = pkg, - }; + } - ok = parser.parse_file(&p, &file); + ok = parser.parse_file(&p, &file) if !ok { - log.errorf("error in parse file for indexing %v", fullpath); + log.errorf("error in parse file for indexing %v", fullpath) } for key, value in index.indexer.dynamic_index.collection.symbols { - when ODIN_OS == "windows"{ - uri := strings.to_lower(save_params.textDocument.uri, context.temp_allocator); + when ODIN_OS == .Windows { + uri := strings.to_lower(save_params.textDocument.uri, context.temp_allocator) } else { - uri := save_params.textDocument.uri; + uri := save_params.textDocument.uri } if value.uri == uri { - index.free_symbol(value, context.allocator); - index.indexer.dynamic_index.collection.symbols[key] = {}; + index.free_symbol(value, context.allocator) + index.indexer.dynamic_index.collection.symbols[key] = {} } } if ret := index.collect_symbols(&index.indexer.dynamic_index.collection, file, uri.uri); ret != .None { - log.errorf("failed to collect symbols on save %v", ret); + log.errorf("failed to collect symbols on save %v", ret) } - check(uri, writer, config); + check(uri, writer, config) - return .None; + return .None } request_semantic_token_full :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - semantic_params: SemanticTokensParams; + semantic_params: SemanticTokensParams if unmarshal(params, semantic_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(semantic_params.textDocument.uri); + document := document_get(semantic_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } range := common.Range { @@ -861,184 +861,184 @@ request_semantic_token_full :: proc (params: json.Value, id: RequestId, config: end = common.Position { line = 9000000, //should be enough }, - }; + } - symbols: SemanticTokens; + symbols: SemanticTokens if config.enable_semantic_tokens { if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok { - symbols = get_semantic_tokens(document, range, cache_symbols); + symbols = get_semantic_tokens(document, range, cache_symbols) } } - response := make_response_message(params = symbols, id = id); + response := make_response_message(params = symbols, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_semantic_token_range :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .None; + return .None } - semantic_params: SemanticTokensRangeParams; + semantic_params: SemanticTokensRangeParams if unmarshal(params, semantic_params, context.temp_allocator) != .None { - return .None; + return .None } - document := document_get(semantic_params.textDocument.uri); + document := document_get(semantic_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - symbols: SemanticTokens; + symbols: SemanticTokens if config.enable_semantic_tokens { if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok { - symbols = get_semantic_tokens(document, semantic_params.range, cache_symbols); + symbols = get_semantic_tokens(document, semantic_params.range, cache_symbols) } } - response := make_response_message(params = symbols, id = id); + response := make_response_message(params = symbols, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_document_symbols :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - symbol_params: DocumentSymbolParams; + symbol_params: DocumentSymbolParams if unmarshal(params, symbol_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(symbol_params.textDocument.uri); + document := document_get(symbol_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - symbols := get_document_symbols(document); + symbols := get_document_symbols(document) - response := make_response_message(params = symbols, id = id); + response := make_response_message(params = symbols, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_hover :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - hover_params: HoverParams; + hover_params: HoverParams if unmarshal(params, hover_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(hover_params.textDocument.uri); + document := document_get(hover_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - hover: Hover; - hover, ok = get_hover_information(document, hover_params.position); + hover: Hover + hover, ok = get_hover_information(document, hover_params.position) if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = hover, id = id); + response := make_response_message(params = hover, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_inlay_hint :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - inlay_params: InlayParams; + inlay_params: InlayParams if unmarshal(params, inlay_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(inlay_params.textDocument.uri); + document := document_get(inlay_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - hints: []InlayHint; + hints: []InlayHint if cache_symbols, ok := file_resolve_cache.files[document.uri.uri]; ok { - hints, ok = get_inlay_hints(document, cache_symbols); + hints, ok = get_inlay_hints(document, cache_symbols) } if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = hints, id = id); + response := make_response_message(params = hints, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } request_document_links :: proc (params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { - params_object, ok := params.(json.Object); + params_object, ok := params.(json.Object) if !ok { - return .ParseError; + return .ParseError } - link_params: DocumentLinkParams; + link_params: DocumentLinkParams if unmarshal(params, link_params, context.temp_allocator) != .None { - return .ParseError; + return .ParseError } - document := document_get(link_params.textDocument.uri); + document := document_get(link_params.textDocument.uri) if document == nil { - return .InternalError; + return .InternalError } - links: []DocumentLink; + links: []DocumentLink - links, ok = get_document_links(document); + links, ok = get_document_links(document) if !ok { - return .InternalError; + return .InternalError } - response := make_response_message(params = links, id = id); + response := make_response_message(params = links, id = id) - send_response(response, writer); + send_response(response, writer) - return .None; + return .None } \ No newline at end of file diff --git a/src/server/response.odin b/src/server/response.odin index c132532..7c07f41 100644 --- a/src/server/response.odin +++ b/src/server/response.odin @@ -5,63 +5,63 @@ import "core:encoding/json" send_notification :: proc (notification: Notification, writer: ^Writer) -> bool { - data, error := json.marshal(notification, context.temp_allocator); + data, error := json.marshal(notification, context.temp_allocator) - header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)); + header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)) if error != .None { - return false; + return false } if !write_sized(writer, transmute([]u8)header) { - return false; + return false } if !write_sized(writer, data) { - return false; + return false } - return true; + return true } send_response :: proc (response: ResponseMessage, writer: ^Writer) -> bool { - data, error := json.marshal(response, context.temp_allocator); + data, error := json.marshal(response, context.temp_allocator) - header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)); + header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)) if error != .None { - return false; + return false } if !write_sized(writer, transmute([]u8)header) { - return false; + return false } if !write_sized(writer, data) { - return false; + return false } - return true; + return true } send_error :: proc (response: ResponseMessageError, writer: ^Writer) -> bool { - data, error := json.marshal(response, context.temp_allocator); + data, error := json.marshal(response, context.temp_allocator) - header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)); + header := fmt.tprintf("Content-Length: %v\r\n\r\n", len(data)) if error != .None { - return false; + return false } if !write_sized(writer, transmute([]u8)header) { - return false; + return false } if !write_sized(writer, data) { - return false; + return false } - return true; + return true } diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin index c0a117f..bd89bb3 100644 --- a/src/server/semantic_tokens.odin +++ b/src/server/semantic_tokens.odin @@ -85,56 +85,56 @@ SemanticTokenBuilder :: struct { make_token_builder :: proc(allocator := context.temp_allocator) -> SemanticTokenBuilder { return { tokens = make([dynamic]u32, 1000, context.temp_allocator), - }; + } } get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens { return { data = builder.tokens[:], - }; + } } get_semantic_tokens :: proc(document: ^common.Document, range: common.Range, symbols: map[uintptr]index.Symbol) -> SemanticTokens { - using analysis; + using analysis - builder := make_token_builder(); + builder := make_token_builder() if document.ast.pkg_decl != nil { - write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None); + write_semantic_token(&builder, document.ast.pkg_token, document.ast.src, .Keyword, .None) } - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - builder.symbols = symbols; + builder.symbols = symbols - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package for decl in document.ast.decls { if range.start.line <= decl.pos.line && decl.end.line <= range.end.line { - visit(decl, &builder, &ast_context); + visit(decl, &builder, &ast_context) } } - return get_tokens(builder); + return get_tokens(builder) } write_semantic_node :: proc(builder: ^SemanticTokenBuilder, node: ^ast.Node, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) { - position := common.get_relative_token_position(node.pos.offset, transmute([]u8)src, builder.current_start); - name := common.get_ast_node_string(node, src); - append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier); - builder.current_start = node.pos.offset; + position := common.get_relative_token_position(node.pos.offset, transmute([]u8)src, builder.current_start) + name := common.get_ast_node_string(node, src) + append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier) + builder.current_start = node.pos.offset } write_semantic_token :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) { - position := common.get_relative_token_position(token.pos.offset, transmute([]u8)src, builder.current_start); - append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(token.text), cast(u32)type, cast(u32)modifier); - builder.current_start = token.pos.offset; + position := common.get_relative_token_position(token.pos.offset, transmute([]u8)src, builder.current_start) + append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(token.text), cast(u32)type, cast(u32)modifier) + builder.current_start = token.pos.offset } write_semantic_string :: proc(builder: ^SemanticTokenBuilder, pos: tokenizer.Pos, name: string, src: string, type: SemanticTokenTypes, modifier: SemanticTokenModifiers) { - position := common.get_relative_token_position(pos.offset, transmute([]u8)src, builder.current_start); - append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier); - builder.current_start = pos.offset; + position := common.get_relative_token_position(pos.offset, transmute([]u8)src, builder.current_start) + append(&builder.tokens, cast(u32)position.line, cast(u32)position.character, cast(u32)len(name), cast(u32)type, cast(u32)modifier) + builder.current_start = pos.offset } visit :: proc { @@ -142,207 +142,207 @@ visit :: proc { visit_dynamic_array, visit_array, visit_stmt, -}; +} visit_array :: proc(array: $A/[]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { for elem, i in array { - visit(elem, builder, ast_context); + visit(elem, builder, ast_context) } } visit_dynamic_array :: proc(array: $A/[dynamic]^$T, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { for elem, i in array { - visit(elem, builder, ast_context); + visit(elem, builder, ast_context) } } visit_stmt :: proc(node: ^ast.Stmt, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - visit_node(node, builder, ast_context); + visit_node(node, builder, ast_context) } visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using ast; + using ast if node == nil { - return; + return } - switch n in node.derived { - case Ellipsis: - write_semantic_string(builder, node.pos, "..", ast_context.file.src, .Operator, .None); - visit(n.expr, builder, ast_context); - case Ident: + #partial switch n in node.derived { + case ^Ellipsis: + write_semantic_string(builder, node.pos, "..", ast_context.file.src, .Operator, .None) + visit(n.expr, builder, ast_context) + case ^Ident: if symbol, ok := builder.symbols[cast(uintptr)node]; ok { if symbol.type == .Variable { - write_semantic_node(builder, node, ast_context.file.src, .Variable, .None); - return; + write_semantic_node(builder, node, ast_context.file.src, .Variable, .None) + return } #partial switch v in symbol.value { case index.SymbolPackageValue: - write_semantic_node(builder, node, ast_context.file.src, .Namespace, .None); + write_semantic_node(builder, node, ast_context.file.src, .Namespace, .None) case index.SymbolStructValue: - write_semantic_node(builder, node, ast_context.file.src, .Struct, .None); + write_semantic_node(builder, node, ast_context.file.src, .Struct, .None) case index.SymbolEnumValue: - write_semantic_node(builder, node, ast_context.file.src, .Enum, .None); + write_semantic_node(builder, node, ast_context.file.src, .Enum, .None) case index.SymbolUnionValue: - write_semantic_node(builder, node, ast_context.file.src, .Enum, .None); + write_semantic_node(builder, node, ast_context.file.src, .Enum, .None) case index.SymbolProcedureValue: - write_semantic_node(builder, node, ast_context.file.src, .Function, .None); + write_semantic_node(builder, node, ast_context.file.src, .Function, .None) case index.SymbolProcedureGroupValue: - write_semantic_node(builder, node, ast_context.file.src, .Function, .None); + write_semantic_node(builder, node, ast_context.file.src, .Function, .None) case index.SymbolUntypedValue: - write_semantic_node(builder, node, ast_context.file.src, .Type, .None); + write_semantic_node(builder, node, ast_context.file.src, .Type, .None) case index.SymbolBasicValue: - write_semantic_node(builder, node, ast_context.file.src, .Type, .None); + write_semantic_node(builder, node, ast_context.file.src, .Type, .None) case: //log.errorf("Unexpected symbol value: %v", symbol.value); //panic(fmt.tprintf("Unexpected symbol value: %v", symbol.value)); } } - case Selector_Expr: - visit_selector(cast(^Selector_Expr)node, builder, ast_context); - builder.selector = false; - case When_Stmt: - write_semantic_string(builder, n.when_pos, "when", ast_context.file.src, .Keyword, .None); - visit(n.cond, builder, ast_context); - visit(n.body, builder, ast_context); - visit(n.else_stmt, builder, ast_context); - case Pointer_Type: - write_semantic_string(builder, node.pos, "^", ast_context.file.src, .Operator, .None); - visit(n.elem, builder, ast_context); - case Value_Decl: - visit_value_decl(n, builder, ast_context); - case Block_Stmt: - visit(n.stmts, builder, ast_context); - case Expr_Stmt: - visit(n.expr, builder, ast_context); - case Branch_Stmt: - write_semantic_token(builder, n.tok, ast_context.file.src, .Type, .None); - case Poly_Type: - write_semantic_string(builder, n.dollar, "$", ast_context.file.src, .Operator, .None); - visit(n.type, builder, ast_context); - visit(n.specialization, builder, ast_context); - case Range_Stmt: - write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); + case ^Selector_Expr: + visit_selector(cast(^Selector_Expr)node, builder, ast_context) + builder.selector = false + case ^When_Stmt: + write_semantic_string(builder, n.when_pos, "when", ast_context.file.src, .Keyword, .None) + visit(n.cond, builder, ast_context) + visit(n.body, builder, ast_context) + visit(n.else_stmt, builder, ast_context) + case ^Pointer_Type: + write_semantic_string(builder, node.pos, "^", ast_context.file.src, .Operator, .None) + visit(n.elem, builder, ast_context) + case ^Value_Decl: + visit_value_decl(n^, builder, ast_context) + case ^Block_Stmt: + visit(n.stmts, builder, ast_context) + case ^Expr_Stmt: + visit(n.expr, builder, ast_context) + case ^Branch_Stmt: + write_semantic_token(builder, n.tok, ast_context.file.src, .Type, .None) + case ^Poly_Type: + write_semantic_string(builder, n.dollar, "$", ast_context.file.src, .Operator, .None) + visit(n.type, builder, ast_context) + visit(n.specialization, builder, ast_context) + case ^Range_Stmt: + write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None) for val in n.vals { - if ident, ok := val.derived.(Ident); ok { - write_semantic_node(builder, val, ast_context.file.src, .Variable, .None); + if ident, ok := val.derived.(^Ident); ok { + write_semantic_node(builder, val, ast_context.file.src, .Variable, .None) } } - write_semantic_string(builder, n.in_pos, "in", ast_context.file.src, .Keyword, .None); - visit(n.expr, builder, ast_context); - visit(n.body, builder, ast_context); - case If_Stmt: - write_semantic_string(builder, n.if_pos, "if", ast_context.file.src, .Keyword, .None); - visit(n.init, builder, ast_context); - visit(n.cond, builder, ast_context); - visit(n.body, builder, ast_context); + write_semantic_string(builder, n.in_pos, "in", ast_context.file.src, .Keyword, .None) + visit(n.expr, builder, ast_context) + visit(n.body, builder, ast_context) + case ^If_Stmt: + write_semantic_string(builder, n.if_pos, "if", ast_context.file.src, .Keyword, .None) + visit(n.init, builder, ast_context) + visit(n.cond, builder, ast_context) + visit(n.body, builder, ast_context) if n.else_stmt != nil { - write_semantic_string(builder, n.else_pos, "else", ast_context.file.src, .Keyword, .None); - visit(n.else_stmt, builder, ast_context); + write_semantic_string(builder, n.else_pos, "else", ast_context.file.src, .Keyword, .None) + visit(n.else_stmt, builder, ast_context) } - case For_Stmt: - write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None); - visit(n.init, builder, ast_context); - visit(n.cond, builder, ast_context); - visit(n.post, builder, ast_context); - visit(n.body, builder, ast_context); - case Switch_Stmt: - write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); - visit(n.init, builder, ast_context); - visit(n.cond, builder, ast_context); - visit(n.body, builder, ast_context); - case Type_Switch_Stmt: - write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None); - visit(n.tag, builder, ast_context); - visit(n.expr, builder, ast_context); - visit(n.body, builder, ast_context); - case Assign_Stmt: + case ^For_Stmt: + write_semantic_string(builder, n.for_pos, "for", ast_context.file.src, .Keyword, .None) + visit(n.init, builder, ast_context) + visit(n.cond, builder, ast_context) + visit(n.post, builder, ast_context) + visit(n.body, builder, ast_context) + case ^Switch_Stmt: + write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None) + visit(n.init, builder, ast_context) + visit(n.cond, builder, ast_context) + visit(n.body, builder, ast_context) + case ^Type_Switch_Stmt: + write_semantic_string(builder, n.switch_pos, "switch", ast_context.file.src, .Keyword, .None) + visit(n.tag, builder, ast_context) + visit(n.expr, builder, ast_context) + visit(n.body, builder, ast_context) + case ^Assign_Stmt: for l in n.lhs { - if ident, ok := l.derived.(Ident); ok { - write_semantic_node(builder, l, ast_context.file.src, .Variable, .None); + if ident, ok := l.derived.(^Ident); ok { + write_semantic_node(builder, l, ast_context.file.src, .Variable, .None) } else { - visit(l, builder, ast_context); + visit(l, builder, ast_context) } } - visit_token_op(builder, n.op, ast_context.file.src); - visit(n.rhs, builder, ast_context); - case Case_Clause: - write_semantic_string(builder, n.case_pos, "case", ast_context.file.src, .Keyword, .None); - visit(n.list, builder, ast_context); - visit(n.body, builder, ast_context); - case Call_Expr: - visit(n.expr, builder, ast_context); - visit(n.args, builder, ast_context); - case Implicit_Selector_Expr: - write_semantic_node(builder, n.field, ast_context.file.src, .Enum, .None); - case Array_Type: - visit(n.elem, builder, ast_context); - case Binary_Expr: - visit(n.left, builder, ast_context); - visit_token_op(builder, n.op, ast_context.file.src); - visit(n.right, builder, ast_context); - case Comp_Lit: - visit(n.type, builder, ast_context); - visit(n.elems, builder, ast_context); - case Struct_Type: - write_semantic_string(builder, n.pos, "struct", ast_context.file.src, .Keyword, .None); - visit_struct_fields(n, builder, ast_context); - case Type_Assertion: - visit(n.expr, builder, ast_context); - visit(n.type, builder, ast_context); - case Type_Cast: - write_semantic_string(builder, n.pos, "cast", ast_context.file.src, .Keyword, .None); - visit(n.type, builder, ast_context); - visit(n.expr, builder, ast_context); - case Paren_Expr: - visit(n.expr, builder, ast_context); - case Deref_Expr: - visit(n.expr, builder, ast_context); - case Return_Stmt: - write_semantic_string(builder, n.pos, "return", ast_context.file.src, .Keyword, .None); - visit(n.results, builder, ast_context); - case Dynamic_Array_Type: - write_semantic_string(builder, n.dynamic_pos, "dynamic", ast_context.file.src, .Keyword, .None); - visit(n.elem, builder, ast_context); - case Field_Value: - if ident, ok := n.field.derived.(Ident); ok { - write_semantic_node(builder, n.field, ast_context.file.src, .Property, .None); + visit_token_op(builder, n.op, ast_context.file.src) + visit(n.rhs, builder, ast_context) + case ^Case_Clause: + write_semantic_string(builder, n.case_pos, "case", ast_context.file.src, .Keyword, .None) + visit(n.list, builder, ast_context) + visit(n.body, builder, ast_context) + case ^Call_Expr: + visit(n.expr, builder, ast_context) + visit(n.args, builder, ast_context) + case ^Implicit_Selector_Expr: + write_semantic_node(builder, n.field, ast_context.file.src, .Enum, .None) + case ^Array_Type: + visit(n.elem, builder, ast_context) + case ^Binary_Expr: + visit(n.left, builder, ast_context) + visit_token_op(builder, n.op, ast_context.file.src) + visit(n.right, builder, ast_context) + case ^Comp_Lit: + visit(n.type, builder, ast_context) + visit(n.elems, builder, ast_context) + case ^Struct_Type: + write_semantic_string(builder, n.pos, "struct", ast_context.file.src, .Keyword, .None) + visit_struct_fields(n^, builder, ast_context) + case ^Type_Assertion: + visit(n.expr, builder, ast_context) + visit(n.type, builder, ast_context) + case ^Type_Cast: + write_semantic_string(builder, n.pos, "cast", ast_context.file.src, .Keyword, .None) + visit(n.type, builder, ast_context) + visit(n.expr, builder, ast_context) + case ^Paren_Expr: + visit(n.expr, builder, ast_context) + case ^Deref_Expr: + visit(n.expr, builder, ast_context) + case ^Return_Stmt: + write_semantic_string(builder, n.pos, "return", ast_context.file.src, .Keyword, .None) + visit(n.results, builder, ast_context) + case ^Dynamic_Array_Type: + write_semantic_string(builder, n.dynamic_pos, "dynamic", ast_context.file.src, .Keyword, .None) + visit(n.elem, builder, ast_context) + case ^Field_Value: + if ident, ok := n.field.derived.(^Ident); ok { + write_semantic_node(builder, n.field, ast_context.file.src, .Property, .None) } - visit(n.value, builder, ast_context); - case Index_Expr: - visit(n.expr, builder, ast_context); - visit(n.index, builder, ast_context); - case Basic_Lit: - visit_basic_lit(n, builder, ast_context); - case Unary_Expr: - visit(n.expr, builder, ast_context); - case Implicit: - case Slice_Expr: - visit(n.expr, builder, ast_context); - case Using_Stmt: - write_semantic_string(builder, n.pos, "using", ast_context.file.src, .Keyword, .None); - visit(n.list, builder, ast_context); - case Map_Type: - write_semantic_string(builder, n.tok_pos, "map", ast_context.file.src, .Keyword, .None); - visit(n.key, builder, ast_context); - visit(n.value, builder, ast_context); - case Defer_Stmt: - write_semantic_string(builder, n.pos, "defer", ast_context.file.src, .Keyword, .None); - visit(n.stmt, builder, ast_context); - case Import_Decl: - write_semantic_token(builder, n.import_tok, ast_context.file.src, .Keyword, .None); + visit(n.value, builder, ast_context) + case ^Index_Expr: + visit(n.expr, builder, ast_context) + visit(n.index, builder, ast_context) + case ^Basic_Lit: + visit_basic_lit(n^, builder, ast_context) + case ^Unary_Expr: + visit(n.expr, builder, ast_context) + case ^Implicit: + case ^Slice_Expr: + visit(n.expr, builder, ast_context) + case ^Using_Stmt: + write_semantic_string(builder, n.pos, "using", ast_context.file.src, .Keyword, .None) + visit(n.list, builder, ast_context) + case ^Map_Type: + write_semantic_string(builder, n.tok_pos, "map", ast_context.file.src, .Keyword, .None) + visit(n.key, builder, ast_context) + visit(n.value, builder, ast_context) + case ^Defer_Stmt: + write_semantic_string(builder, n.pos, "defer", ast_context.file.src, .Keyword, .None) + visit(n.stmt, builder, ast_context) + case ^Import_Decl: + write_semantic_token(builder, n.import_tok, ast_context.file.src, .Keyword, .None) if n.name.text != "" { - write_semantic_token(builder, n.name, ast_context.file.src, .Namespace, .None); + write_semantic_token(builder, n.name, ast_context.file.src, .Namespace, .None) } - write_semantic_token(builder, n.relpath, ast_context.file.src, .String, .None); + write_semantic_token(builder, n.relpath, ast_context.file.src, .String, .None) case: //log.errorf("unhandled semantic token node %v", n); //panic(fmt.tprintf("Missed semantic token handling %v", n)); @@ -350,179 +350,179 @@ visit_node :: proc(node: ^ast.Node, builder: ^SemanticTokenBuilder, ast_context: } visit_basic_lit :: proc(basic_lit: ast.Basic_Lit, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using analysis; + using analysis if symbol, ok := resolve_basic_lit(ast_context, basic_lit); ok { if untyped, ok := symbol.value.(index.SymbolUntypedValue); ok { switch untyped.type { case .Bool: - write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Keyword, .None); + write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Keyword, .None) case .Float, .Integer: - write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Number, .None); + write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .Number, .None) case .String: - write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .String, .None); + write_semantic_token(builder, basic_lit.tok, ast_context.file.src, .String, .None) } } } } visit_value_decl :: proc(value_decl: ast.Value_Decl, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using ast; + using ast if value_decl.type != nil { for name in value_decl.names { - write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None) } - visit(value_decl.type, builder, ast_context); + visit(value_decl.type, builder, ast_context) - return; + return } if len(value_decl.values) == 1 { - switch v in value_decl.values[0].derived { - case Union_Type: - write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None); - write_semantic_string(builder, v.pos, "union", ast_context.file.src, .Keyword, .None); - visit(v.variants, builder, ast_context); - case Struct_Type: - write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Struct, .None); - write_semantic_string(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None); - visit_struct_fields(v, builder, ast_context); - case Enum_Type: - write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None); - write_semantic_string(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None); - visit_enum_fields(v, builder, ast_context); - case Proc_Group: - write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None); - write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); + #partial switch v in value_decl.values[0].derived { + case ^Union_Type: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None) + write_semantic_string(builder, v.pos, "union", ast_context.file.src, .Keyword, .None) + visit(v.variants, builder, ast_context) + case ^Struct_Type: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Struct, .None) + write_semantic_string(builder, v.pos, "struct", ast_context.file.src, .Keyword, .None) + visit_struct_fields(v^, builder, ast_context) + case ^Enum_Type: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Enum, .None) + write_semantic_string(builder, v.pos, "enum", ast_context.file.src, .Keyword, .None) + visit_enum_fields(v^, builder, ast_context) + case ^Proc_Group: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None) + write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None) for arg in v.args { - if ident, ok := arg.derived.(Ident); ok { - write_semantic_node(builder, arg, ast_context.file.src, .Function, .None); + if ident, ok := arg.derived.(^Ident); ok { + write_semantic_node(builder, arg, ast_context.file.src, .Function, .None) } } - case Proc_Lit: - write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None); - write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None); - visit_proc_type(v.type, builder, ast_context); + case ^Proc_Lit: + write_semantic_node(builder, value_decl.names[0], ast_context.file.src, .Function, .None) + write_semantic_string(builder, v.pos, "proc", ast_context.file.src, .Keyword, .None) + visit_proc_type(v.type, builder, ast_context) - visit(v.body, builder, ast_context); + visit(v.body, builder, ast_context) case: for name in value_decl.names { - write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None) } - visit(value_decl.values[0], builder, ast_context); + visit(value_decl.values[0], builder, ast_context) } } else { for name in value_decl.names { - write_semantic_node(builder, name, ast_context.file.src, .Variable, .None); + write_semantic_node(builder, name, ast_context.file.src, .Variable, .None) } for value in value_decl.values { - visit(value, builder, ast_context); + visit(value, builder, ast_context) } } } visit_token_op :: proc(builder: ^SemanticTokenBuilder, token: tokenizer.Token, src: string) { if token.text == "in" { - write_semantic_string(builder, token.pos, token.text, src, .Keyword, .None); + write_semantic_string(builder, token.pos, token.text, src, .Keyword, .None) } else { - write_semantic_string(builder, token.pos, token.text, src, .Operator, .None); + write_semantic_string(builder, token.pos, token.text, src, .Operator, .None) } } visit_proc_type :: proc(node: ^ast.Proc_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using ast; + using ast if node == nil { - return; + return } if node.params != nil { for param in node.params.list { for name in param.names { - if ident, ok := name.derived.(Ident); ok { - write_semantic_node(builder, name, ast_context.file.src, .Parameter, .None); + if ident, ok := name.derived.(^Ident); ok { + write_semantic_node(builder, name, ast_context.file.src, .Parameter, .None) } } - visit(param.type, builder, ast_context); + visit(param.type, builder, ast_context) } } if node.results != nil { for result in node.results.list { - visit(result.names, builder, ast_context); - visit(result.type, builder, ast_context); + visit(result.names, builder, ast_context) + visit(result.type, builder, ast_context) } } } visit_enum_fields :: proc(node: ast.Enum_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using ast; + using ast if node.fields == nil { - return; + return } for field in node.fields { - if ident, ok := field.derived.(Ident); ok { - write_semantic_node(builder, field, ast_context.file.src, .EnumMember, .None); + if ident, ok := field.derived.(^Ident); ok { + write_semantic_node(builder, field, ast_context.file.src, .EnumMember, .None) } - else if f, ok := field.derived.(Field_Value); ok { - if _, ok := f.field.derived.(Ident); ok { - write_semantic_node(builder, f.field, ast_context.file.src, .EnumMember, .None); + else if f, ok := field.derived.(^Field_Value); ok { + if _, ok := f.field.derived.(^Ident); ok { + write_semantic_node(builder, f.field, ast_context.file.src, .EnumMember, .None) } - visit(f.value, builder, ast_context); + visit(f.value, builder, ast_context) } } } visit_struct_fields :: proc(node: ast.Struct_Type, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - using ast; + using ast if node.fields == nil { - return; + return } for field in node.fields.list { for name in field.names { - if ident, ok := name.derived.(Ident); ok { - write_semantic_node(builder, name, ast_context.file.src, .Property, .None); + if ident, ok := name.derived.(^Ident); ok { + write_semantic_node(builder, name, ast_context.file.src, .Property, .None) } } - visit(field.type, builder, ast_context); + visit(field.type, builder, ast_context) } } visit_selector :: proc(selector: ^ast.Selector_Expr, builder: ^SemanticTokenBuilder, ast_context: ^analysis.AstContext) { - if _, ok := selector.expr.derived.(ast.Selector_Expr); ok { - visit_selector(cast(^ast.Selector_Expr)selector.expr, builder, ast_context); + if _, ok := selector.expr.derived.(^ast.Selector_Expr); ok { + visit_selector(cast(^ast.Selector_Expr)selector.expr, builder, ast_context) } else { - visit(selector.expr, builder, ast_context); - builder.selector = true; + visit(selector.expr, builder, ast_context) + builder.selector = true } if symbol, ok := builder.symbols[cast(uintptr)selector]; ok { if symbol.type == .Variable { - write_semantic_node(builder, selector.field, ast_context.file.src, .Method, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Method, .None) } #partial switch v in symbol.value { case index.SymbolPackageValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Namespace, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Namespace, .None) case index.SymbolStructValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Struct, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Struct, .None) case index.SymbolEnumValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None) case index.SymbolUnionValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Enum, .None) case index.SymbolProcedureValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None) case index.SymbolProcedureGroupValue: - write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None); + write_semantic_node(builder, selector.field, ast_context.file.src, .Function, .None) } } } \ No newline at end of file diff --git a/src/server/signature.odin b/src/server/signature.odin index d187336..e8b3ae1 100644 --- a/src/server/signature.odin +++ b/src/server/signature.odin @@ -54,165 +54,165 @@ ParameterInformation :: struct { */ build_procedure_symbol_signature :: proc(symbol: ^index.Symbol) { if value, ok := symbol.value.(index.SymbolProcedureValue); ok { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) - strings.write_string(&builder, "proc"); - strings.write_string(&builder, "("); + strings.write_string(&builder, "proc") + strings.write_string(&builder, "(") for arg, i in value.arg_types { - strings.write_string(&builder, common.node_to_string(arg)); + strings.write_string(&builder, common.node_to_string(arg)) if i != len(value.arg_types) - 1 { - strings.write_string(&builder, ", "); + strings.write_string(&builder, ", ") } } - strings.write_string(&builder, ")"); + strings.write_string(&builder, ")") if len(value.return_types) != 0 { - strings.write_string(&builder, " -> "); + strings.write_string(&builder, " -> ") if len(value.return_types) > 1 { - strings.write_string(&builder, "("); + strings.write_string(&builder, "(") } for arg, i in value.return_types { - strings.write_string(&builder, common.node_to_string(arg)); + strings.write_string(&builder, common.node_to_string(arg)) if i != len(value.return_types) - 1 { - strings.write_string(&builder, ", "); + strings.write_string(&builder, ", ") } } if len(value.return_types) > 1 { - strings.write_string(&builder, ")"); + strings.write_string(&builder, ")") } } - symbol.signature = strings.to_string(builder); + symbol.signature = strings.to_string(builder) } else if value, ok := symbol.value.(index.SymbolAggregateValue); ok { - symbol.signature = "proc"; + symbol.signature = "proc" } } seperate_proc_field_arguments :: proc(procedure: ^index.Symbol) { if value, ok := &procedure.value.(index.SymbolProcedureValue); ok { - types := make([dynamic]^ast.Field, context.temp_allocator); + types := make([dynamic]^ast.Field, context.temp_allocator) for arg, i in value.arg_types { if len(arg.names) == 1 { - append(&types, arg); - continue; + append(&types, arg) + continue } for name in arg.names { - field : ^ast.Field = index.new_type(ast.Field, {}, {}, context.temp_allocator); - field.names = make([]^ast.Expr, 1, context.temp_allocator); - field.names[0] = name; - field.type = arg.type; - append(&types, field); + field : ^ast.Field = index.new_type(ast.Field, {}, {}, context.temp_allocator) + field.names = make([]^ast.Expr, 1, context.temp_allocator) + field.names[0] = name + field.type = arg.type + append(&types, field) } } - value.arg_types = types[:]; + value.arg_types = types[:] } } get_signature_information :: proc(document: ^common.Document, position: common.Position) -> (SignatureHelp, bool) { - using analysis; + using analysis - signature_help: SignatureHelp; + signature_help: SignatureHelp - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - position_context, ok := get_document_position_context(document, position, .SignatureHelp); + position_context, ok := get_document_position_context(document, position, .SignatureHelp) if !ok { - return signature_help, true; + return signature_help, true } //TODO(should probably not be an ast.Expr, but ast.Call_Expr) if position_context.call == nil { - return signature_help, true; + return signature_help, true } - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context) if position_context.function != nil { - get_locals(document.ast, position_context.function, &ast_context, &position_context); + get_locals(document.ast, position_context.function, &ast_context, &position_context) } for comma, i in position_context.call_commas { if position_context.position > comma { - signature_help.activeParameter = i+1; + signature_help.activeParameter = i+1 } else if position_context.position == comma { - signature_help.activeParameter = i; + signature_help.activeParameter = i } } - call: index.Symbol; - call, ok = resolve_type_expression(&ast_context, position_context.call); + call: index.Symbol + call, ok = resolve_type_expression(&ast_context, position_context.call) if !ok { - return signature_help, true; + return signature_help, true } - seperate_proc_field_arguments(&call); + seperate_proc_field_arguments(&call) - signature_information := make([dynamic]SignatureInformation, context.temp_allocator); + signature_information := make([dynamic]SignatureInformation, context.temp_allocator) if value, ok := call.value.(index.SymbolProcedureValue); ok { - parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator); + parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator) for arg, i in value.arg_types { if arg.type != nil { - if _, is_ellipsis := arg.type.derived.(ast.Ellipsis); is_ellipsis { - signature_help.activeParameter = min(i, signature_help.activeParameter); + if _, is_ellipsis := arg.type.derived.(^ast.Ellipsis); is_ellipsis { + signature_help.activeParameter = min(i, signature_help.activeParameter) } } - parameters[i].label = common.node_to_string(arg); + parameters[i].label = common.node_to_string(arg) } - build_procedure_symbol_signature(&call); + build_procedure_symbol_signature(&call) info := SignatureInformation { label = concatenate_symbol_information(&ast_context, call, false), documentation = call.doc, parameters = parameters, - }; - append(&signature_information, info); + } + append(&signature_information, info) } else if value, ok := call.value.(index.SymbolAggregateValue); ok { //function overloaded procedures for symbol in value.symbols { - symbol := symbol; + symbol := symbol if value, ok := symbol.value.(index.SymbolProcedureValue); ok { - parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator); + parameters := make([]ParameterInformation, len(value.arg_types), context.temp_allocator) for arg, i in value.arg_types { if arg.type != nil { - if _, is_ellipsis := arg.type.derived.(ast.Ellipsis); is_ellipsis { - signature_help.activeParameter = min(i, signature_help.activeParameter); + if _, is_ellipsis := arg.type.derived.(^ast.Ellipsis); is_ellipsis { + signature_help.activeParameter = min(i, signature_help.activeParameter) } } - parameters[i].label = common.node_to_string(arg); - parameters[i].activeParameter = i; + parameters[i].label = common.node_to_string(arg) + parameters[i].activeParameter = i } - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) info := SignatureInformation { label = concatenate_symbol_information(&ast_context, symbol, false), documentation = symbol.doc, parameters = parameters, - }; + } - append(&signature_information, info); + append(&signature_information, info) } } } - signature_help.signatures = signature_information[:]; + signature_help.signatures = signature_information[:] - return signature_help, true; + return signature_help, true } \ No newline at end of file diff --git a/src/server/unmarshal.odin b/src/server/unmarshal.odin index 0de3d53..c8a8071 100644 --- a/src/server/unmarshal.odin +++ b/src/server/unmarshal.odin @@ -12,33 +12,33 @@ import "core:fmt" unmarshal :: proc(json_value: json.Value, v: any, allocator: mem.Allocator) -> json.Marshal_Error { - using runtime; + using runtime if v == nil { - return .None; + return .None } if json_value == nil { - return .None; + return .None } - type_info := type_info_base(type_info_of(v.id)); + type_info := type_info_base(type_info_of(v.id)) #partial switch j in json_value { case json.Object: #partial switch variant in type_info.variant { case Type_Info_Struct: for field, i in variant.names { - a := any {rawptr(uintptr(v.data) + uintptr(variant.offsets[i])), variant.types[i].id}; + a := any {rawptr(uintptr(v.data) + uintptr(variant.offsets[i])), variant.types[i].id} //TEMP most likely have to rewrite the entire unmarshal using tags instead, because i sometimes have to support names like 'context', which can't be written like that if field[len(field)-1] == '_' { if ret := unmarshal(j[field[:len(field)-1]], a, allocator); ret != .None { - return ret; + return ret } } else { if ret := unmarshal(j[field], a, allocator); ret != .None { - return ret; + return ret } } @@ -50,59 +50,59 @@ unmarshal :: proc(json_value: json.Value, v: any, allocator: mem.Allocator) -> j //Note(Daniel, THIS IS REALLY SCUFFED. Need to talk to gingerbill about unmarshalling unions) //This only works for unions with one object - made to handle optionals - tag_ptr := uintptr(v.data) + variant.tag_offset; - tag_any := any {rawptr(tag_ptr), variant.tag_type.id}; + tag_ptr := uintptr(v.data) + variant.tag_offset + tag_any := any {rawptr(tag_ptr), variant.tag_type.id} - not_optional := 1; + not_optional := 1 - mem.copy(cast(rawptr)tag_ptr, ¬_optional, size_of(variant.tag_type)); + mem.copy(cast(rawptr)tag_ptr, ¬_optional, size_of(variant.tag_type)) - id := variant.variants[0].id; + id := variant.variants[0].id - unmarshal(json_value, any {v.data, id}, allocator); + unmarshal(json_value, any {v.data, id}, allocator) } case json.Array: #partial switch variant in type_info.variant { case Type_Info_Dynamic_Array: - array := (^mem.Raw_Dynamic_Array)(v.data); + array := (^mem.Raw_Dynamic_Array)(v.data) if array.data == nil { - array.data = mem.alloc(len(j) * variant.elem_size, variant.elem.align, allocator); - array.len = len(j); - array.cap = len(j); - array.allocator = allocator; + array.data = mem.alloc(len(j) * variant.elem_size, variant.elem.align, allocator) + array.len = len(j) + array.cap = len(j) + array.allocator = allocator } else { - return .Unsupported_Type; + return .Unsupported_Type } for i in 0.. j case Type_Info_Integer: switch type_info.size { case 8: - tmp := i64(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := i64(j) + mem.copy(v.data, &tmp, type_info.size) case 4: - tmp := i32(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := i32(j) + mem.copy(v.data, &tmp, type_info.size) case 2: - tmp := i16(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := i16(j) + mem.copy(v.data, &tmp, type_info.size) case 1: - tmp := i8(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := i8(j) + mem.copy(v.data, &tmp, type_info.size) case: - return .Unsupported_Type; + return .Unsupported_Type } case Type_Info_Union: - tag_ptr := uintptr(v.data) + variant.tag_offset; + tag_ptr := uintptr(v.data) + variant.tag_offset } case json.Float: if _, ok := type_info.variant.(Type_Info_Float); ok { switch type_info.size { case 8: - tmp := f64(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := f64(j) + mem.copy(v.data, &tmp, type_info.size) case 4: - tmp := f32(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := f32(j) + mem.copy(v.data, &tmp, type_info.size) case: - return .Unsupported_Type; + return .Unsupported_Type } } case json.Null: case json.Boolean: if _, ok := type_info.variant.(Type_Info_Boolean); ok { - tmp := bool(j); - mem.copy(v.data, &tmp, type_info.size); + tmp := bool(j) + mem.copy(v.data, &tmp, type_info.size) } case: - return .Unsupported_Type; + return .Unsupported_Type } - return .None; + return .None } diff --git a/src/server/writer.odin b/src/server/writer.odin index 46a340e..4918f81 100644 --- a/src/server/writer.odin +++ b/src/server/writer.odin @@ -6,7 +6,7 @@ import "core:fmt" import "core:strings" import "core:sync" -WriterFn :: proc(_: rawptr, _: []byte) -> (int, int); +WriterFn :: proc(_: rawptr, _: []byte) -> (int, int) Writer :: struct { writer_fn: WriterFn, @@ -15,21 +15,21 @@ Writer :: struct { } make_writer :: proc(writer_fn: WriterFn, writer_context: rawptr) -> Writer { - writer := Writer {writer_context = writer_context, writer_fn = writer_fn}; - sync.mutex_init(&writer.writer_mutex); - return writer; + writer := Writer {writer_context = writer_context, writer_fn = writer_fn} + sync.mutex_init(&writer.writer_mutex) + return writer } write_sized :: proc(writer: ^Writer, data: []byte) -> bool { - sync.mutex_lock(&writer.writer_mutex); - defer sync.mutex_unlock(&writer.writer_mutex); + sync.mutex_lock(&writer.writer_mutex) + defer sync.mutex_unlock(&writer.writer_mutex) - written, err := writer.writer_fn(writer.writer_context, data); + written, err := writer.writer_fn(writer.writer_context, data) if (err != 0) { - return false; + return false } - return true; + return true } diff --git a/src/testing/testing.odin b/src/testing/testing.odin index 4a40f16..d6c01c8 100644 --- a/src/testing/testing.odin +++ b/src/testing/testing.odin @@ -38,7 +38,7 @@ setup :: proc(src: ^Source) { src.document.allocator = new(common.Scratch_Allocator); src.document.package_name = "test"; - common.scratch_allocator_init(src.document.allocator, mem.kilobytes(20), context.temp_allocator); + common.scratch_allocator_init(src.document.allocator, mem.kilobytes(200), context.temp_allocator); //no unicode in tests currently current, last: u8; @@ -111,7 +111,7 @@ setup :: proc(src: ^Source) { if !ok || file.syntax_error_count > 0 { panic("Parser error in test package source"); } - + if ret := index.collect_symbols(&index.indexer.static_index.collection, file, uri.uri); ret != .None { return; } -- cgit v1.2.3