refactor: remove enum-map lookup wrappers
This commit is contained in:
@@ -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)?
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, {
|
||||
|
||||
Reference in New Issue
Block a user