comptime storage and function values
This commit is contained in:
@@ -903,13 +903,16 @@ function_value_signature :: proc(
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
function := checker.ast_module.functions[template]
|
||||
if !function.c_abi || types.is_valid(function.error) {
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
if function_has_comptime_params(function) {
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
result = type_from_syntax(checker, function.result, function.pkg, function.file)
|
||||
if function.c_abi && types.is_valid(function.error) {
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
if !function.c_abi && (!function.has_body || function.variadic) {
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
result = function_channel_type(checker, function)
|
||||
if !types.is_void(result) && !is_runtime_type(checker, result) {
|
||||
return nil, types.INVALID, false
|
||||
}
|
||||
@@ -929,6 +932,7 @@ function_pointer_type_for_template :: proc(
|
||||
checker: ^Checker,
|
||||
template: ast.Function_Id,
|
||||
demanded: ^[dynamic]Spec_Id = nil,
|
||||
demand_spec := true,
|
||||
) -> (types.Type, Spec_Id, bool) {
|
||||
params, result, ok := function_value_signature(checker, template)
|
||||
if !ok {
|
||||
@@ -936,16 +940,20 @@ function_pointer_type_for_template :: proc(
|
||||
}
|
||||
defer delete(params, checker.allocator)
|
||||
function := checker.ast_module.functions[template]
|
||||
function_type := types.function(&checker.module.types, params, result, true, function.variadic)
|
||||
function_type := types.function(&checker.module.types, params, result, function.c_abi, function.variadic)
|
||||
pointer_type := types.pointer(&checker.module.types, function_type, false, true)
|
||||
spec := INVALID_SPEC
|
||||
if demanded == nil {
|
||||
spec = ensure_spec(checker, template, params)
|
||||
if demand_spec {
|
||||
spec = ensure_spec(checker, template, params)
|
||||
} else {
|
||||
spec = find_spec(checker, template, params)
|
||||
}
|
||||
} else {
|
||||
spec = find_spec(checker, template, params)
|
||||
mark_spec_demanded(checker, spec, demanded)
|
||||
}
|
||||
return pointer_type, spec, spec != INVALID_SPEC
|
||||
return pointer_type, spec, spec != INVALID_SPEC || !demand_spec
|
||||
}
|
||||
|
||||
contains_name :: proc(names: []symbol.Id, name: symbol.Id) -> bool {
|
||||
@@ -1391,16 +1399,30 @@ validate_type_nodes :: proc(checker: ^Checker) {
|
||||
}
|
||||
}
|
||||
if item.kind == .Function {
|
||||
if !item.c_abi {
|
||||
source.add(checker.diagnostics, source.Span{}, "only c_func function pointer types are supported")
|
||||
}
|
||||
for param in types.params_for(&checker.module.types, id) {
|
||||
if types.is_void(param.type) || !types.is_c_signature_type(param.type, &checker.module.types) {
|
||||
source.add(checker.diagnostics, source.Span{}, "function pointer parameters must be concrete C signature types")
|
||||
if item.c_abi {
|
||||
if types.kind(item.child, &checker.module.types) == .Fallible {
|
||||
source.add(checker.diagnostics, source.Span{}, "c_func pointer results cannot be fallible")
|
||||
}
|
||||
for param in types.params_for(&checker.module.types, id) {
|
||||
if types.is_void(param.type) || !types.is_c_signature_type(param.type, &checker.module.types) {
|
||||
source.add(checker.diagnostics, source.Span{}, "c_func pointer parameters must be concrete C signature types")
|
||||
}
|
||||
}
|
||||
if !types.is_c_signature_type(item.child, &checker.module.types, true) {
|
||||
source.add(checker.diagnostics, source.Span{}, "c_func pointer results must be concrete C signature types or void")
|
||||
}
|
||||
} else {
|
||||
if item.variadic {
|
||||
source.add(checker.diagnostics, source.Span{}, "native function pointer types do not support variadic parameters")
|
||||
}
|
||||
for param in types.params_for(&checker.module.types, id) {
|
||||
if types.is_void(param.type) || !is_runtime_type(checker, param.type) {
|
||||
source.add(checker.diagnostics, source.Span{}, "native function pointer parameters must be concrete runtime types")
|
||||
}
|
||||
}
|
||||
if !types.is_void(item.child) && !is_runtime_type(checker, item.child) {
|
||||
source.add(checker.diagnostics, source.Span{}, "native function pointer results must be concrete runtime types or void")
|
||||
}
|
||||
}
|
||||
if !types.is_c_signature_type(item.child, &checker.module.types, true) {
|
||||
source.add(checker.diagnostics, source.Span{}, "function pointer results must be concrete C signature types or void")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1597,7 +1619,7 @@ infer_compound_expr :: proc(
|
||||
store := &checker.module.types
|
||||
#partial switch expr.kind {
|
||||
case .Comptime:
|
||||
return infer_comptime_expr_type(checker, expr, pkg, file)
|
||||
return infer_comptime_expr_type(checker, expr, pkg, file, demanded)
|
||||
case .Bool:
|
||||
return types.BOOL
|
||||
case .Not:
|
||||
@@ -3535,13 +3557,13 @@ build_function_value :: proc(
|
||||
id := source.addf(
|
||||
checker.diagnostics,
|
||||
span,
|
||||
"function '%s' cannot be used as a C callback; expected a concrete c_func",
|
||||
"function '%s' cannot be used as a function value; expected a concrete non-comptime signature",
|
||||
symbol_text(checker, function.name),
|
||||
)
|
||||
return invalid_hir_expr(checker, span, id)
|
||||
}
|
||||
defer delete(params, checker.allocator)
|
||||
function_type := types.function(&checker.module.types, params, result, true, function.variadic)
|
||||
function_type := types.function(&checker.module.types, params, result, function.c_abi, function.variadic)
|
||||
pointer_type := types.pointer(&checker.module.types, function_type, false, true)
|
||||
spec := find_spec(checker, template, params)
|
||||
if spec == INVALID_SPEC {
|
||||
@@ -4444,7 +4466,7 @@ build_expr :: proc(
|
||||
last = build_global_reference(checker, global, expr.span, global_reads)
|
||||
} else {
|
||||
template := find_template(checker, expr.name, target_pkg)
|
||||
if template != ast.INVALID_FUNCTION && checker.ast_module.functions[template].c_abi {
|
||||
if template != ast.INVALID_FUNCTION {
|
||||
last = build_function_value(checker, template, expr.span, frame.expected)
|
||||
} else {
|
||||
id := add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)
|
||||
|
||||
+1022
-71
File diff suppressed because it is too large
Load Diff
@@ -113,7 +113,7 @@ is_type_token :: proc(kind: token.Kind) -> bool {
|
||||
.Keyword_C_Short, .Keyword_C_Ushort, .Keyword_C_Int, .Keyword_C_Uint,
|
||||
.Keyword_C_Long, .Keyword_C_Ulong, .Keyword_C_Longlong, .Keyword_C_Ulonglong,
|
||||
.Keyword_C_Float, .Keyword_C_Double, .Keyword_C_Longdouble,
|
||||
.Keyword_Void, .Keyword_Bool, .Keyword_C_Func, .Identifier, .Question, .At, .Star, .Left_Bracket:
|
||||
.Keyword_Void, .Keyword_Bool, .Keyword_Func, .Keyword_C_Func, .Identifier, .Question, .At, .Star, .Left_Bracket:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -329,10 +329,11 @@ parse_type_atom :: proc(parser: ^Parser) -> ast.Type_Syntax {
|
||||
case .Keyword_Bool:
|
||||
advance(parser)
|
||||
return types.BOOL
|
||||
case .Keyword_C_Func:
|
||||
case .Keyword_Func, .Keyword_C_Func:
|
||||
c_abi := tok.kind == .Keyword_C_Func
|
||||
advance(parser)
|
||||
if _, ok := allow(parser, .Left_Paren); !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '(' after c_func type")
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '(' after function type")
|
||||
return types.INVALID
|
||||
}
|
||||
params, variadic := parse_params(parser)
|
||||
@@ -340,11 +341,19 @@ parse_type_atom :: proc(parser: ^Parser) -> ast.Type_Syntax {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected ')' after function type parameters")
|
||||
}
|
||||
result := parse_type(parser)
|
||||
if _, ok := allow(parser, .Bang); ok {
|
||||
error_type := parse_error_type(parser)
|
||||
if c_abi {
|
||||
source.add(parser.diagnostics, current(parser).span, "c_func pointer types cannot be fallible")
|
||||
} else {
|
||||
result = types.fallible(&parser.module.type_store, result, error_type)
|
||||
}
|
||||
}
|
||||
param_types := make([]types.Type, len(params), parser.module.allocator)
|
||||
for param, index in params {
|
||||
param_types[index] = param.type
|
||||
}
|
||||
function_type := types.function(&parser.module.type_store, param_types, result, true, variadic)
|
||||
function_type := types.function(&parser.module.type_store, param_types, result, c_abi, variadic)
|
||||
delete(param_types, parser.module.allocator)
|
||||
delete(params, parser.module.allocator)
|
||||
return function_type
|
||||
|
||||
Reference in New Issue
Block a user