diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-30 16:26:45 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-30 16:29:57 -0400 |
| commit | 27e2caa6363f9afa6910930fbaf4c00aa67dfbfb (patch) | |
| tree | e1fa6e62e5f02d01e9c2894714f4fa7fea805c0f /src/server/analysis.odin | |
| parent | 0e4157ebfd357e5fdb181408185cca42dcd24047 (diff) | |
Improve builtin proc resolution, complex and quaternion procs and add missing basic type keywords
Diffstat (limited to 'src/server/analysis.odin')
| -rw-r--r-- | src/server/analysis.odin | 132 |
1 files changed, 4 insertions, 128 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 81fe560..06fc81c 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -373,7 +373,7 @@ are_symbol_untyped_basic_same_typed :: proc(a, b: Symbol) -> (bool, bool) { } case .Bool: switch basic.ident.name { - case "bool", "b32", "b64": + case "bool", "b8", "b16", "b32", "b64": return true, true case: return false, true @@ -387,7 +387,7 @@ are_symbol_untyped_basic_same_typed :: proc(a, b: Symbol) -> (bool, bool) { } case .Float: switch basic.ident.name { - case "f32", "f64": + case "f16", "f32", "f64": return true, true case: return false, true @@ -928,7 +928,8 @@ get_proc_return_types :: proc( is_mutable: bool, ) -> []^ast.Expr { return_types := make([dynamic]^ast.Expr, context.temp_allocator) - if ret, ok := check_builtin_proc_return_type(symbol, call, is_mutable); ok { + if ret, ok := check_builtin_proc_return_type(ast_context, symbol, call, is_mutable); ok { + appended := false if call, ok := ret.derived.(^ast.Call_Expr); ok { if symbol, ok := internal_resolve_type_expression(ast_context, call.expr); ok { return get_proc_return_types(ast_context, symbol, call, true) @@ -948,131 +949,6 @@ get_proc_return_types :: proc( return return_types[:] } -// Attempts to resolve the type of the builtin proc by following the rules of the odin type checker -// defined in `check_builtin.cpp`. -// We don't need to worry about whether the inputs to the procs are valid which eliminates most edge cases. -// The basic rules are as follows: -// - For values not known at compile time (eg values return from procs), just return that type. -// The correct value will either be that type or a compiler error. -// - If all values are known at compile time, then we essentially compute the relevant value -// and return that type. -// There is a difference in the returned types between constants and variables. Constants will use an untyped -// value whereas variables will be typed (as either `int` or `f64`). -check_builtin_proc_return_type :: proc(symbol: Symbol, call: ^ast.Call_Expr, is_mutable: bool) -> (^ast.Expr, bool) { - convert_candidate :: proc(candidate: ^ast.Basic_Lit, is_mutable: bool) -> ^ast.Expr { - if is_mutable { - ident := ast.new(ast.Ident, candidate.pos, candidate.end) - if candidate.tok.kind == .Integer { - ident.name = "int" - } else { - ident.name = "f64" - } - return ident - } - - return candidate - } - - compare_basic_lit_value :: proc(a, b: f64, name: string) -> bool { - if name == "max" { - return a > b - } else if name == "min" { - return a < b - } - return a > b - } - - get_basic_lit_value :: proc(n: ^ast.Expr) -> (^ast.Basic_Lit, f64, bool) { - n := n - - op := "" - if u, ok := n.derived.(^ast.Unary_Expr); ok { - op = u.op.text - n = u.expr - } - - if lit, ok := n.derived.(^ast.Basic_Lit); ok { - text := lit.tok.text - if op != "" { - text = fmt.tprintf("%s%s", op, text) - } - value, ok := strconv.parse_f64(text) - if !ok { - return nil, 0, false - } - - return lit, value, true - } - - return nil, 0, false - } - - if symbol.pkg == "$builtin" { - switch symbol.name { - case "max", "min": - curr_candidate: ^ast.Basic_Lit - curr_value := 0.0 - for arg, i in call.args { - if lit, value, ok := get_basic_lit_value(arg); ok { - if i != 0 { - if compare_basic_lit_value(value, curr_value, symbol.name) { - curr_candidate = lit - curr_value = value - } - } else { - curr_candidate = lit - curr_value = value - } - } - if lit, ok := arg.derived.(^ast.Basic_Lit); ok { - } else { - return arg, true - } - } - if curr_candidate != nil { - return convert_candidate(curr_candidate, is_mutable), true - } - case "abs": - for arg in call.args { - if lit, _, ok := get_basic_lit_value(arg); ok { - return convert_candidate(lit, is_mutable), true - } - return arg, true - } - case "clamp": - if len(call.args) == 3 { - - value_lit, value_value, value_ok := get_basic_lit_value(call.args[0]) - if !value_ok { - return call.args[0], true - } - - minimum_lit, minimum_value, minimum_ok := get_basic_lit_value(call.args[1]) - if !minimum_ok { - return call.args[1], true - } - - maximum_lit, maximum_value, maximum_ok := get_basic_lit_value(call.args[2]) - if !maximum_ok { - return call.args[2], true - } - - if value_value < minimum_value { - return convert_candidate(minimum_lit, is_mutable), true - } - if value_value > maximum_value { - return convert_candidate(maximum_lit, is_mutable), true - } - - return convert_candidate(value_lit, is_mutable), true - } - } - - } - - return nil, false -} - check_node_recursion :: proc(ast_context: ^AstContext, node: ^ast.Node) -> bool { raw := cast(rawptr)node |