function values as comptime params

This commit is contained in:
2026-07-18 01:35:39 +02:00
parent 9f433af724
commit 85693e57e1
7 changed files with 254 additions and 12 deletions
+51 -3
View File
@@ -596,6 +596,9 @@ build_static_value :: proc(checker: ^Checker, value: Ct_Value, span: source.Span
diagnostic=source.INVALID_DIAGNOSTIC,
})
}
if value.kind == .Function {
return build_function_value(checker, ast.Function_Id(u32(value.index)), span, expected)
}
if value.kind == .Array || value.kind == .Struct || value.kind == .Range {
children := ct_child_slice(&checker.static_state, value)
args := make([]hir.Expr_Id, len(children), checker.allocator)
@@ -4728,7 +4731,7 @@ infer_expr :: proc(
_ = pop(&stack)
continue
}
if callee_type, handled := infer_qualified_value_field_type(checker, expr, locals, pkg, file); handled {
if callee_type, handled := infer_qualified_value_field_type(checker, expr, locals, pkg, file, demanded); handled {
_, function_item, function_type, ok := types.function_pointer(callee_type, &checker.module.types)
if !ok {
last = types.INVALID
@@ -4757,6 +4760,19 @@ infer_expr :: proc(
callee_type := types.INVALID
if !symbol.is_valid(expr.qualifier) {
callee_type = find_infer_local(locals, expr.name)
if !types.is_valid(callee_type) {
if value, ok := current_comptime_value(checker, expr.name); ok && value.kind == .Static {
callee_type = value.type
if value.static_value != INVALID_CT_VALUE && int(value.static_value) < len(checker.static_state.values) {
function_value := checker.static_state.values[value.static_value]
if function_value.kind == .Function {
_, _, _ = function_pointer_type_for_template(
checker, ast.Function_Id(u32(function_value.index)), demanded,
)
}
}
}
}
}
if !types.is_valid(callee_type) && available {
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
@@ -6690,12 +6706,24 @@ infer_qualified_value_field_type :: proc(
locals: []Infer_Local,
pkg: ast.Package_Id,
file: ast.File_Id,
demanded: ^[dynamic]Spec_Id = nil,
) -> (types.Type, bool) {
if !symbol.is_valid(expr.qualifier) ||
find_import(checker, file, expr.qualifier) != ast.INVALID_IMPORT {
return types.INVALID, false
}
base_type := find_infer_local(locals, expr.qualifier)
if !types.is_valid(base_type) {
if value, ok := current_comptime_value(checker, expr.qualifier); ok && value.kind == .Static {
base_type = value.type
if field_value, found := persistent_field_value(checker, value.static_value, expr.name);
found && field_value.kind == .Function {
_, _, _ = function_pointer_type_for_template(
checker, ast.Function_Id(u32(field_value.index)), demanded,
)
}
}
}
if !types.is_valid(base_type) {
if global := find_global(checker, expr.qualifier, pkg, file); global != ast.INVALID_GLOBAL {
base_type = checker.global_types[global]
@@ -8235,6 +8263,15 @@ build_expr :: proc(
non_callable = true
}
}
if callee == hir.INVALID_EXPR && !non_callable {
if value, ok := current_comptime_value(checker, expr.name);
ok && value.kind == .Static && value.static_value != INVALID_CT_VALUE &&
int(value.static_value) < len(checker.static_state.values) {
callee = build_static_value(
checker, checker.static_state.values[value.static_value], expr.span, types.INVALID,
)
}
}
}
if callee == hir.INVALID_EXPR && !non_callable {
if global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file)); global != ast.INVALID_GLOBAL {
@@ -8757,9 +8794,20 @@ build_expr :: proc(
stack[frame_index].built_args = nil
last = invalid_hir_expr(checker, expr.span, id)
} else {
target := hir.INVALID_REF
callee := frame.left
callee_expr := checker.module.exprs[frame.left]
if callee_expr.kind == .Function {
function := hir.as_function(callee_expr.target)
if function != hir.INVALID_FUNCTION {
target = callee_expr.target
callee = hir.INVALID_EXPR
add_unique_function(calls, function)
}
}
last = add_hir_expr(checker, hir.Expr{
kind=.Call, span=expr.span, type=result, target=hir.INVALID_REF,
left=frame.left, right=hir.INVALID_EXPR, args=stack[frame_index].built_args,
kind=.Call, span=expr.span, type=result, target=target,
left=callee, right=hir.INVALID_EXPR, args=stack[frame_index].built_args,
diagnostic=source.INVALID_DIAGNOSTIC,
})
stack[frame_index].built_args = nil