Add intrinsics.procedure_of

```odin
foo :: proc(x: $T) { fmt.println(x) }
bar :: intrinsics.procedure_of(foo(int(123))) // parameters are never ran at compile time, similar to `size_of`
bar(333) // prints 333
```
This commit is contained in:
gingerBill
2024-06-10 15:02:34 +01:00
parent 1945218f6d
commit fa3cae2bb0
9 changed files with 87 additions and 6 deletions

View File

@@ -1843,6 +1843,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_objc_register_class:
case BuiltinProc_atomic_type_is_lock_free:
case BuiltinProc_has_target_feature:
case BuiltinProc_procedure_of:
// NOTE(bill): The first arg may be a Type, this will be checked case by case
break;
@@ -6157,6 +6158,51 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
break;
}
case BuiltinProc_procedure_of:
{
Ast *call_expr = unparen_expr(ce->args[0]);
Operand op = {};
check_expr_base(c, &op, ce->args[0], nullptr);
if (op.mode != Addressing_Value && !(call_expr && call_expr->kind == Ast_CallExpr)) {
error(ce->args[0], "Expected a call expression for '%.*s'", LIT(builtin_name));
return false;
}
Ast *proc = call_expr->CallExpr.proc;
Entity *e = entity_of_node(proc);
if (e == nullptr) {
error(ce->args[0], "Invalid procedure value, expected a regular/specialized procedure");
return false;
}
TypeAndValue tav = proc->tav;
operand->type = e->type;
operand->mode = Addressing_Value;
operand->value = tav.value;
operand->builtin_id = BuiltinProc_Invalid;
operand->proc_group = nullptr;
if (tav.mode == Addressing_Builtin) {
operand->mode = tav.mode;
operand->builtin_id = cast(BuiltinProcId)e->Builtin.id;
break;
}
if (!is_type_proc(e->type)) {
gbString s = type_to_string(e->type);
error(ce->args[0], "Expected a procedure value, got '%s'", s);
gb_string_free(s);
return false;
}
ce->entity_procedure_of = e;
break;
}
case BuiltinProc_constant_utf16_cstring:
{
String value = {};