aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-07-20 19:03:08 +0200
committerGitHub <noreply@github.com>2025-07-20 19:03:08 +0200
commit4aed6e6c7e5e1a9cf556be9dbc0687f154aa61c8 (patch)
tree422bf7e8580ceff46c8696263b482c6f51e96504 /src
parentf76edb9e86d1e529a20a81a0ffaa4b8192751737 (diff)
parent931bb7c892f9d672addc8b29c5e8e03f20607d7f (diff)
Merge pull request #764 from BradLewis/fix/overload-proc-union
Overload proc resolving improvements
Diffstat (limited to 'src')
-rw-r--r--src/server/analysis.odin96
1 files changed, 80 insertions, 16 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 9162856..ab1860d 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -659,6 +659,25 @@ get_unnamed_arg_count :: proc(args: []^ast.Expr) -> int {
return total
}
+Candidate :: struct {
+ symbol: Symbol,
+ score: int,
+}
+
+get_top_candiate :: proc(candidates: []Candidate) -> (Candidate, bool) {
+ if len(candidates) == 0 {
+ return {}, false
+ }
+
+ top := candidates[0]
+ for candidate in candidates {
+ if candidate.score < top.score {
+ top = candidate
+ }
+ }
+ return top, true
+}
+
/*
Figure out which function the call expression is using out of the list from proc group
*/
@@ -684,12 +703,16 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
call_unnamed_arg_count = get_unnamed_arg_count(call_expr.args)
}
- candidates := make([dynamic]Symbol, context.temp_allocator)
+ candidates := make([dynamic]Candidate, context.temp_allocator)
for arg_expr in group.args {
next_fn: if f, ok := internal_resolve_type_expression(ast_context, arg_expr); ok {
+ candidate := Candidate{
+ symbol = f,
+ score = 1,
+ }
if call_expr == nil || (resolve_all_possibilities && len(call_expr.args) == 0) {
- append(&candidates, f)
+ append(&candidates, candidate)
break next_fn
}
if procedure, ok := f.value.(SymbolProcedureValue); ok {
@@ -772,35 +795,76 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
if !ok {
break next_fn
}
-
+
if !is_symbol_same_typed(ast_context, call_symbol, arg_symbol, proc_arg.flags) {
- break next_fn
+ found := false
+ // Are we a union variant
+ if value, ok := arg_symbol.value.(SymbolUnionValue); ok {
+ for variant in value.types {
+ if symbol, ok := resolve_type_expression(ast_context, variant); ok {
+ if is_symbol_same_typed(ast_context, call_symbol, symbol, proc_arg.flags) {
+ // matching union types are a low priority
+ candidate.score = 1000000
+ found = true
+ break
+ }
+ }
+ }
+ }
+
+ // Do we contain a using that matches
+ if value, ok := call_symbol.value.(SymbolStructValue); ok {
+ using_score := 1000000
+ for k in value.usings {
+ if symbol, ok := resolve_type_expression(ast_context, value.types[k]); ok {
+ symbol.pointers = call_symbol.pointers
+ if is_symbol_same_typed(ast_context, symbol, arg_symbol, proc_arg.flags) {
+ if k < using_score {
+ using_score = k
+ }
+ found = true
+ }
+ }
+ }
+ candidate.score = using_score
+ }
+
+ if !found {
+ break next_fn
+ }
}
i += 1
}
}
- append(&candidates, f)
+ append(&candidates, candidate)
}
}
}
- if len(candidates) > 0 && !resolve_all_possibilities {
- return candidates[0], true
- } else if len(candidates) > 1 {
- return Symbol {
- type = candidates[0].type,
- name = candidates[0].name,
- pkg = candidates[0].pkg,
- uri = candidates[0].uri,
- value = SymbolAggregateValue{symbols = candidates[:]},
+ if candidate, ok := get_top_candiate(candidates[:]); ok {
+ if !resolve_all_possibilities {
+ return candidate.symbol, true
+ } else if len(candidates) > 1 {
+ symbols := make([dynamic]Symbol, context.temp_allocator)
+ for c in candidates {
+ append(&symbols, c.symbol)
+ }
+ return Symbol {
+ type = candidate.symbol.type,
+ name = candidate.symbol.name,
+ pkg = candidate.symbol.pkg,
+ uri = candidate.symbol.uri,
+ value = SymbolAggregateValue{symbols = symbols[:]},
},
true
- } else if len(candidates) == 1 {
- return candidates[0], true
+ } else if len(candidates) == 1 {
+ return candidate.symbol, true
+ }
}
+
return Symbol{}, false
}