feat: specialize generic type and value parameters

This commit is contained in:
2026-10-26 13:10:52 +01:00
parent 9058135326
commit 6886d743b5
18 changed files with 2499 additions and 103 deletions
+10 -57
View File
@@ -1768,6 +1768,10 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr
}
if (typecheck.is_union_variant(state.checked, id)) return try lower_union(state, id)
match ast.expr_kind(tree, id) {
.typed_constant: {
if (trap_type(state, id)) return ir.no_value
return try lower_as(state, ast.typed_constant(tree, id).value, typecheck.type_of(state.checked, id))
}
.invalid: {
invalid :: ast.invalid(tree, id)
trap(state, invalid.diagnostic, invalid.span)
@@ -1849,7 +1853,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr
if (trap_type(state, id)) return ir.no_value
return try constant(state, ir.Value{
type = .bool,
data = ir.ValueData{ boolean = mem.eql(ast.source_text(tree, span), "true") },
data = ir.ValueData{ boolean = mem.eql(ast.literal_text(tree, id), "true") },
}, span)
}
.literal_string: {
@@ -1959,7 +1963,7 @@ 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.source_text(tree, ast.node_span(tree, expression.operand))
text :: ast.literal_text(tree, expression.operand)
magnitude_limit :: ir.integer_max(type) + 1
if (integer_magnitude(text, magnitude_limit)) |magnitude| {
if (magnitude == magnitude_limit) {
@@ -2099,7 +2103,7 @@ exact_float_integer proc(text []u8, value f64) bool {
@hide:file
lower_number proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError | diagnostics.CapacityError) {
span :: ast.node_span(state.tree, id)
text :: ast.source_text(state.tree, span)
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| {
@@ -2129,14 +2133,6 @@ lower_number proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError
return ir.no_value
}
@hide:file
hex_digit proc(byte u8) ?u8 {
if (byte >= '0' and byte <= '9') return byte - '0'
if (byte >= 'a' and byte <= 'f') return byte - 'a' + 10
if (byte >= 'A' and byte <= 'F') return byte - 'A' + 10
return null
}
@hide:file
lower_string proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError | diagnostics.CapacityError) {
span :: ast.node_span(state.tree, id)
@@ -2147,57 +2143,14 @@ lower_string proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError
length := usize(0)
cursor := usize(1)
end :: text.len - 1
valid := true
while (cursor < end) {
byte := text[cursor]
cursor += 1
if (byte == '\\') {
if (cursor >= end) {
valid = false
break
}
escape :: text[cursor]
cursor += 1
match escape {
'\\': byte = '\\'
'"': byte = '"'
'n': byte = '\n'
'r': byte = '\r'
't': byte = '\t'
'0': byte = 0
'x': {
if (end - cursor < 2) {
valid = false
break
}
high := u8(0)
low := u8(0)
if (hex_digit(text[cursor])) |digit| high = digit
else {
valid = false
break
}
if (hex_digit(text[cursor + 1])) |digit| low = digit
else {
valid = false
break
}
byte = high * 16 + low
cursor += 2
}
else: {
valid = false
break
}
}
byte :: ast.string_next(text, &cursor) catch |_| {
trap(state, try diagnostics.add(state.diagnostics, .invalid_escape, span), span)
return ir.no_value
}
owned[length] = byte
length += 1
}
if (!valid) {
trap(state, try diagnostics.add(state.diagnostics, .invalid_escape, span), span)
return ir.no_value
}
if (state.module.strings.items.len > usize(maxval!(ir.StringId)))
return .out_of_memory