aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorBradley Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-02 12:34:25 -0400
committerGitHub <noreply@github.com>2025-08-02 12:34:25 -0400
commit9f72598068b5dfb2f70cfccc935ec56f537230d2 (patch)
tree7d05917f1e5c856044a9f04e07e7236daee676c7 /src/server
parent5d1bf18bb5e0494759fce01490fe02b802c26561 (diff)
parentf770f22960041c74347d2f96247c6d8bf8194d57 (diff)
Merge pull request #817 from BradLewis/fix/resolve-procs-that-return-procs-called-immediately
Fix/resolve procs that return procs called immediately
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin679
1 files changed, 377 insertions, 302 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 6464d2b..5949077 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1102,39 +1102,7 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex
ident.name = v.tok.text
return internal_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 := internal_resolve_type_expression(ast_context, v.expr); ok {
- //To handle type assertions for unions, i.e. my_maybe_variable.?
- if union_value, ok := symbol.value.(SymbolUnionValue); ok {
- if len(union_value.types) != 1 {
- return {}, false
- }
- return internal_resolve_type_expression(ast_context, union_value.types[0])
- } else if proc_value, ok := symbol.value.(SymbolProcedureValue); ok {
- //To handle type assertions for unions returned from procedures, i.e: my_function().?
- if len(proc_value.return_types) != 1 || proc_value.return_types[0].type == nil {
- return {}, false
- }
-
- if symbol, ok := internal_resolve_type_expression(
- ast_context,
- proc_value.return_types[0].type,
- ); ok {
- if union_value, ok := symbol.value.(SymbolUnionValue); ok {
- if len(union_value.types) != 1 {
- return {}, false
- }
- return internal_resolve_type_expression(ast_context, union_value.types[0])
- }
- }
- }
-
- }
- }
- } else {
- return internal_resolve_type_expression(ast_context, v.type)
- }
+ return resolve_type_assertion_expr(ast_context, v)
case ^Proc_Lit:
if v.type.results != nil {
if len(v.type.results.list) > 0 {
@@ -1152,33 +1120,7 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex
}
}
case ^Index_Expr:
- indexed, ok := internal_resolve_type_expression(ast_context, v.expr)
-
- if !ok {
- return {}, false
- }
-
- set_ast_package_set_scoped(ast_context, indexed.pkg)
-
- symbol: Symbol
-
- #partial switch v2 in indexed.value {
- case SymbolDynamicArrayValue:
- symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
- case SymbolSliceValue:
- symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
- case SymbolFixedArrayValue:
- symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
- case SymbolMapValue:
- symbol, ok = internal_resolve_type_expression(ast_context, v2.value)
- case SymbolMultiPointerValue:
- symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
- }
-
-
- symbol.type = indexed.type
-
- return symbol, ok
+ return resolve_index_expr(ast_context, v)
case ^Call_Expr:
old_call := ast_context.call
ast_context.call = cast(^Call_Expr)node
@@ -1186,31 +1128,9 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex
defer {
ast_context.call = old_call
}
-
- if ident, ok := v.expr.derived.(^ast.Ident); ok && len(v.args) >= 1 {
- switch ident.name {
- case "type_of":
- ast_context.call = nil
- return internal_resolve_type_expression(ast_context, v.args[0])
- }
- }
-
- return internal_resolve_type_expression(ast_context, v.expr)
+ return resolve_call_expr(ast_context, v)
case ^Selector_Call_Expr:
- if selector, ok := internal_resolve_type_expression(ast_context, v.expr); ok {
- ast_context.use_locals = false
-
- set_ast_package_from_symbol_scoped(ast_context, selector)
-
- #partial switch s in selector.value {
- case SymbolProcedureValue:
- if len(s.return_types) == 1 {
- return internal_resolve_type_expression(ast_context, s.return_types[0].type)
- }
- }
-
- return selector, true
- }
+ return resolve_selector_call_expr(ast_context, v)
case ^Selector_Expr:
return resolve_selector_expression(ast_context, v)
case ^ast.Poly_Type:
@@ -1225,6 +1145,113 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex
return Symbol{}, false
}
+resolve_call_expr :: proc(ast_context: ^AstContext, v: ^ast.Call_Expr) -> (Symbol, bool) {
+ if ident, ok := v.expr.derived.(^ast.Ident); ok && len(v.args) >= 1 {
+ switch ident.name {
+ case "type_of":
+ ast_context.call = nil
+ return internal_resolve_type_expression(ast_context, v.args[0])
+ }
+ } else if call, ok := v.expr.derived.(^ast.Call_Expr); ok {
+ // handle the case where we immediately call a proc returned by another proc
+ if symbol, ok := internal_resolve_type_expression(ast_context, v.expr); ok {
+ if value, ok := symbol.value.(SymbolProcedureValue); ok {
+ if len(value.return_types) == 1 {
+ return internal_resolve_type_expression(ast_context, value.return_types[0].type)
+ }
+ }
+ return symbol, ok
+ } else {
+ return {}, false
+ }
+ }
+
+ return internal_resolve_type_expression(ast_context, v.expr)
+}
+
+resolve_index_expr :: proc(ast_context: ^AstContext, v: ^ast.Index_Expr) -> (Symbol, bool) {
+ indexed, ok := internal_resolve_type_expression(ast_context, v.expr)
+
+ if !ok {
+ return {}, false
+ }
+
+ set_ast_package_set_scoped(ast_context, indexed.pkg)
+
+ symbol: Symbol
+
+ #partial switch v2 in indexed.value {
+ case SymbolDynamicArrayValue:
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
+ case SymbolSliceValue:
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
+ case SymbolFixedArrayValue:
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
+ case SymbolMapValue:
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.value)
+ case SymbolMultiPointerValue:
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
+ }
+
+
+ symbol.type = indexed.type
+
+ return symbol, ok
+}
+
+resolve_selector_call_expr :: proc(ast_context: ^AstContext, v: ^ast.Selector_Call_Expr) -> (Symbol, bool) {
+ if selector, ok := internal_resolve_type_expression(ast_context, v.expr); ok {
+ ast_context.use_locals = false
+
+ set_ast_package_from_symbol_scoped(ast_context, selector)
+
+ #partial switch s in selector.value {
+ case SymbolProcedureValue:
+ if len(s.return_types) == 1 {
+ return internal_resolve_type_expression(ast_context, s.return_types[0].type)
+ }
+ }
+
+ return selector, true
+ }
+ return {}, false
+}
+
+resolve_type_assertion_expr :: proc(ast_context: ^AstContext, v: ^ast.Type_Assertion) -> (Symbol, bool) {
+ if unary, ok := v.type.derived.(^ast.Unary_Expr); ok {
+ if unary.op.kind == .Question {
+ if symbol, ok := internal_resolve_type_expression(ast_context, v.expr); ok {
+ //To handle type assertions for unions, i.e. my_maybe_variable.?
+ if union_value, ok := symbol.value.(SymbolUnionValue); ok {
+ if len(union_value.types) != 1 {
+ return {}, false
+ }
+ return internal_resolve_type_expression(ast_context, union_value.types[0])
+ } else if proc_value, ok := symbol.value.(SymbolProcedureValue); ok {
+ //To handle type assertions for unions returned from procedures, i.e: my_function().?
+ if len(proc_value.return_types) != 1 || proc_value.return_types[0].type == nil {
+ return {}, false
+ }
+
+ if symbol, ok := internal_resolve_type_expression(
+ ast_context,
+ proc_value.return_types[0].type,
+ ); ok {
+ if union_value, ok := symbol.value.(SymbolUnionValue); ok {
+ if len(union_value.types) != 1 {
+ return {}, false
+ }
+ return internal_resolve_type_expression(ast_context, union_value.types[0])
+ }
+ }
+ }
+
+ }
+ }
+ }
+ return internal_resolve_type_expression(ast_context, v.type)
+}
+
resolve_selector_expression :: proc(ast_context: ^AstContext, node: ^ast.Selector_Expr) -> (Symbol, bool) {
if selector, ok := internal_resolve_type_expression(ast_context, node.expr); ok {
ast_context.use_locals = false
@@ -1430,7 +1457,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (S
return internal_resolve_type_identifier(ast_context, node)
}
-internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (_symbol: Symbol, _ok: bool) {
+internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (Symbol, bool) {
using ast
if check_node_recursion(ast_context, node.derived.(^ast.Ident)) {
@@ -1478,109 +1505,7 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide
}
if local, ok := get_local(ast_context^, node); ok && (ast_context.use_locals || local.local_global) {
- is_distinct := false
-
- if local.parameter {
- for imp in ast_context.imports {
- if strings.compare(imp.base, node.name) == 0 {
- symbol := Symbol {
- type = .Package,
- pkg = imp.name,
- value = SymbolPackageValue{},
- }
-
- return symbol, true
- }
- }
- }
-
- if local.pkg != "" {
- ast_context.current_package = local.pkg
- }
-
- //Sometimes the locals are semi resolved and can no longer use the locals
- if local.resolved_global {
- ast_context.use_locals = false
- }
-
- if dist, ok := local.rhs.derived.(^ast.Distinct_Type); ok {
- if dist.type != nil {
- local.rhs = dist.type
- is_distinct = true
- }
- }
-
- return_symbol: Symbol
- ok: bool
-
- #partial switch v in local.rhs.derived {
- case ^Ident:
- return_symbol, ok = internal_resolve_type_identifier(ast_context, v^)
- case ^Union_Type:
- return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Enum_Type:
- return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Struct_Type:
- return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node, {}), true
- return_symbol.name = node.name
- case ^Bit_Set_Type:
- return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Bit_Field_Type:
- return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true
- return_symbol.name = node.name
- case ^Proc_Lit:
- if is_procedure_generic(v.type) {
- return_symbol, ok = resolve_generic_function(ast_context, v^)
-
- if !ok && !ast_context.overloading {
- return_symbol, ok =
- make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node, {}, false, v.inlining),
- true
- }
- } else {
- return_symbol, ok =
- make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node, {}, false, v.inlining), 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^, node), true
- case ^Dynamic_Array_Type:
- return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
- case ^Matrix_Type:
- return_symbol, ok = make_symbol_matrix_from_ast(ast_context, v^, node), true
- case ^Map_Type:
- return_symbol, ok = make_symbol_map_from_ast(ast_context, v^, node), true
- case ^Basic_Lit:
- return_symbol, ok = resolve_basic_lit(ast_context, v^)
- return_symbol.name = node.name
- return_symbol.type = local.variable ? .Variable : .Constant
- case ^ast.Binary_Expr:
- return_symbol, ok = resolve_binary_expression(ast_context, v)
- case:
- return_symbol, ok = internal_resolve_type_expression(ast_context, local.rhs)
- }
-
- if is_distinct {
- return_symbol.name = node.name
- return_symbol.flags |= {.Distinct}
- }
-
- if local.parameter {
- return_symbol.flags |= {.Parameter}
- }
-
- if local.variable {
- return_symbol.type = .Variable
- }
-
- return_symbol.flags |= {.Local}
-
- return return_symbol, ok
-
+ return resolve_local_identifier(ast_context, node, &local)
}
for imp in ast_context.imports {
@@ -1614,120 +1539,7 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide
if global, ok := ast_context.globals[node.name];
ast_context.current_package == ast_context.document_package && ok {
- is_distinct := false
- ast_context.use_locals = false
-
- if dist, ok := global.expr.derived.(^ast.Distinct_Type); ok {
- if dist.type != nil {
- global.expr = dist.type
- is_distinct = true
- }
- }
-
- return_symbol: Symbol
- ok: bool
-
- #partial switch v in global.expr.derived {
- case ^Ident:
- return_symbol, ok = internal_resolve_type_identifier(ast_context, v^)
- case ^ast.Call_Expr:
- old_call := ast_context.call
- ast_context.call = cast(^Call_Expr)global.expr
-
- defer {
- ast_context.call = old_call
- }
-
- if return_symbol, ok = internal_resolve_type_expression(ast_context, v.expr); ok {
- return_types := get_proc_return_types(ast_context, return_symbol, v, global.mutable)
- if len(return_types) > 0 {
- return_symbol, ok = internal_resolve_type_expression(ast_context, return_types[0])
- }
- // Otherwise should be a parapoly style
- }
-
- case ^Struct_Type:
- return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node, global.attributes), true
- return_symbol.name = node.name
- case ^Bit_Set_Type:
- return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Union_Type:
- return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Enum_Type:
- return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node), true
- return_symbol.name = node.name
- case ^Bit_Field_Type:
- return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true
- return_symbol.name = node.name
- case ^Proc_Lit:
- if is_procedure_generic(v.type) {
- return_symbol, ok = resolve_generic_function(ast_context, v^)
-
- //If we are not overloading just show the unresolved generic function
- if !ok && !ast_context.overloading {
- return_symbol, ok =
- make_symbol_procedure_from_ast(
- ast_context,
- global.expr,
- v.type^,
- node,
- global.attributes,
- false,
- v.inlining,
- ),
- true
- }
- } else {
- return_symbol, ok =
- make_symbol_procedure_from_ast(
- ast_context,
- global.expr,
- v.type^,
- node,
- global.attributes,
- false,
- v.inlining,
- ),
- 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^, node), true
- case ^Dynamic_Array_Type:
- return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
- case ^Matrix_Type:
- return_symbol, ok = make_symbol_matrix_from_ast(ast_context, v^, node), true
- case ^Map_Type:
- return_symbol, ok = make_symbol_map_from_ast(ast_context, v^, node), 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 = internal_resolve_type_expression(ast_context, global.expr)
- }
-
- if is_distinct {
- return_symbol.name = node.name
- return_symbol.flags |= {.Distinct}
- }
-
- if global.mutable {
- return_symbol.type = .Variable
- }
-
- if global.docs != nil {
- return_symbol.doc = get_doc(global.docs, ast_context.allocator)
- }
-
- if global.comment != nil {
- return_symbol.comment = get_comment(global.comment)
- }
-
- return return_symbol, ok
+ return resolve_global_identifier(ast_context, node, &global)
} else {
switch node.name {
case "context":
@@ -1792,6 +1604,228 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide
return Symbol{}, false
}
+resolve_local_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, local: ^DocumentLocal) -> (Symbol, bool) {
+ is_distinct := false
+
+ if local.parameter {
+ for imp in ast_context.imports {
+ if strings.compare(imp.base, node.name) == 0 {
+ symbol := Symbol {
+ type = .Package,
+ pkg = imp.name,
+ value = SymbolPackageValue{},
+ }
+
+ return symbol, true
+ }
+ }
+ }
+
+ if local.pkg != "" {
+ ast_context.current_package = local.pkg
+ }
+
+ //Sometimes the locals are semi resolved and can no longer use the locals
+ if local.resolved_global {
+ ast_context.use_locals = false
+ }
+
+ if dist, ok := local.rhs.derived.(^ast.Distinct_Type); ok {
+ if dist.type != nil {
+ local.rhs = dist.type
+ is_distinct = true
+ }
+ }
+
+ return_symbol: Symbol
+ ok: bool
+
+ #partial switch v in local.rhs.derived {
+ case ^ast.Ident:
+ return_symbol, ok = internal_resolve_type_identifier(ast_context, v^)
+ case ^ast.Union_Type:
+ return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Enum_Type:
+ return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Struct_Type:
+ return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node, {}), true
+ return_symbol.name = node.name
+ case ^ast.Bit_Set_Type:
+ return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Bit_Field_Type:
+ return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true
+ return_symbol.name = node.name
+ case ^ast.Proc_Lit:
+ if is_procedure_generic(v.type) {
+ return_symbol, ok = resolve_generic_function(ast_context, v^)
+
+ if !ok && !ast_context.overloading {
+ return_symbol, ok =
+ make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node, {}, false, v.inlining),
+ true
+ }
+ } else {
+ return_symbol, ok =
+ make_symbol_procedure_from_ast(ast_context, local.rhs, v.type^, node, {}, false, v.inlining), true
+ }
+ case ^ast.Proc_Group:
+ return_symbol, ok = resolve_function_overload(ast_context, v^)
+ case ^ast.Array_Type:
+ return_symbol, ok = make_symbol_array_from_ast(ast_context, v^, node), true
+ case ^ast.Dynamic_Array_Type:
+ return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
+ case ^ast.Matrix_Type:
+ return_symbol, ok = make_symbol_matrix_from_ast(ast_context, v^, node), true
+ case ^ast.Map_Type:
+ return_symbol, ok = make_symbol_map_from_ast(ast_context, v^, node), true
+ case ^ast.Basic_Lit:
+ return_symbol, ok = resolve_basic_lit(ast_context, v^)
+ return_symbol.name = node.name
+ return_symbol.type = local.variable ? .Variable : .Constant
+ case ^ast.Binary_Expr:
+ return_symbol, ok = resolve_binary_expression(ast_context, v)
+ case:
+ return_symbol, ok = internal_resolve_type_expression(ast_context, local.rhs)
+ }
+
+ if is_distinct {
+ return_symbol.name = node.name
+ return_symbol.flags |= {.Distinct}
+ }
+
+ if local.parameter {
+ return_symbol.flags |= {.Parameter}
+ }
+
+ if local.variable {
+ return_symbol.type = .Variable
+ }
+
+ return_symbol.flags |= {.Local}
+
+ return return_symbol, ok
+}
+
+resolve_global_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, global: ^GlobalExpr) -> (Symbol, bool) {
+ is_distinct := false
+ ast_context.use_locals = false
+
+ if dist, ok := global.expr.derived.(^ast.Distinct_Type); ok {
+ if dist.type != nil {
+ global.expr = dist.type
+ is_distinct = true
+ }
+ }
+
+ return_symbol: Symbol
+ ok: bool
+
+ #partial switch v in global.expr.derived {
+ case ^ast.Ident:
+ return_symbol, ok = internal_resolve_type_identifier(ast_context, v^)
+ case ^ast.Call_Expr:
+ old_call := ast_context.call
+ ast_context.call = cast(^ast.Call_Expr)global.expr
+
+ defer {
+ ast_context.call = old_call
+ }
+
+ if return_symbol, ok = internal_resolve_type_expression(ast_context, v.expr); ok {
+ return_types := get_proc_return_types(ast_context, return_symbol, v, global.mutable)
+ if len(return_types) > 0 {
+ return_symbol, ok = internal_resolve_type_expression(ast_context, return_types[0])
+ }
+ // Otherwise should be a parapoly style
+ }
+
+ case ^ast.Struct_Type:
+ return_symbol, ok = make_symbol_struct_from_ast(ast_context, v, node, global.attributes), true
+ return_symbol.name = node.name
+ case ^ast.Bit_Set_Type:
+ return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Union_Type:
+ return_symbol, ok = make_symbol_union_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Enum_Type:
+ return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node), true
+ return_symbol.name = node.name
+ case ^ast.Bit_Field_Type:
+ return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true
+ return_symbol.name = node.name
+ case ^ast.Proc_Lit:
+ if is_procedure_generic(v.type) {
+ return_symbol, ok = resolve_generic_function(ast_context, v^)
+
+ //If we are not overloading just show the unresolved generic function
+ if !ok && !ast_context.overloading {
+ return_symbol, ok =
+ make_symbol_procedure_from_ast(
+ ast_context,
+ global.expr,
+ v.type^,
+ node,
+ global.attributes,
+ false,
+ v.inlining,
+ ),
+ true
+ }
+ } else {
+ return_symbol, ok =
+ make_symbol_procedure_from_ast(
+ ast_context,
+ global.expr,
+ v.type^,
+ node,
+ global.attributes,
+ false,
+ v.inlining,
+ ),
+ true
+ }
+ case ^ast.Proc_Group:
+ return_symbol, ok = resolve_function_overload(ast_context, v^)
+ case ^ast.Array_Type:
+ return_symbol, ok = make_symbol_array_from_ast(ast_context, v^, node), true
+ case ^ast.Dynamic_Array_Type:
+ return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
+ case ^ast.Matrix_Type:
+ return_symbol, ok = make_symbol_matrix_from_ast(ast_context, v^, node), true
+ case ^ast.Map_Type:
+ return_symbol, ok = make_symbol_map_from_ast(ast_context, v^, node), true
+ case ^ast.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 = internal_resolve_type_expression(ast_context, global.expr)
+ }
+
+ if is_distinct {
+ return_symbol.name = node.name
+ return_symbol.flags |= {.Distinct}
+ }
+
+ if global.mutable {
+ return_symbol.type = .Variable
+ }
+
+ if global.docs != nil {
+ return_symbol.doc = get_doc(global.docs, ast_context.allocator)
+ }
+
+ if global.comment != nil {
+ return_symbol.comment = get_comment(global.comment)
+ }
+
+ return return_symbol, ok
+}
+
struct_type_from_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (^ast.Struct_Type, bool) {
if check_node_recursion(ast_context, node.derived.(^ast.Ident)) {
return {}, false
@@ -3255,6 +3289,47 @@ get_generic_assignment :: proc(
}
}
+ // If we have a call expr followed immediately by another call expr, we want to return value
+ // of the second call. Eg a := foo()()
+ if _, ok := v.expr.derived.(^Call_Expr); ok {
+ if symbol, ok := internal_resolve_type_expression(ast_context, v.expr); ok {
+ if value, ok := symbol.value.(SymbolProcedureValue); ok {
+ if len(value.return_types) == 1 {
+ if proc_type, ok := value.return_types[0].type.derived.(^Proc_Type); ok {
+ for return_item in proc_type.results.list {
+ get_generic_assignment(
+ file,
+ return_item.type,
+ ast_context,
+ results,
+ calls,
+ flags,
+ is_mutable,
+ )
+ }
+ return
+ } else if ident, ok := value.return_types[0].type.derived.(^ast.Ident); ok {
+ if symbol, ok := internal_resolve_type_expression(ast_context, ident); ok {
+ if value, ok := symbol.value.(SymbolProcedureValue); ok {
+ for return_item in value.return_types {
+ get_generic_assignment(
+ file,
+ return_item.type,
+ ast_context,
+ results,
+ calls,
+ flags,
+ is_mutable,
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
//We have to resolve early and can't rely on lazy evalutation because it can have multiple returns.
if symbol, ok := resolve_type_expression(ast_context, v.expr); ok {
#partial switch symbol_value in symbol.value {