refactor: remove enum-map lookup wrappers

This commit is contained in:
2026-10-30 11:17:11 +01:00
parent 30a98db379
commit 31a1bf1995
14 changed files with 118 additions and 117 deletions
+23 -10
View File
@@ -54,7 +54,7 @@ render_function proc(
render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, depth usize) void ! mem.AllocError {
for 0..ast.block_statement_count(tree, block) |index| {
statement :: ast.block_statement(tree, block, index)
for 0..depth |_| try append_text(renderer, " ")
for (0..depth) |_| try append_text(renderer, " ")
match ast.stmt_kind(tree, statement) {
.declaration: try render_statement(renderer, tree, statement, "")
.expression: {
@@ -65,6 +65,22 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept
}
.break_stmt: try append_text(renderer, "break\n")
.continue_stmt: try append_text(renderer, "continue\n")
.block_stmt: {
try append_text(renderer, "block\n")
try render_block(renderer, tree, ast.statement_block(tree, statement), depth + 1)
}
.defer_stmt, .errdefer_stmt: {
cleanup :: ast.cleanup_stmt(tree, statement)
keyword :: if (ast.stmt_kind(tree, statement) == .errdefer_stmt) "errdefer" else "defer"
try append_text(renderer, keyword)
if (cleanup.capture) |capture| {
try append_text(renderer, " |")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, capture)))
try append_text(renderer, "|")
}
try append_text(renderer, "\n")
try render_block(renderer, tree, cleanup.body, depth + 1)
}
.return_stmt: {
try append_text(renderer, "return")
if (ast.return_stmt(tree, statement).value) |value| {
@@ -86,7 +102,7 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept
try append_text(renderer, "\n")
try render_block(renderer, tree, conditional.then_block, depth + 1)
if (conditional.else_block) |alternative| {
for 0..depth |_| try append_text(renderer, " ")
for (0..depth) |_| try append_text(renderer, " ")
try append_text(renderer, "else\n")
try render_block(renderer, tree, alternative, depth + 1)
}
@@ -99,7 +115,7 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept
if (assignment.compound) {
binary :: ast.binary_expr(tree, value)
try append_text(renderer, " ")
try append_text(renderer, assignment_operator_text(binary.operator))
try append_text(renderer, enummap.get(&assignment_operator_texts, binary.operator)?)
try append_text(renderer, "= ")
value = binary.right
} else {
@@ -126,7 +142,7 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept
else try append_text(renderer, "_")
if (loop.index_capture) {
try append_text(renderer, ", ")
if (loop.index) |index| try append_text(renderer, ast.source_text(tree, ast.node_span(tree, index)))
if (loop.index) |index_capture| try append_text(renderer, ast.source_text(tree, ast.node_span(tree, index_capture)))
else try append_text(renderer, "_")
}
try append_text(renderer, "|\n")
@@ -152,7 +168,8 @@ render_statement proc(
try append_text(renderer, " ")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, type)))
}
try append_text(renderer, if (statement.mutability == .constant) " :: " else " := ")
binding :: if (statement.mutability == .constant) " :: " else " := "
try append_text(renderer, binding)
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, statement.initializer)))
try append_text(renderer, "\n")
}
@@ -163,7 +180,7 @@ append_text proc(renderer @mut Renderer, text []u8) void ! mem.AllocError {
}
@hide:file
assignment_operator_texts :: $enummap.init_filled(
assignment_operator_texts :: $enummap.init_default(
ast.BinaryOperator, []u8, "", {
add = "+",
subtract = "-",
@@ -178,7 +195,3 @@ assignment_operator_texts :: $enummap.init_filled(
},
)
@hide:file
assignment_operator_text proc(operator ast.BinaryOperator) []u8 {
return enummap.get(&assignment_operator_texts, operator)?
}
+10 -9
View File
@@ -1,5 +1,6 @@
import "@std/mem"
import "@std/arraylist"
import "@std/enummap"
import "@source/ir"
import "@source/diagnostics"
@@ -579,7 +580,7 @@ execute proc(
if instruction.type == .float {
value = ir.Value{ type = .float, data = ir.ValueData{ real = -operand.data.real } }
} else {
if (operand.data.integer == ir.integer_min(instruction.type)) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
if (operand.data.integer == enummap.get(&ir.integer_minima, instruction.type)?) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
value = ir.Value{ type = instruction.type, data = ir.ValueData{ integer = -operand.data.integer } }
}
}
@@ -628,7 +629,7 @@ execute proc(
} else if ir.unsigned_integer(instruction.type) {
result :: checked_unsigned(instruction.op, left.data.unsigned, right.data.unsigned)
if result |unsigned| {
if (unsigned > ir.integer_max(instruction.type)) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
if (unsigned > enummap.get(&ir.integer_maxima, instruction.type)?) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
value = ir.Value{ type = instruction.type, data = ir.ValueData{ unsigned = unsigned } }
} else {
return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
@@ -636,7 +637,7 @@ execute proc(
} else {
result :: checked_integer(instruction.op, left.data.integer, right.data.integer)
if result |result_integer| {
if (result_integer < ir.integer_min(instruction.type) or result_integer > i64(ir.integer_max(instruction.type))) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
if (result_integer < enummap.get(&ir.integer_minima, instruction.type)? or result_integer > i64(enummap.get(&ir.integer_maxima, instruction.type)?)) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
value = ir.Value{ type = instruction.type, data = ir.ValueData{ integer = result_integer } }
} else {
return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span)
@@ -950,7 +951,7 @@ shift_integer proc(op ir.Op, left ir.Value, count u64) ir.Value {
negative :: signed and left.data.integer < 0
if (op == .shift_left_saturating) {
if (bits == 0) return left
limit :: if (negative) 1 + (mask >> 1) else ir.integer_max(left.type)
limit :: if (negative) 1 + (mask >> 1) else enummap.get(&ir.integer_maxima, left.type)?
magnitude :: if (negative) 1 + (bits xor mask) else bits
if (count >= width) return integer_from_bits(left.type, limit)
if (magnitude > (limit >> count)) return integer_from_bits(left.type, limit)
@@ -1054,28 +1055,28 @@ convert proc(source ir.Value, target ir.Type) ?ir.Value {
if (ir.unsigned_integer(target)) {
if (!(real > -1.0 and real < 18446744073709551616.0)) return null
integer :: u64(real)
if (integer > ir.integer_max(target)) return null
if (integer > enummap.get(&ir.integer_maxima, target)?) return null
result.data = ir.ValueData{ unsigned = integer }
} else {
if (!(real >= -9223372036854775808.0 and real < 9223372036854775808.0)) return null
integer :: i64(real)
if (integer < ir.integer_min(target) or integer > i64(ir.integer_max(target))) return null
if (integer < enummap.get(&ir.integer_minima, target)? or integer > i64(enummap.get(&ir.integer_maxima, target)?)) return null
result.data = ir.ValueData{ integer = integer }
}
return result
}
if (ir.unsigned_integer(source.type)) {
integer :: source.data.unsigned
if (integer > ir.integer_max(target)) return null
if (integer > enummap.get(&ir.integer_maxima, target)?) return null
if (ir.unsigned_integer(target)) result.data = ir.ValueData{ unsigned = integer }
else result.data = ir.ValueData{ integer = i64(integer) }
} else {
integer :: source.data.integer
if (ir.unsigned_integer(target)) {
if (integer < 0 or u64(integer) > ir.integer_max(target)) return null
if (integer < 0 or u64(integer) > enummap.get(&ir.integer_maxima, target)?) return null
result.data = ir.ValueData{ unsigned = u64(integer) }
} else {
if (integer < ir.integer_min(target) or integer > i64(ir.integer_max(target))) return null
if (integer < enummap.get(&ir.integer_minima, target)? or integer > i64(enummap.get(&ir.integer_maxima, target)?)) return null
result.data = ir.ValueData{ integer = integer }
}
}
+7 -15
View File
@@ -35,7 +35,7 @@ aggregate proc(type Type) bool {
}
@hide:file
integer_widths :: $enummap.init_filled(Type, usize, usize(0), {
integer_widths :: $enummap.init_default(Type, usize, usize(0), {
i8 = 8, u8 = 8,
i16 = 16, u16 = 16,
i32 = 32, u32 = 32,
@@ -52,8 +52,8 @@ unsigned_integer proc(type Type) bool {
return type == .u8 or type == .u16 or type == .u32 or type == .u64 or type == .usize
}
@hide:file
integer_maxima :: $enummap.init_filled(Type, u64, u64(0), {
#! maxima for supported integer storage types; noninteger keys are absent.
integer_maxima :: $enummap.init_default(Type, u64, u64(0), {
i8 = 127,
i16 = 32767,
i32 = 2147483647,
@@ -64,12 +64,8 @@ integer_maxima :: $enummap.init_filled(Type, u64, u64(0), {
u64 = maxval!(u64), usize = maxval!(u64),
})
integer_max proc(type Type) u64 {
return enummap.get(&integer_maxima, type)?
}
@hide:file
integer_minima :: $enummap.init_filled(Type, i64, i64(0), {
#! minima for supported integer storage types; noninteger keys are absent.
integer_minima :: $enummap.init_default(Type, i64, i64(0), {
i8 = i64(-128),
i16 = i64(-32768),
i32 = i64(-2147483648),
@@ -77,10 +73,6 @@ integer_minima :: $enummap.init_filled(Type, i64, i64(0), {
u8 = 0, u16 = 0, u32 = 0, u64 = 0, usize = 0,
})
integer_min proc(type Type) i64 {
return enummap.get(&integer_minima, type)?
}
ValueData :: union {
integer i64
# source pointers use run-wide handles; internal addresses use frame-local IDs below.
@@ -421,12 +413,12 @@ aligned_size proc(size, alignment usize) usize {
}
@hide:file
scalar_alignments :: $enummap.init_filled(Type, usize, usize(1), {
scalar_alignments :: $enummap.init_default(Type, usize, usize(1), {
float = 8, string = 8, function = 8, pointer = 8,
})
@hide:file
scalar_sizes :: $enummap.init_filled(Type, usize, usize(0), {
scalar_sizes :: $enummap.init_default(Type, usize, usize(0), {
float = 8, function = 8, pointer = 8,
string = 16,
bool = 1,
+11 -11
View File
@@ -4,14 +4,14 @@ import "@source/ir"
import "@source/diagnostics"
@hide:file
bitwise_opcodes :: $enummap.init_filled(ir.Op, []u8, "", {
bitwise_opcodes :: $enummap.init_default(ir.Op, []u8, "", {
bit_and = "and",
bit_or = "or",
bit_xor = "xor",
})
@hide:file
float_opcodes :: $enummap.init_filled(ir.Op, []u8, "", {
float_opcodes :: $enummap.init_default(ir.Op, []u8, "", {
add = "fadd",
subtract = "fsub",
multiply = "fmul",
@@ -19,14 +19,14 @@ float_opcodes :: $enummap.init_filled(ir.Op, []u8, "", {
})
@hide:file
integer_opcodes :: $enummap.init_filled(ir.Op, []u8, "", {
integer_opcodes :: $enummap.init_default(ir.Op, []u8, "", {
add = "add",
subtract = "sub",
multiply = "mul",
})
@hide:file
float_predicates :: $enummap.init_filled(ir.Op, []u8, "", {
float_predicates :: $enummap.init_default(ir.Op, []u8, "", {
equal = "oeq",
not_equal = "une",
less = "olt",
@@ -36,7 +36,7 @@ float_predicates :: $enummap.init_filled(ir.Op, []u8, "", {
})
@hide:file
integer_predicates :: $enummap.init_filled(ir.Op, []u8, "", {
integer_predicates :: $enummap.init_default(ir.Op, []u8, "", {
equal = "eq",
not_equal = "ne",
less = "lt",
@@ -46,7 +46,7 @@ integer_predicates :: $enummap.init_filled(ir.Op, []u8, "", {
})
@hide:file
conversion_upper_bounds :: $enummap.init_filled(ir.Type, []u8, "", {
conversion_upper_bounds :: $enummap.init_default(ir.Type, []u8, "", {
i8 = "1.280000e+02",
i16 = "3.276800e+04",
i32 = "2.147483648e+09",
@@ -387,7 +387,7 @@ emit_instruction proc(state @mut State, block @ir.Block, instruction ir.Instruct
minimum :: fresh(state)
negative_one :: fresh(state)
overflow :: fresh(state)
try io.print(" %r{} = icmp eq i{} %r{}, {}\n", output, {minimum, bits, left, ir.integer_min(instruction.type)})
try io.print(" %r{} = icmp eq i{} %r{}, {}\n", output, {minimum, bits, left, enummap.get(&ir.integer_minima, instruction.type)?})
try io.print(" %r{} = icmp eq i{} %r{}, -1\n", output, {negative_one, bits, right})
try io.print(" %r{} = and i1 %r{}, %r{}\n", output, {overflow, minimum, negative_one})
try check_failure(state, overflow, .integer_overflow, instruction.span)
@@ -472,9 +472,9 @@ emit_shift proc(state @mut State, instruction ir.Instruction) usize ! io.WriteEr
if (signed) {
negative :: fresh(state)
try io.print(" %r{} = icmp slt i{} %r{}, 0\n", output, {negative, bits, left})
try io.print(" %r{} = select i1 %r{}, i{} {}, i{} {}\n", output, {limit, negative, bits, ir.integer_min(instruction.type), bits, ir.integer_max(instruction.type)})
try io.print(" %r{} = select i1 %r{}, i{} {}, i{} {}\n", output, {limit, negative, bits, enummap.get(&ir.integer_minima, instruction.type)?, bits, enummap.get(&ir.integer_maxima, instruction.type)?})
} else {
try io.print(" %r{} = or i{} 0, {}\n", output, {limit, bits, ir.integer_max(instruction.type)})
try io.print(" %r{} = or i{} 0, {}\n", output, {limit, bits, enummap.get(&ir.integer_maxima, instruction.type)?})
}
result :: fresh(state)
try io.print(" %r{} = select i1 %r{}, i{} %r{}, i{} %r{}\n", output, {result, saturate, bits, limit, bits, shifted})
@@ -684,13 +684,13 @@ emit_conversion proc(state @mut State, instruction ir.Instruction) usize ! io.Wr
}
if (!source_unsigned and (destination_unsigned or destination_bits < source_bits)) {
failed :: fresh(state)
try io.print(" %r{} = icmp slt i{} %r{}, {}\n", output, {failed, source_bits, operand, ir.integer_min(destination)})
try io.print(" %r{} = icmp slt i{} %r{}, {}\n", output, {failed, source_bits, operand, enummap.get(&ir.integer_minima, destination)?})
try check_failure(state, failed, .integer_overflow, instruction.span)
}
if (destination_bits < source_bits or (source_unsigned and !destination_unsigned and destination_bits == source_bits)) {
failed :: fresh(state)
predicate []u8 :: if (source_unsigned) "ugt" else "sgt"
try io.print(" %r{} = icmp {s} i{} %r{}, {}\n", output, {failed, predicate, source_bits, operand, ir.integer_max(destination)})
try io.print(" %r{} = icmp {s} i{} %r{}, {}\n", output, {failed, predicate, source_bits, operand, enummap.get(&ir.integer_maxima, destination)?})
try check_failure(state, failed, .integer_overflow, instruction.span)
}
if (source_bits == destination_bits) return operand
+5 -10
View File
@@ -71,7 +71,7 @@ emit proc(
.invalid_shift_count,
]
for (memory_codes) |code| {
try io.print("@memory_{s} = private constant ", output, {memory_symbol(code)})
try io.print("@memory_{s} = private constant ", output, {enummap.get(&memory_symbols, code)?})
try bytes_constant(output, enummap.get(diagnostics.Code, []u8, &diagnostics.messages, code)?, false)
try io.write_all(output, "\n")
}
@@ -212,7 +212,7 @@ write_type proc(output io.Writer, module @ir.Module, type Type) void ! io.WriteE
}
@hide:file
abi_extensions :: $enummap.init_filled(ir.Type, []u8, "", {
abi_extensions :: $enummap.init_default(ir.Type, []u8, "", {
i8 = "signext",
i16 = "signext",
u8 = "zeroext",
@@ -502,7 +502,7 @@ check_local proc(state @State, slot u32, read bool, span diagnostics.Span) void
}
@hide:file
memory_symbols :: $enummap.init_filled(diagnostics.Code, []u8, "", {
memory_symbols :: $enummap.init_default(diagnostics.Code, []u8, "", {
null_unwrap = "null_unwrap",
invalid_slice_bounds = "invalid_slice_bounds",
sentinel_mismatch = "sentinel_mismatch",
@@ -514,17 +514,12 @@ memory_symbols :: $enummap.init_filled(diagnostics.Code, []u8, "", {
})
@hide:file
trap_symbols :: $enummap.init_filled(diagnostics.Code, []u8, "", {
trap_symbols :: $enummap.init_default(diagnostics.Code, []u8, "", {
integer_overflow = "overflow",
index_out_of_bounds = "bounds",
inactive_union_field = "inactive_union",
})
@hide:file
memory_symbol proc(code diagnostics.Code) []u8 {
return enummap.get(&memory_symbols, code)?
}
@hide:file
trap proc(state @State, code diagnostics.Code, span diagnostics.Span) void ! io.WriteError {
position :: location(state.line_starts, span)
@@ -533,7 +528,7 @@ trap proc(state @State, code diagnostics.Code, span diagnostics.Span) void ! io.
length :: message.len
try io.print(" call void @trap(i64 -1, i64 {}, i64 {}, i64 {}, ptr @", state.output, {usize(span.source), position.line, position.column})
if (symbol) |name| try io.write_all(state.output, name)
else try io.print("memory_{s}", state.output, {memory_symbol(code)})
else try io.print("memory_{s}", state.output, {enummap.get(&memory_symbols, code)?})
try io.print(", i64 {})\n unreachable\n", state.output, {length})
}
+11 -16
View File
@@ -183,7 +183,7 @@ lower_module proc(
}
@hide:file
base_types :: $enummap.init_filled(
base_types :: $enummap.init_default(
typecheck.TypeKind, ir.Type, ir.Type.invalid, {
int = .int,
usize = .usize,
@@ -957,7 +957,7 @@ lower_statement proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | d
array_type = try array_shape(state, pointer.element), span = ast.node_span(tree, id),
})
} else try emit(state, ir.Instruction{
op = binary_op(expression.operator), type = type, left = old, right = right,
op = enummap.get(&binary_ops, expression.operator)?, type = type, left = old, right = right,
span = ast.node_span(tree, id),
})
_ = try emit(state, ir.Instruction{
@@ -1056,7 +1056,7 @@ lower_statement proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | d
}
@hide:file
binary_ops :: $enummap.init_filled(
binary_ops :: $enummap.init_default(
ast.BinaryOperator, ir.Op, ir.Op.constant, {
add = .add,
subtract = .subtract,
@@ -1078,7 +1078,7 @@ binary_ops :: $enummap.init_filled(
)
@hide:file
unary_ops :: $enummap.init_filled(
unary_ops :: $enummap.init_default(
ast.UnaryOperator, ir.Op, ir.Op.constant, {
negate = .negate,
logical_not = .logical_not,
@@ -1086,11 +1086,6 @@ unary_ops :: $enummap.init_filled(
},
)
@hide:file
binary_op proc(operator ast.BinaryOperator) ir.Op {
return enummap.get(&binary_ops, operator)?
}
@hide:file
lower_logical proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError | diagnostics.CapacityError) {
expression :: ast.binary_expr(state.tree, id)
@@ -1892,8 +1887,8 @@ lower_builtin proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError
if (mem.eql(name, "maxval") or mem.eql(name, "minval")) {
type :: lower_type(state, typecheck.type_of(state.checked, id))
value := ir.Value{ type = type }
if (mem.eql(name, "maxval")) value.data = ir.ValueData{ unsigned = ir.integer_max(type) }
else value.data = ir.ValueData{ integer = ir.integer_min(type) }
if (mem.eql(name, "maxval")) value.data = ir.ValueData{ unsigned = enummap.get(&ir.integer_maxima, type)? }
else value.data = ir.ValueData{ integer = enummap.get(&ir.integer_minima, type)? }
return try constant(state, value, span)
}
if (mem.eql(name, "divtrunc")) {
@@ -2264,9 +2259,9 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr
}
if (expression.operator == .negate and ir.integer_bits(type) != 0 and !ir.unsigned_integer(type) and ast.expr_kind(tree, expression.operand) == .literal_int) {
text :: ast.literal_text(tree, expression.operand)
magnitude_limit :: ir.integer_max(type) + 1
magnitude_limit :: enummap.get(&ir.integer_maxima, type)? + 1
if (integer_magnitude(text, magnitude_limit)) |magnitude| {
if (magnitude == magnitude_limit) return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = ir.integer_min(type) } }, span)
if (magnitude == magnitude_limit) return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = enummap.get(&ir.integer_minima, type)? } }, span)
}
}
operand :: try lower_expression(state, expression.operand)
@@ -2302,7 +2297,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr
array_type = try array_shape(state, pointer.element), span = span,
})
}
op :: binary_op(expression.operator)
op :: enummap.get(&binary_ops, expression.operator)?
return try emit(state, ir.Instruction{ op = op, type = type, left = left, right = right, span = span })
}
.call: {
@@ -2392,9 +2387,9 @@ lower_number proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError
text :: ast.literal_text(state.tree, id)
type :: lower_type(state, typecheck.type_of(state.checked, id))
if (ir.integer_bits(type) != 0 and !ir.unsigned_integer(type)) {
if (integer_magnitude(text, ir.integer_max(type))) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = i64(magnitude) } }, span)
if (integer_magnitude(text, enummap.get(&ir.integer_maxima, type)?)) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = i64(magnitude) } }, span)
} else if (ir.unsigned_integer(type)) {
if (integer_magnitude(text, ir.integer_max(type))) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ unsigned = magnitude } }, span)
if (integer_magnitude(text, enummap.get(&ir.integer_maxima, type)?)) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ unsigned = magnitude } }, span)
} else {
value :: strconv.parse_float(state.module.allocator, text) catch |err| {
match err {
+12 -31
View File
@@ -432,7 +432,7 @@ parse_loop_control proc(state @mut State, allow_else bool) ast.NodeId ! ParseErr
@hide:file
parse_assignment proc(state @mut State, target ast.NodeId, allow_else bool) ast.NodeId ! ParseError {
operator :: assignment_operator(current(state).kind)
operator :: enummap.get(&assignment_operators, current(state).kind)
state.next_token += 1
value := try parse_expr(state)
if (
@@ -939,7 +939,7 @@ parse_function_type proc(state @mut State, start ast.Span, invalid bool) ast.Nod
}
@hide:file
type_starters :: $enummap.init_filled(lexer.TokenKind, bool, false, {
type_starters :: $enummap.init_default(lexer.TokenKind, bool, false, {
ident = true, open_bracket = true, struct = true, c_struct = true, opaque = true,
enum = true, union = true, distinct = true, alias = true, match = true, if = true,
at = true, star = true, question = true, open_paren = true, proc = true, c_func = true,
@@ -951,7 +951,7 @@ starts_type proc(kind lexer.TokenKind) bool {
}
@hide:file
member_names :: $enummap.init_filled(lexer.TokenKind, bool, false, {
member_names :: $enummap.init_default(lexer.TokenKind, bool, false, {
ident = true, if = true, else = true, for = true, inline = true, while = true,
proc = true, return = true, yield = true, break = true, continue = true,
true = true, false = true, and = true, or = true, xor = true, mut = true,
@@ -1388,7 +1388,7 @@ parse_expr_bp proc(state @mut State, min_bp BindingPowerScalar) ast.NodeId ! Par
skip_operand_newlines(state)
token := current(state)
expression_start :: state.next_token
left := if (prefix_binding_power(token.kind)) |right_bp| {
left := if (enummap.get(&prefix_binding_powers, token.kind)) |right_bp| {
state.next_token += 1
operand :: try parse_expr_bp(state, right_bp)
operand_span :: ast.builder_span(state.builder, operand)
@@ -1518,7 +1518,7 @@ parse_expr_bp proc(state @mut State, min_bp BindingPowerScalar) ast.NodeId ! Par
continue
}
if (token.kind == .pipe and !state.allow_bit_or) break
if (infix_binding_power(token.kind)) |power| {
if (enummap.get(&infix_binding_powers, token.kind)) |power| {
if (power.left < min_bp) break
state.next_token += 1
right :: try parse_expr_bp(state, power.right)
@@ -1531,7 +1531,7 @@ parse_expr_bp proc(state @mut State, min_bp BindingPowerScalar) ast.NodeId ! Par
end = right_span.end,
source = left_span.source,
},
binary_operator(token.kind),
enummap.get(&binary_operators, token.kind)?,
left,
right,
)
@@ -1975,7 +1975,7 @@ skip_continuation_newlines proc(state @mut State) void {
and kind != .close_bracket and kind != .open_bracket
and kind != .range and kind != .range_inclusive
and kind != .pipe and kind != .bang and kind != .catch
and infix_binding_power(kind) == null
and enummap.get(&infix_binding_powers, kind) == null
) state.next_token = start
}
@@ -2122,19 +2122,14 @@ consume_either proc(state @mut State, kinds []lexer.TokenKind) lexer.Token ! Syn
}
@hide:file
prefix_binding_powers :: $enummap.init_filled(
prefix_binding_powers :: $enummap.init_default(
lexer.TokenKind, BindingPowerScalar, BindingPowerScalar(0), {
minus = BindingPowerScalar(50), bang = BindingPowerScalar(50), tilde = BindingPowerScalar(50),
ampersand = BindingPowerScalar(50), try = BindingPowerScalar(50),
})
@hide:file
prefix_binding_power proc(kind lexer.TokenKind) ?BindingPowerScalar {
return enummap.get(&prefix_binding_powers, kind)
}
@hide:file
infix_binding_powers :: $enummap.init_filled(lexer.TokenKind, BindingPower,
infix_binding_powers :: $enummap.init_default(lexer.TokenKind, BindingPower,
BindingPower{ left = BindingPowerScalar(0), right = BindingPowerScalar(0) },
{
or = BindingPower{ left = BindingPowerScalar(2), right = BindingPowerScalar(3) },
@@ -2159,12 +2154,7 @@ infix_binding_powers :: $enummap.init_filled(lexer.TokenKind, BindingPower,
)
@hide:file
infix_binding_power proc(kind lexer.TokenKind) ?BindingPower {
return enummap.get(&infix_binding_powers, kind)
}
@hide:file
binary_operators :: $enummap.init_filled(
binary_operators :: $enummap.init_default(
lexer.TokenKind,
ast.BinaryOperator,
ast.BinaryOperator.add, {
@@ -2189,18 +2179,13 @@ binary_operators :: $enummap.init_filled(
},
)
@hide:file
binary_operator proc(kind lexer.TokenKind) ast.BinaryOperator {
return enummap.get(&binary_operators, kind)?
}
@hide:file
is_assignment_operator proc(kind lexer.TokenKind) bool {
return kind == .equal or assignment_operator(kind) != null
return kind == .equal or enummap.get(&assignment_operators, kind) != null
}
@hide:file
assignment_operators :: $enummap.init_filled(lexer.TokenKind, ast.BinaryOperator, ast.BinaryOperator.add, {
assignment_operators :: $enummap.init_default(lexer.TokenKind, ast.BinaryOperator, ast.BinaryOperator.add, {
plus_equal = .add,
minus_equal = .subtract,
star_equal = .multiply,
@@ -2213,7 +2198,3 @@ assignment_operators :: $enummap.init_filled(lexer.TokenKind, ast.BinaryOperator
shift_left_saturating_equal = .shift_left_saturating,
})
@hide:file
assignment_operator proc(kind lexer.TokenKind) ?ast.BinaryOperator {
return enummap.get(&assignment_operators, kind)
}
+27
View File
@@ -6,6 +6,7 @@ import "@source/diagnostics"
import "@source/strpool"
import "@source/lexer"
import "@source/ast"
import "@source/ast/renderer"
parses_expression_precedence_through_tree_views test {
strings := strpool.init(mem.c_allocator)
@@ -2375,3 +2376,29 @@ keeps_type_composition_and_capture_pipes_with_bitwise_or test {
try testing.expect(ast.while_stmt(&tree, ast.block_statement(&tree, body, 4)).capture != null)
try testing.expect(ast.for_stmt(&tree, ast.block_statement(&tree, body, 5)).capture != null)
}
renders_compound_updates_in_scoped_statement_bodies test {
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
`run proc() void {
` value := 1
` { value += 2 }
` defer { value -= 3 }
` errdefer |err| { value xor= 4 }
` for (0..2) |item, index| value |= 5
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
output := renderer.init(mem.c_allocator)
defer renderer.deinit(&output)
try renderer.render(&output, &tree)
expected :: "package\n function run\n declaration value := 1\n block\n assignment value += 2\n defer\n assignment value -= 3\n errdefer |err|\n assignment value xor= 4\n for 0..2 |item, index|\n assignment value |= 5\n"
try testing.expect(mem.eql(output.bytes.items, expected))
}
+4 -9
View File
@@ -931,7 +931,7 @@ check_annotation proc(state @mut State, id ast.NodeId, allow_void bool) Type ! (
match binding.kind {
.invalid: type = invalid_type(binding.data.diagnostic)
.builtin: {
type.kind = builtin_kind(binding.data.builtin)
type.kind = enummap.get(&builtin_kinds, binding.data.builtin)?
if (binding.data.builtin == .unavailable)
type = invalid_type(try diagnostics.add(state.diagnostics, .invalid_operand, ast.node_span(state.tree, id)))
if (type.kind == .anyopaque and state.pointer_depth == 0) {
@@ -1551,17 +1551,12 @@ builtin_kinds :: $enummap.init(sema.BuiltinType, TypeKind, {
unavailable = .none,
})
@hide:file
builtin_kind proc(type sema.BuiltinType) TypeKind {
return enummap.get(&builtin_kinds, type)?
}
@hide:file
conversion_kind proc(state @State, id ast.NodeId) TypeKind {
callee :: ast.call_expr(state.tree, id).callee
binding :: sema.binding(state.resolution, callee)
if (binding.kind != .builtin) return .none
kind :: builtin_kind(binding.data.builtin)
kind :: enummap.get(&builtin_kinds, binding.data.builtin)?
return if (numeric_kind(kind)) kind else .none
}
@@ -1589,7 +1584,7 @@ bitwise proc(operator ast.BinaryOperator) bool {
}
@hide:file
integer_widths :: $enummap.init_filled(
integer_widths :: $enummap.init_default(
TypeKind, usize, usize(0), {
i8 = 8, u8 = 8,
i16 = 16, u16 = 16,
@@ -2512,7 +2507,7 @@ evaluate_integer proc(state @mut State, id ast.NodeId, allow_local bool) ?Consta
type_binding :: sema.binding(state.resolution, annotation)
if (
!integer_kind(state.types[usize(annotation)].kind)
and (type_binding.kind != .builtin or !integer_kind(builtin_kind(type_binding.data.builtin)))
and (type_binding.kind != .builtin or !integer_kind(enummap.get(&builtin_kinds, type_binding.data.builtin)?))
) return null
}
return evaluate_integer(state, declaration.initializer, allow_local)
+1 -1
View File
@@ -5297,7 +5297,7 @@ replace proc(state @mut State, target, source ast.NodeId) void ! mem.AllocError
}
@hide:file
builtin_identities :: $enummap.init_filled(
builtin_identities :: $enummap.init_default(
sema.BuiltinType,
sema.BuiltinType,
sema.BuiltinType.type, {