rename intrinsics

This commit is contained in:
2026-07-14 19:22:20 +02:00
parent 471896b48a
commit 5157cf3bcc
26 changed files with 107640 additions and 106418 deletions
+44 -27
View File
@@ -401,10 +401,11 @@ type_label :: proc(checker: ^Checker, value: types.Type) -> string {
return strings.to_string(builder)
}
is_ptr_cast_call :: proc(checker: ^Checker, expr: ast.Expr) -> bool {
return expr.left == ast.INVALID_EXPR &&
is_ptrcast_call :: proc(checker: ^Checker, expr: ast.Expr) -> bool {
return expr.intrinsic &&
expr.left == ast.INVALID_EXPR &&
!symbol.is_valid(expr.qualifier) &&
symbol_text(checker, expr.name) == "ptr_cast"
symbol_text(checker, expr.name) == "ptrcast"
}
Type_Builtin :: enum u8 {
@@ -426,14 +427,14 @@ Division_Builtin :: enum u8 {
}
division_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Division_Builtin {
if expr.kind != .Call || expr.left != ast.INVALID_EXPR || symbol.is_valid(expr.qualifier) {
if !expr.intrinsic || expr.kind != .Call || expr.left != ast.INVALID_EXPR || symbol.is_valid(expr.qualifier) {
return .None
}
switch symbol_text(checker, expr.name) {
case "div_trunc": return .Trunc
case "div_floor": return .Floor
case "div_exact": return .Exact
case "div_ceil": return .Ceil
case "divtrunc": return .Trunc
case "divfloor": return .Floor
case "divexact": return .Exact
case "divceil": return .Ceil
case "rem": return .Rem
case "mod": return .Mod
}
@@ -441,26 +442,26 @@ division_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Division_Bui
}
type_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Type_Builtin {
if expr.kind != .Call || expr.left != ast.INVALID_EXPR || symbol.is_valid(expr.qualifier) {
if !expr.intrinsic || expr.kind != .Call || expr.left != ast.INVALID_EXPR || symbol.is_valid(expr.qualifier) {
return .None
}
name := symbol_text(checker, expr.name)
if name == "size_of" {
if name == "sizeof" {
return .Size_Of
}
if name == "align_of" {
if name == "alignof" {
return .Align_Of
}
if name == "min_value" {
if name == "minval" {
return .Min_Value
}
if name == "max_value" {
if name == "maxval" {
return .Max_Value
}
return .None
}
valid_ptr_cast_child :: proc(checker: ^Checker, value: types.Type) -> bool {
valid_ptrcast_child :: proc(checker: ^Checker, value: types.Type) -> bool {
return types.is_valid(value) &&
!types.is_void(value) &&
!types.is_anyopaque(value) &&
@@ -501,7 +502,7 @@ build_type_builtin :: proc(
file: ast.File_Id,
) -> hir.Expr_Id {
if len(expr.args) != 1 {
id := source.addf(checker.diagnostics, expr.span, "%s expects 1 argument, got %d", symbol_text(checker, expr.name), len(expr.args))
id := source.addf(checker.diagnostics, expr.span, "%s! expects 1 argument, got %d", symbol_text(checker, expr.name), len(expr.args))
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
}
target, target_ok := resolve_type_argument(checker, expr.args[0], pkg, file)
@@ -640,7 +641,7 @@ type_from_syntax :: proc(
}
} else {
if constant.kind == .Integer_Division {
source.add(checker.diagnostics, span, "integer '/' is not allowed; use div_trunc, div_floor, div_exact, or div_ceil")
source.add(checker.diagnostics, span, "integer '/' is not allowed; use divtrunc!, divfloor!, divexact!, or divceil!")
return types.INVALID
}
source.add(checker.diagnostics, span, "array count must be a compile-time integer expression")
@@ -3365,7 +3366,7 @@ infer_expr :: proc(
_ = pop(&stack)
continue
}
if is_ptr_cast_call(checker, expr) {
if is_ptrcast_call(checker, expr) {
if len(expr.args) != 2 {
last = types.INVALID
_ = pop(&stack)
@@ -3374,13 +3375,18 @@ infer_expr :: proc(
child, child_ok := resolve_type_argument(checker, expr.args[0], pkg, file)
operand := infer_nested_expr(checker, expr.args[1], locals, pkg, file, demanded, local_types)
result := types.INVALID
if child_ok && valid_ptr_cast_child(checker, child) {
if child_ok && valid_ptrcast_child(checker, child) {
result, _ = types.replace_pointer_child(&checker.module.types, operand, child)
}
last = result
_ = pop(&stack)
continue
}
if expr.intrinsic {
last = types.INVALID
_ = pop(&stack)
continue
}
if callee_type, handled := infer_qualified_value_field_type(checker, expr, locals, pkg, file); handled {
_, function_item, function_type, ok := types.function_pointer(callee_type, &checker.module.types)
if !ok {
@@ -4957,7 +4963,7 @@ build_constant_expr :: proc(
return invalid_hir_expr(checker, expr.span, id, recovery_type)
}
if constant.kind == .Integer_Division {
id := source.add(checker.diagnostics, expr.span, "integer '/' is not allowed; use div_trunc, div_floor, div_exact, or div_ceil")
id := source.add(checker.diagnostics, expr.span, "integer '/' is not allowed; use divtrunc!, divfloor!, divexact!, or divceil!")
return invalid_hir_expr(checker, expr.span, id, recovery_type)
}
if constant.kind == .Overflow ||
@@ -5447,7 +5453,7 @@ build_division_builtin :: proc(
) -> hir.Expr_Id {
if len(expr.args) != 2 {
id := source.addf(
checker.diagnostics, expr.span, "%s expects 2 arguments, got %d",
checker.diagnostics, expr.span, "%s! expects 2 arguments, got %d",
symbol_text(checker, expr.name), len(expr.args),
)
return invalid_hir_expr(checker, expr.span, id)
@@ -6223,7 +6229,7 @@ build_binary_arith :: proc(
if op == .Div && !types.is_float(result, checker.target) {
id := source.add(
checker.diagnostics, span,
"integer '/' is not allowed; use div_trunc, div_floor, div_exact, or div_ceil",
"integer '/' is not allowed; use divtrunc!, divfloor!, divexact!, or divceil!",
)
return invalid_hir_expr(checker, span, id, result)
}
@@ -6463,22 +6469,22 @@ build_expr :: proc(
_ = pop(&stack)
continue
}
if is_ptr_cast_call(checker, expr) {
if is_ptrcast_call(checker, expr) {
if len(expr.args) != 2 {
id := source.addf(checker.diagnostics, expr.span, "ptr_cast expects 2 arguments, got %d", len(expr.args))
id := source.addf(checker.diagnostics, expr.span, "ptrcast! expects 2 arguments, got %d", len(expr.args))
last = invalid_hir_expr(checker, expr.span, id)
_ = pop(&stack)
continue
}
target, target_ok := resolve_type_argument(checker, expr.args[0], pkg, file)
if !target_ok {
id := source.add(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "ptr_cast target must be a type")
id := source.add(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "ptrcast! target must be a type")
last = invalid_hir_expr(checker, expr.span, id)
_ = pop(&stack)
continue
}
if !valid_ptr_cast_child(checker, target) {
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "ptr_cast target must be a sized runtime object type, got %s", type_label(checker, target))
if !valid_ptrcast_child(checker, target) {
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "ptrcast! target must be a sized runtime object type, got %s", type_label(checker, target))
last = invalid_hir_expr(checker, expr.span, id)
_ = pop(&stack)
continue
@@ -6488,6 +6494,17 @@ build_expr :: proc(
append(&stack, Build_Expr_Frame{expr=expr.args[1], expected=types.INVALID, template=ast.INVALID_FUNCTION})
continue
}
if expr.intrinsic {
id := source.INVALID_DIAGNOSTIC
if symbol.is_valid(expr.qualifier) {
id = source.add(checker.diagnostics, expr.span, "intrinsic calls must be unqualified")
} else {
id = source.addf(checker.diagnostics, expr.span, "unknown intrinsic '%s!'", symbol_text(checker, expr.name))
}
last = invalid_hir_expr(checker, expr.span, id)
_ = pop(&stack)
continue
}
if callee, handled, ok := build_qualified_value_field(checker, expr, locals, global_reads, pkg, file); handled {
if !ok {
last = callee
@@ -6996,7 +7013,7 @@ build_expr :: proc(
if frame.stage == 9 {
result, ok := types.replace_pointer_child(&checker.module.types, checker.module.exprs[last].type, frame.target_type)
if !ok {
id := source.add(checker.diagnostics, expr.span, "ptr_cast operand must be a pointer or optional pointer")
id := source.add(checker.diagnostics, expr.span, "ptrcast! operand must be a pointer or optional pointer")
last = invalid_hir_expr(checker, expr.span, id)
} else {
last = add_hir_expr(checker, hir.Expr{
+8 -2
View File
@@ -1862,7 +1862,7 @@ ct_eval_binary :: proc(state: ^Ct_State, op: ast.Expr_Kind, left_id, right_id: C
if op == .Div {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(
state, .Integer_Division, span,
"integer '/' is not allowed; use div_trunc, div_floor, div_exact, or div_ceil",
"integer '/' is not allowed; use divtrunc!, divfloor!, divexact!, or divceil!",
)
}
value: i128
@@ -2059,7 +2059,7 @@ ct_eval_call_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Type
}
if builtin := type_builtin_call(checker, expr); builtin != .None {
if len(expr.args) != 1 {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "%s expects 1 argument, got %d", symbol_text(checker, expr.name), len(expr.args))
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "%s! expects 1 argument, got %d", symbol_text(checker, expr.name), len(expr.args))
}
target, target_ok := resolve_type_argument(checker, expr.args[0], state.pkg, state.file)
if !target_ok {
@@ -2078,6 +2078,12 @@ ct_eval_call_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Type
if builtin := division_builtin_call(checker, expr); builtin != .None {
return ct_eval_division_call(state, expr, builtin, expected, depth+1)
}
if expr.intrinsic {
if symbol.is_valid(expr.qualifier) {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "intrinsic calls must be unqualified")
}
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "unknown intrinsic '%s!'", symbol_text(checker, expr.name))
}
target_pkg, available := expr_package(checker, expr, state.pkg, state.file, false)
if !available {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "unavailable function package")