rename none to null

This commit is contained in:
2026-07-21 22:59:51 +02:00
parent 1619ea98a3
commit 402871ef7a
44 changed files with 3771 additions and 3767 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ Expr_Kind :: enum u8 {
String,
Bool,
Array,
None,
Null,
Undefined,
Inference_Hole,
Type,
+43 -43
View File
@@ -81,7 +81,7 @@ Yield_Target :: struct {
label: symbol.Id,
slot: hir.Local_Id,
slot_type: types.Type,
// True when the loop also yields `none` (a `{T, none}` set `?T`); set from a
// True when the loop also yields `null` (a `{T, null}` set `?T`); set from a
// pure-AST scan, used to pick the slot's element type on the first concrete yield.
result_optional: bool,
// `len(defers)` when this target's body began; a `yield :label` flushes defers down
@@ -394,7 +394,7 @@ block_reads_name :: proc(checker: ^Checker, statements: []ast.Stmt_Id, name: sym
case .Add, .Sub, .Mul, .Div, .Bit_And, .Bit_Or, .Bit_Xor, .Shift_Left, .Shift_Right,
.Shift_Left_Saturating, .Index, .Orelse, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or, .Range:
append(&expr_stack, expr.left, expr.right)
case .Invalid, .Integer, .Float, .String, .Bool, .None, .Undefined, .Inference_Hole,
case .Invalid, .Integer, .Float, .String, .Bool, .Null, .Undefined, .Inference_Hole,
.Type, .Name, .Function_Literal, .Anonymous_Struct_Type:
}
}
@@ -639,9 +639,9 @@ build_static_value :: proc(checker: ^Checker, value: Ct_Value, span: source.Span
diagnostic=source.INVALID_DIAGNOSTIC,
})
}
if value.kind == .None {
if value.kind == .Null {
return add_hir_expr(checker, hir.Expr{
kind=.None, span=span, type=value.type,
kind=.Null, span=span, type=value.type,
target=hir.INVALID_REF, left=hir.INVALID_EXPR, right=hir.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
@@ -2797,7 +2797,7 @@ infer_call_comptime_values :: proc(
for value_bound in bound {
all_bound = all_bound && value_bound
}
// Concrete arguments bind first. Numeric constants and `none` are contextual and
// Concrete arguments bind first. Numeric constants and `null` are contextual and
// therefore only contribute after stronger evidence has had a chance to bind the
// parameter type.
weak_passes := [2]bool{false, true}
@@ -2811,8 +2811,8 @@ infer_call_comptime_values :: proc(
continue
}
arg_expr := checker.ast_module.exprs[arg_id]
is_none := arg_expr.kind == .None
is_weak := is_numeric_constant_expr(checker, arg_id) || is_none
is_null := arg_expr.kind == .Null
is_weak := is_numeric_constant_expr(checker, arg_id) || is_null
if is_weak != weak {
continue
}
@@ -2836,7 +2836,7 @@ infer_call_comptime_values :: proc(
}
}
actual := actual_args[param_index]
if is_none {
if is_null {
previous := checker.current_comptime_values
checker.current_comptime_values = values
contextual := type_from_syntax(
@@ -3506,7 +3506,7 @@ mark_expr_imports_used :: proc(checker: ^Checker, expr_id: ast.Expr_Id, file: as
case .Add, .Sub, .Mul, .Div, .Bit_And, .Bit_Or, .Bit_Xor, .Shift_Left, .Shift_Right,
.Shift_Left_Saturating, .Index, .Orelse, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or, .Range:
append(&stack, expr.left, expr.right)
case .Invalid, .Integer, .Float, .String, .Bool, .None, .Undefined, .Inference_Hole, .Type, .Name, .Anonymous_Struct_Type:
case .Invalid, .Integer, .Float, .String, .Bool, .Null, .Undefined, .Inference_Hole, .Type, .Name, .Anonymous_Struct_Type:
}
}
}
@@ -4585,10 +4585,10 @@ infer_compound_expr :: proc(
case .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
left_expr := checker.ast_module.exprs[expr.left]
right_expr := checker.ast_module.exprs[expr.right]
if left_expr.kind == .None && right_expr.kind != .None {
if left_expr.kind == .Null && right_expr.kind != .Null {
right := infer_nested_expr(checker, expr.right, locals, pkg, file, demanded, local_types)
_ = infer_nested_expr(checker, expr.left, locals, pkg, file, demanded, local_types, right)
} else if right_expr.kind == .None && left_expr.kind != .None {
} else if right_expr.kind == .Null && left_expr.kind != .Null {
left := infer_nested_expr(checker, expr.left, locals, pkg, file, demanded, local_types)
_ = infer_nested_expr(checker, expr.right, locals, pkg, file, demanded, local_types, left)
} else {
@@ -4629,7 +4629,7 @@ infer_compound_expr :: proc(
element = types.I64
}
return types.array(store, element, u64(len(expr.args)), false)
case .None:
case .Null:
return expected if types.is_optional(expected, store) else types.INVALID
case .Undefined:
return types.INVALID
@@ -4928,7 +4928,7 @@ infer_expr :: proc(
case .Float:
last = types.F64
_ = pop(&stack)
case .String, .Array, .None, .Undefined, .Address, .Deref, .Index, .Slice,
case .String, .Array, .Null, .Undefined, .Address, .Deref, .Index, .Slice,
.Field, .Unwrap, .Orelse, .Try, .Catch, .Struct_Literal, .Keyed, .Enum_Literal, .Cast,
.Comptime, .Bool, .Not, .Bit_Not, .Bit_And, .Bit_Or, .Bit_Xor, .Shift_Left,
.Shift_Right, .Shift_Left_Saturating, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or, .Range:
@@ -7773,13 +7773,13 @@ build_compound_expr :: proc(
target=hir.INVALID_REF, left=hir.INVALID_EXPR, right=hir.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .None:
case .Null:
if !types.is_optional(expected, store) {
id := source.add(checker.diagnostics, expr.span, "'none' requires an optional context")
id := source.add(checker.diagnostics, expr.span, "'null' requires an optional context")
return invalid_hir_expr(checker, expr.span, id, expected)
}
return add_hir_expr(checker, hir.Expr{
kind=.None, span=expr.span, type=expected, target=hir.INVALID_REF,
kind=.Null, span=expr.span, type=expected, target=hir.INVALID_REF,
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
})
case .Undefined:
@@ -8311,7 +8311,7 @@ build_compound_expr :: proc(
case .Eq, .Ne, .Lt, .Le, .Gt, .Ge:
// Contextualize literals whose type comes from their peer. This covers
// integer and enum literals as well as optional presence tests such as
// `value == none` and `none != value`.
// `value == null` and `null != value`.
left_const := eval_constant(checker, expr.left)
right_const := eval_constant(checker, expr.right)
left, right: hir.Expr_Id
@@ -8319,10 +8319,10 @@ build_compound_expr :: proc(
right_expr := checker.ast_module.exprs[expr.right]
left_numeric_const := left_const.kind == .Value || is_float_constant_expr(checker, expr.left)
right_numeric_const := right_const.kind == .Value || is_float_constant_expr(checker, expr.right)
if right_expr.kind == .None && left_expr.kind != .None {
if right_expr.kind == .Null && left_expr.kind != .Null {
left = build_nested_expr(checker, expr.left, locals, global_reads, calls, types.INVALID, pkg, file)
right = build_nested_expr(checker, expr.right, locals, global_reads, calls, checker.module.exprs[left].type, pkg, file)
} else if left_expr.kind == .None && right_expr.kind != .None {
} else if left_expr.kind == .Null && right_expr.kind != .Null {
right = build_nested_expr(checker, expr.right, locals, global_reads, calls, types.INVALID, pkg, file)
left = build_nested_expr(checker, expr.left, locals, global_reads, calls, checker.module.exprs[right].type, pkg, file)
} else if right_expr.kind == .Enum_Literal && left_expr.kind != .Enum_Literal {
@@ -8349,10 +8349,10 @@ build_compound_expr :: proc(
left_type := checker.module.exprs[left].type
right_type := checker.module.exprs[right].type
operand_type := types.INVALID
if left_expr.kind == .None || right_expr.kind == .None {
if left_expr.kind == .Null || right_expr.kind == .Null {
if expr.kind != .Eq && expr.kind != .Ne ||
!types.is_optional(left_type, store) || !types.equal(left_type, right_type) {
id := source.add(checker.diagnostics, expr.span, "'none' only supports '==' and '!=' with an optional value")
id := source.add(checker.diagnostics, expr.span, "'null' only supports '==' and '!=' with an optional value")
return invalid_hir_expr(checker, expr.span, id, types.BOOL)
}
operand_type = left_type
@@ -8703,7 +8703,7 @@ build_expr :: proc(
continue
}
switch expr.kind {
case .String, .Array, .None, .Undefined, .Address, .Deref, .Index, .Slice,
case .String, .Array, .Null, .Undefined, .Address, .Deref, .Index, .Slice,
.Field, .Unwrap, .Orelse, .Try, .Catch, .Struct_Literal, .Keyed,
.Bool, .Cast, .Comptime, .Not, .Bit_Not, .Bit_And, .Bit_Or, .Bit_Xor, .Shift_Left,
.Shift_Right, .Shift_Left_Saturating, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or, .Range,
@@ -12567,24 +12567,24 @@ build_value_match :: proc(
return slot_read(checker, slot, slot_type, span), slot_type
}
// loop_yields_none reports whether any `yield` that targets this loop (a labeled
// loop_yields_null reports whether any `yield` that targets this loop (a labeled
// `yield :blk` inside `if`/block branches, or the trailing fall-through) yields the
// literal `none` making the loop's result optional. Pure AST walk; does not descend
// literal `null` making the loop's result optional. Pure AST walk; does not descend
// into nested loops or value sources, whose yields belong to them.
loop_yields_none :: proc(checker: ^Checker, stmts: []ast.Stmt_Id) -> bool {
loop_yields_null :: proc(checker: ^Checker, stmts: []ast.Stmt_Id) -> bool {
for id in stmts {
s := checker.ast_module.statements[id]
#partial switch s.kind {
case .Yield:
if s.expr != ast.INVALID_EXPR && checker.ast_module.exprs[s.expr].kind == .None {
if s.expr != ast.INVALID_EXPR && checker.ast_module.exprs[s.expr].kind == .Null {
return true
}
case .If:
if loop_yields_none(checker, s.body) || loop_yields_none(checker, s.else_body) {
if loop_yields_null(checker, s.body) || loop_yields_null(checker, s.else_body) {
return true
}
case .Block:
if loop_yields_none(checker, s.body) {
if loop_yields_null(checker, s.body) {
return true
}
}
@@ -12593,8 +12593,8 @@ loop_yields_none :: proc(checker: ^Checker, stmts: []ast.Stmt_Id) -> bool {
}
// resolve_loop_slot fixes a value-loop's result slot from its first concrete yield (an
// optional element type when the loop also yields `none`) and coerces `value` into it.
// Returns INVALID when the type can't be fixed yet (a `none`/invalid first yield).
// optional element type when the loop also yields `null`) and coerces `value` into it.
// Returns INVALID when the type can't be fixed yet (a `null`/invalid first yield).
resolve_loop_slot :: proc(ctx: ^Build_Ctx, target: ^Yield_Target, value: hir.Expr_Id, vtype: types.Type, span: source.Span) -> hir.Expr_Id {
checker := ctx.checker
if target.slot == hir.INVALID_LOCAL {
@@ -12608,14 +12608,14 @@ resolve_loop_slot :: proc(ctx: ^Build_Ctx, target: ^Yield_Target, value: hir.Exp
}
// first_concrete_yield_expr returns the AST expr of the first yield (source order) that is
// not the literal `none`, descending into `if`/block branches but not nested loops or value
// sources (whose yields belong to them). INVALID when the loop yields only `none`.
// not the literal `null`, descending into `if`/block branches but not nested loops or value
// sources (whose yields belong to them). INVALID when the loop yields only `null`.
first_concrete_yield_expr :: proc(checker: ^Checker, stmts: []ast.Stmt_Id) -> ast.Expr_Id {
for id in stmts {
s := checker.ast_module.statements[id]
#partial switch s.kind {
case .Yield:
if s.expr != ast.INVALID_EXPR && checker.ast_module.exprs[s.expr].kind != .None {
if s.expr != ast.INVALID_EXPR && checker.ast_module.exprs[s.expr].kind != .Null {
return s.expr
}
case .If:
@@ -12635,9 +12635,9 @@ first_concrete_yield_expr :: proc(checker: ^Checker, stmts: []ast.Stmt_Id) -> as
}
// value_loop_element_type pre-types the element of an untyped value loop from its first
// concrete (non-`none`) yield, so a `none` yielded before any concrete value still resolves
// concrete (non-`null`) yield, so a `null` yielded before any concrete value still resolves
// the result to `?T`. The loop's captures are bound temporarily for the probe and the probe
// expr is discarded; returns INVALID when the loop yields only `none`.
// expr is discarded; returns INVALID when the loop yields only `null`.
value_loop_element_type :: proc(ctx: ^Build_Ctx, loop_stmt: ast.Stmt) -> types.Type {
checker := ctx.checker
yield_expr := first_concrete_yield_expr(checker, loop_stmt.body)
@@ -12736,7 +12736,7 @@ block_element_type :: proc(ctx: ^Build_Ctx, block_stmts: []ast.Stmt_Id) -> types
// reads it after the block. Every path must yield (or otherwise exit); HIR holds a `.Block`
// that emits the body and the exit label the labeled breaks branch to. No iteration / no
// fall-through (unlike a value loop). The type is the annotation when typed, else the first
// concrete `yield :blk`'s type (optional when any yield is `none`).
// concrete `yield :blk`'s type (optional when any yield is `null`).
build_value_labeled_block :: proc(
ctx: ^Build_Ctx,
body: ^[dynamic]hir.Stmt_Id,
@@ -12746,7 +12746,7 @@ build_value_labeled_block :: proc(
span: source.Span,
) -> (value: hir.Expr_Id, value_type: types.Type) {
checker := ctx.checker
result_optional := loop_yields_none(checker, block_stmts)
result_optional := loop_yields_null(checker, block_stmts)
slot := hir.INVALID_LOCAL
slot_type := types.INVALID
if is_runtime_type(checker, expected) {
@@ -12754,8 +12754,8 @@ build_value_labeled_block :: proc(
slot = new_value_slot(ctx, slot_type)
result_optional = types.is_optional(slot_type, &checker.module.types)
} else if result_optional {
// Untyped block that also yields `none`: pre-type the element from the first
// concrete yield (regardless of source order) so a `none` yielded first still
// Untyped block that also yields `null`: pre-type the element from the first
// concrete yield (regardless of source order) so a `null` yielded first still
// resolves the result to `?T`.
elem := block_element_type(ctx, block_stmts)
if is_runtime_type(checker, elem) {
@@ -12816,7 +12816,7 @@ build_value_labeled_block :: proc(
// desugars (in build_block) to `slot = x; break`, and the construct's value is a read
// of the slot after the loop. Reuses the ordinary `.For`/`.While` build via a peeled
// copy; no new HIR. The yielded type is the annotation when typed, else the first
// concrete yield's type (optional when any yield is `none`).
// concrete yield's type (optional when any yield is `null`).
build_value_loop :: proc(
ctx: ^Build_Ctx,
body: ^[dynamic]hir.Stmt_Id,
@@ -12844,7 +12844,7 @@ build_value_loop :: proc(
}
fall_stmt := checker.ast_module.statements[loop_stmt.body[n - 1]]
result_optional := loop_yields_none(checker, loop_stmt.body)
result_optional := loop_yields_null(checker, loop_stmt.body)
slot := hir.INVALID_LOCAL
slot_type := types.INVALID
if is_runtime_type(checker, expected) {
@@ -12852,8 +12852,8 @@ build_value_loop :: proc(
slot = new_value_slot(ctx, slot_type)
result_optional = types.is_optional(slot_type, &checker.module.types)
} else if result_optional {
// Untyped loop that also yields `none`: pre-type the element from the first
// concrete yield (regardless of source order) so a `none` built before any
// Untyped loop that also yields `null`: pre-type the element from the first
// concrete yield (regardless of source order) so a `null` built before any
// concrete yield still resolves the result to `?T`.
elem := value_loop_element_type(ctx, loop_stmt)
if is_runtime_type(checker, elem) {
+19 -19
View File
@@ -228,7 +228,7 @@ Ct_Value_Kind :: enum u8 {
Slice,
Function,
Type,
None,
Null,
Optional_Some,
Fallible,
}
@@ -651,12 +651,12 @@ ct_coerce_value :: proc(state: ^Ct_State, id: Ct_Value_Id, expected: types.Type,
return ct_add_value(state, value), true
}
}
if value.kind == .None {
if value.kind == .Null {
if types.is_optional(expected, store) {
value.type = expected
return ct_add_value(state, value), true
}
return INVALID_CT_VALUE, ct_fail(state, .Not_Comptime, span, "'none' requires an optional context")
return INVALID_CT_VALUE, ct_fail(state, .Not_Comptime, span, "'null' requires an optional context")
}
if types.is_optional(expected, store) {
child := types.child_type(expected, store)
@@ -941,9 +941,9 @@ ct_materialize_value :: proc(
case .Function:
value_expected := expected if types.is_valid(expected) else value.type
return build_function_value(checker, ast.Function_Id(u32(value.index)), span, value_expected)
case .None:
case .Null:
return add_hir_expr(checker, hir.Expr{
kind=.None, span=span, type=value.type,
kind=.Null, span=span, type=value.type,
target=hir.INVALID_REF, left=hir.INVALID_EXPR, right=hir.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
@@ -1154,11 +1154,11 @@ ct_eval_expr :: proc(
return ct_add_value(state, Ct_Value{kind=.Type, type=types.INVALID, index=u64(resolved)}), ct_flow(.Normal), types.is_valid(resolved)
case .Enum_Literal:
return ct_eval_enum_literal(state, expr, expected, depth+1)
case .None:
case .Null:
if !types.is_optional(expected, store) {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "'none' requires an optional context")
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "'null' requires an optional context")
}
return ct_add_value(state, Ct_Value{kind=.None, type=expected}), ct_flow(.Normal), true
return ct_add_value(state, Ct_Value{kind=.Null, type=expected}), ct_flow(.Normal), true
case .Field:
if enum_type, enum_ok := enum_type_from_field_expr(checker, expr, state.pkg, state.file); enum_ok {
member, ok := find_enum_member(checker, enum_type, expr.name)
@@ -1246,7 +1246,7 @@ ct_eval_expr :: proc(
return children[0], ct_flow(.Normal), true
}
}
if v.kind == .None {
if v.kind == .Null {
child := types.child_type(v.type, store)
return ct_eval_expr(state, expr.right, child, depth+1)
}
@@ -1289,7 +1289,7 @@ ct_eval_expr :: proc(
}
left_expr := checker.ast_module.exprs[expr.left]
right_expr := checker.ast_module.exprs[expr.right]
if left_expr.kind == .None && right_expr.kind != .None &&
if left_expr.kind == .Null && right_expr.kind != .Null &&
(expr.kind == .Eq || expr.kind == .Ne) {
right, right_flow, right_ok := ct_eval_expr(state, expr.right, types.INVALID, depth+1)
if !right_ok || right_flow.kind != .Normal {
@@ -2071,8 +2071,8 @@ ct_unwrap_optional :: proc(state: ^Ct_State, id: Ct_Value_Id, span: source.Span)
return children[0], ct_flow(.Normal), true
}
}
if value.kind == .None {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "comptime optional unwrap of none")
if value.kind == .Null {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "comptime optional unwrap of null")
}
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "postfix '?' requires an optional")
}
@@ -2132,13 +2132,13 @@ ct_eval_binary :: proc(state: ^Ct_State, op: ast.Expr_Kind, left_id, right_id: C
left := state.values[left_id]
right := state.values[right_id]
is_compare := op == .Eq || op == .Ne || op == .Lt || op == .Le || op == .Gt || op == .Ge
if left.kind == .None || right.kind == .None {
if left.kind == .Null || right.kind == .Null {
if (op != .Eq && op != .Ne) ||
!types.is_optional(left.type, &state.checker.module.types) ||
!types.equal(left.type, right.type) {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "'none' only supports '==' and '!=' with an optional value")
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "'null' only supports '==' and '!=' with an optional value")
}
equal := left.kind == .None && right.kind == .None
equal := left.kind == .Null && right.kind == .Null
if op == .Ne {
equal = !equal
}
@@ -2781,7 +2781,7 @@ ct_typeinfo_value :: proc(state: ^Ct_State, target: types.Type, span: source.Spa
kind=.Array, type=fields_type, start=fields_start, count=u32(len(field_values)),
})
name_optional_type := types.optional(store, types.slice(store, types.U8, false))
record_name := ct_add_value(state, Ct_Value{kind=.None, type=name_optional_type})
record_name := ct_add_value(state, Ct_Value{kind=.Null, type=name_optional_type})
if item.name != 0 {
name_value := ct_reflection_string(state, symbol_text(checker, symbol.Id(item.name)))
name_start := u32(len(state.children))
@@ -3053,7 +3053,7 @@ ct_struct_type :: proc(
)
}
default := state.values[value]
if default.kind == .None {
if default.kind == .Null {
continue
}
children := ct_child_slice(state, default)
@@ -3616,7 +3616,7 @@ ct_write_comptime_key :: proc(state: ^Ct_State, id: Ct_Value_Id, builder: ^strin
}
strings.write_string(builder, "];")
return true
case .None:
case .Null:
strings.write_string(builder, "n;")
return true
case .Optional_Some:
@@ -4156,7 +4156,7 @@ ct_exec_if :: proc(state: ^Ct_State, statement: ast.Stmt, yield_returns: bool, d
return flow, ok
}
v := state.values[value]
if v.kind == .None {
if v.kind == .Null {
matched = false
break
}
+1 -1
View File
@@ -82,7 +82,7 @@ Expr_Kind :: enum u8 {
Undefined,
Array,
Struct,
None,
Null,
Optional_Some,
Local,
Global,
+1 -1
View File
@@ -71,7 +71,7 @@ Opcode :: enum u8 {
Poison,
String,
Aggregate,
None,
Null,
Optional_Some,
Load_Global,
Function_Address,
+1 -1
View File
@@ -30,7 +30,7 @@ keyword_kind :: proc(text: string) -> token.Kind {
case "try": return .Keyword_Try
case "catch": return .Keyword_Catch
case "mut": return .Keyword_Mut
case "none": return .Keyword_None
case "null": return .Keyword_Null
case "undefined": return .Keyword_Undefined
case "orelse": return .Keyword_Orelse
case "and": return .Keyword_And
+4 -4
View File
@@ -275,7 +275,7 @@ valid_value :: proc(
return false
}
switch instructions[value_id].op {
case .Param, .Const, .Poison, .String, .Aggregate, .None, .Optional_Some,
case .Param, .Const, .Poison, .String, .Aggregate, .Null, .Optional_Some,
.Load_Global, .Function_Address, .Address_Of, .Load, .Union_Tag, .Slice, .Length, .Slice_Ptr,
.Fallible_Error, .Extract, .Select, .Unwrap,
.Optional_Is_Some, .Optional_Value, .Orelse,
@@ -1109,10 +1109,10 @@ emit_instruction_stream :: proc(
}
fmt.sbprintf(&emitter.builder, ", %d\n", arg_index)
}
case .None:
case .Null:
item, ok := types.node(&emitter.module.types, instruction.type)
if !ok || item.kind != .Optional {
emit_recovery_value(emitter, instruction_index, instruction, "invalid optional none")
emit_recovery_value(emitter, instruction_index, instruction, "invalid optional null")
continue
}
if types.is_pointer(item.child, &emitter.module.types) {
@@ -1656,7 +1656,7 @@ emit_instruction_stream :: proc(
fmt.sbprintf(&emitter.builder, " %%optional_ok%d = extractvalue %s %%v%d, 0\n", instruction_index, llvm_type(optional_type, &emitter.module.types), instruction.a)
}
fmt.sbprintf(&emitter.builder, " br i1 %%optional_ok%d, label %%optional_continue%d, label %%optional_trap%d\noptional_trap%d:\n", instruction_index, instruction_index, instruction_index, instruction_index)
message := diagnostic_message(emitter, source.INVALID_DIAGNOSTIC, instruction.span, "attempted to unwrap none")
message := diagnostic_message(emitter, source.INVALID_DIAGNOSTIC, instruction.span, "attempted to unwrap null")
emit_trap_call(emitter, message)
fmt.sbprintf(&emitter.builder, " unreachable\noptional_continue%d:\n", instruction_index)
if types.is_pointer(item.child, &emitter.module.types) {
+2 -2
View File
@@ -437,7 +437,7 @@ add_macro_zero_expr :: proc(
return ast.INVALID_EXPR, false
}
return add_import_expr(state, ast.Expr{
kind=.None, span=span,
kind=.Null, span=span,
left=ast.INVALID_EXPR, right=ast.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
}), true
@@ -680,7 +680,7 @@ add_converted_macro_value_expr :: proc(
}, span), true
case .Null:
return add_import_expr(state, ast.Expr{
kind=.None, span=span,
kind=.Null, span=span,
left=ast.INVALID_EXPR, right=ast.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
}), true
+5 -5
View File
@@ -244,9 +244,9 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .None:
case .Null:
return append_instruction(state, ir.Instruction{
op=.None, span=expr.span, type=expr.type,
op=.Null, span=expr.span, type=expr.type,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
@@ -563,8 +563,8 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
case .Eq, .Ne, .Lt, .Le, .Gt, .Ge:
left_expr := state.hir_module.exprs[expr.left]
right_expr := state.hir_module.exprs[expr.right]
if left_expr.kind == .None || right_expr.kind == .None {
optional_expr := expr.right if left_expr.kind == .None else expr.left
if left_expr.kind == .Null || right_expr.kind == .Null {
optional_expr := expr.right if left_expr.kind == .Null else expr.left
optional := lower_nested_expr(state, optional_expr)
present := append_instruction(state, ir.Instruction{
op=.Optional_Is_Some, span=expr.span, type=types.BOOL,
@@ -716,7 +716,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
diagnostic=source.INVALID_DIAGNOSTIC,
})
_ = pop(&stack)
case .String, .Array, .Struct, .Range, .None, .Optional_Some, .Address, .Deref,
case .String, .Array, .Struct, .Range, .Null, .Optional_Some, .Address, .Deref,
.Index, .Slice, .Field, .Union_Tag, .Length, .Slice_Ptr, .Unwrap, .Orelse,
.Try, .Catch, .Not, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
last = lower_compound_expr(state, frame.expr)
+2 -2
View File
@@ -966,10 +966,10 @@ parse_primary :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
right=ast.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .Keyword_None:
case .Keyword_Null:
advance(parser)
return add_expr(parser, ast.Expr{
kind=.None,
kind=.Null,
span=tok.span,
left=ast.INVALID_EXPR,
right=ast.INVALID_EXPR,
+1 -1
View File
@@ -76,7 +76,7 @@ Kind :: enum u8 {
Keyword_Try,
Keyword_Catch,
Keyword_Mut,
Keyword_None,
Keyword_Null,
Keyword_Undefined,
Keyword_Orelse,
Keyword_And,