refactor: integrate compilation-owned identifier interning

This commit is contained in:
2026-10-24 23:47:00 +02:00
parent 0593786553
commit 675fa5049f
17 changed files with 626 additions and 389 deletions
+37 -6
View File
@@ -16,6 +16,7 @@ import "@std/debug"
import "@std/mem"
import "@std/arraylist"
import "@source/diagnostics"
import "@source/strpool"
Span :: alias diagnostics.Span
DiagnosticId :: alias diagnostics.DiagnosticId
@@ -114,6 +115,7 @@ NodeKind :: enum {
NodeData :: union {
node_id NodeId
extra u32
name_id strpool.StringId
diagnostic DiagnosticId
mutability Mutability
unary_operator UnaryOperator
@@ -295,8 +297,15 @@ add_literal proc(builder @mut Builder, kind LiteralKind, span Span) NodeId ! mem
return try add_node(builder, Node{ kind = node_kind }, span)
}
add_identifier proc(builder @mut Builder, span Span) NodeId ! mem.AllocError {
return try add_node(builder, Node{ kind = .expr_identifier }, span)
add_identifier proc(
builder @mut Builder,
span Span,
interned_name strpool.StringId,
) NodeId ! mem.AllocError {
return try add_node(builder, Node{
kind = .expr_identifier,
main = NodeData{ name_id = interned_name },
}, span)
}
add_unary proc(
@@ -475,6 +484,7 @@ add_statement_decl proc(
builder @mut Builder,
span Span,
name Span,
interned_name strpool.StringId,
type ?NodeId,
mutability Mutability,
initializer NodeId,
@@ -488,16 +498,23 @@ add_statement_decl proc(
kind = .stmt_decl,
main = NodeData{ extra = extra },
data0 = NodeData{ mutability = mutability },
data1 = NodeData{ name_id = interned_name },
}, span)
}
add_param proc(builder @mut Builder, span, name Span, type NodeId) NodeId ! mem.AllocError {
add_param proc(
builder @mut Builder,
span, name Span,
interned_name strpool.StringId,
type NodeId,
) NodeId ! mem.AllocError {
extra :: try add_extra(builder, name.start)
_ = try add_extra(builder, name.end)
return try add_node(builder, Node{
kind = .param_decl,
main = NodeData{ extra = extra },
data0 = NodeData{ node_id = type },
data1 = NodeData{ name_id = interned_name },
}, span)
}
@@ -505,6 +522,7 @@ add_function_decl proc(
builder @mut Builder,
span Span,
name Span,
interned_name strpool.StringId,
return_type NodeId,
params []NodeId,
body NodeId,
@@ -513,6 +531,7 @@ add_function_decl proc(
_ = try add_extra(builder, name.start)
_ = try add_extra(builder, name.end)
_ = try add_extra(builder, u32(return_type))
_ = try add_extra(builder, u32(interned_name))
for (params) |parameter| _ = try add_extra(builder, u32(parameter))
return try add_node(builder, Node{
kind = .func_decl,
@@ -579,6 +598,18 @@ node_count proc(tree @Tree) usize {
return tree.storage.nodes.items.len
}
#! returns the identifier's identity in the compilation-owned string pool.
#! accepts identifiers, declarations, and parameters; source spans remain available in typed views.
name_id proc(tree @Tree, id NodeId) strpool.StringId {
node :: get_node(&tree.storage, id)
return match node.kind {
.expr_identifier: node.main.name_id
.stmt_decl, .param_decl: node.data1.name_id
.func_decl: strpool.StringId(tree.storage.extra.items[usize(node.main.extra) + 3])
else: unreachable
}
}
package_decl_count proc(tree @Tree) usize {
root :: get_node(&tree.storage, tree.root)
debug.assert(root.kind == .package)
@@ -707,14 +738,14 @@ function_decl proc(tree @Tree, id NodeId) FunctionDeclView {
function_param_count proc(tree @Tree, id NodeId) usize {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .func_decl)
return usize(node.data1.extra - node.main.extra - 3)
return usize(node.data1.extra - node.main.extra - 4)
}
function_param proc(tree @Tree, id NodeId, index usize) NodeId {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .func_decl)
debug.assert(index < usize(node.data1.extra - node.main.extra - 3))
return NodeId(tree.storage.extra.items[usize(node.main.extra) + 3 + index])
debug.assert(index < usize(node.data1.extra - node.main.extra - 4))
return NodeId(tree.storage.extra.items[usize(node.main.extra) + 4 + index])
}
param proc(tree @Tree, id NodeId) ParamView {
+11 -1
View File
@@ -1,7 +1,11 @@
import "@std/mem"
import "@std/testing"
import "@source/strpool"
exposes_typed_declaration_views test {
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
value_id :: try strpool.intern(&strings, "value")
builder := init_builder(mem.c_allocator, "value :: 42")
defer deinit_builder(&builder)
@@ -11,6 +15,7 @@ exposes_typed_declaration_views test {
&builder,
Span{ start = 0, end = 11 },
value_name,
value_id,
null,
.constant,
value,
@@ -23,6 +28,7 @@ exposes_typed_declaration_views test {
try testing.expect_equal(1, package_decl_count(&tree))
decl :: package_decl(&tree, 0)
try testing.expect_equal(DeclKind.statement, decl_kind(&tree, decl))
try testing.expect_equal(value_id, name_id(&tree, decl))
statement :: statement_decl(&tree, decl)
try testing.expect_equal(value_name.start, statement.name.start)
@@ -34,11 +40,14 @@ exposes_typed_declaration_views test {
}
exposes_array_type_literal_and_index_views test {
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
element_id :: try strpool.intern(&strings, "int")
builder := init_builder(mem.c_allocator, "")
defer deinit_builder(&builder)
span :: Span{ start = 0, end = 0 }
count :: try add_literal(&builder, .int, span)
element :: try add_identifier(&builder, span)
element :: try add_identifier(&builder, span, element_id)
row :: try add_array_type(&builder, span, count, element, false)
matrix :: try add_array_type(&builder, span, null, row, true)
elements [2]NodeId :: [count, element]
@@ -55,6 +64,7 @@ exposes_array_type_literal_and_index_views test {
try testing.expect_equal(count, array_type(&tree, row).count?)
try testing.expect(!array_type(&tree, row).mutable)
try testing.expect_equal(element, array_type(&tree, row).element)
try testing.expect_equal(element_id, name_id(&tree, element))
try testing.expect_equal(ExprKind.array_literal, expr_kind(&tree, literal))
try testing.expect_equal(2, array_element_count(&tree, literal))
try testing.expect_equal(count, array_element(&tree, literal, 0))
+3 -3
View File
@@ -7,8 +7,8 @@ import "@source/parser"
import "@source/ast"
renders_array_annotations_literals_and_indexed_assignments test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -19,7 +19,7 @@ renders_array_annotations_literals_and_indexed_assignments test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
renderer := init(mem.c_allocator)
+12 -8
View File
@@ -36,7 +36,7 @@ keywords strmap.StaticStringMap(TokenKind) :: strmap.init([
])
#! owns token storage and retains its allocator; release with deinit.
#! identifier IDs refer to strings in the separately owned strpool.strings.
#! identifier IDs belong to the compilation's separately owned string pool.
State :: struct {
tokens arraylist.ArrayList(Token)
}
@@ -46,17 +46,17 @@ init proc(allocator mem.Allocator) State {
return State{ tokens = arraylist.init(allocator) }
}
#! releases token storage with the retained allocator, without releasing strpool.strings.
#! releases token storage with the retained allocator, without releasing identifier strings.
deinit proc(state @mut State) void {
arraylist.deinit(&state.tokens)
}
#! borrows `program` and `diagnostic_store` during scanning; tokens remain state-owned.
#! token allocation uses the retained allocator; identifiers use strpool.strings's allocator.
#! initialize strpool.strings before scanning and keep it alive while using identifier IDs.
#! borrows `program`, `pool`, and `diagnostic_store`; tokens remain state-owned.
#! identifier storage uses the pool's allocator; keep the pool alive while using their IDs.
scan proc(
state @mut State,
program []u8,
pool @mut strpool.StringPool,
diagnostic_store @mut diagnostics.Store,
) void ! (mem.AllocError | strpool.InternError | diagnostics.CapacityError | SourceError) {
if (program.len > usize(maxval!(u32))) return .source_too_large
@@ -82,7 +82,7 @@ scan proc(
if is_alpha(char) or char == '_' {
start :: cursor
result :: scan_ident(start, program)
result :: try scan_ident(start, program, pool)
try add_token(state, Token{
span = make_span(start, result.end),
kind = result.kind,
@@ -286,7 +286,11 @@ ScanIdentResult :: struct {
}
@hide:file
scan_ident proc(start usize, program []u8) ScanIdentResult {
scan_ident proc(
start usize,
program []u8,
pool @mut strpool.StringPool,
) ScanIdentResult ! (mem.AllocError | strpool.InternError) {
cursor := start + 1
while (
cursor < program.len
@@ -302,7 +306,7 @@ scan_ident proc(start usize, program []u8) ScanIdentResult {
# don't intern keywords (already O(1) lookup via token kind)
kind :: strmap.get(&keywords, program[start..cursor]) orelse .ident
str_id :: if (kind == .ident)
strpool.intern(&strpool.strings, program[start..cursor]) catch strpool.no_str
try strpool.intern(pool, program[start..cursor])
else
strpool.no_str
return ScanIdentResult{ end = cursor, kind = kind, str_id = str_id }
+103 -26
View File
@@ -4,14 +4,14 @@ import "@source/diagnostics"
import "@source/strpool"
reports_invalid_input_and_keeps_scanning test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
try scan(&state, "if name # comment\n$1. 2 3.5 \"hi\"", &diagnostic_store)
try scan(&state, "if name # comment\n$1. 2 3.5 \"hi\"", &pool, &diagnostic_store)
try testing.expect_equal(8, state.tokens.items.len)
try testing.expect_equal(TokenKind.if, state.tokens.items[0].kind)
@@ -25,21 +25,21 @@ reports_invalid_input_and_keeps_scanning test {
try testing.expect_equal(2, diagnostics.count(&diagnostic_store))
try testing.expect_equal(
"name",
strpool.get_str(&strpool.strings, state.tokens.items[1].data.str_id)?,
strpool.get_str(&pool, state.tokens.items[1].data.str_id)?,
)
try testing.expect_equal(u32(3), state.tokens.items[1].span.start)
try testing.expect_equal(u32(7), state.tokens.items[1].span.end)
}
reserves_boolean_keywords_and_scans_comparisons test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
source :: "true false bool trueish == != < <= > >="
try scan(&state, source, &diagnostic_store)
try scan(&state, source, &pool, &diagnostic_store)
expected [11]TokenKind :: [
TokenKind.true, .false, .ident, .ident,
.equal_equal, .not_equal, .less, .less_equal, .greater, .greater_equal, .eof,
@@ -50,29 +50,29 @@ reserves_boolean_keywords_and_scans_comparisons test {
try testing.expect_equal(u32(4), state.tokens.items[0].span.end)
try testing.expect_equal(u32(5), state.tokens.items[1].span.start)
try testing.expect_equal(u32(10), state.tokens.items[1].span.end)
try testing.expect_equal("bool", strpool.get_str(&strpool.strings, state.tokens.items[2].data.str_id)?)
try testing.expect_equal("bool", strpool.get_str(&pool, state.tokens.items[2].data.str_id)?)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
}
scans_logical_operators_without_splitting_identifiers test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
source :: "and or android orbit and_1 or2 ! != !! !true"
try scan(&state, source, &diagnostic_store)
try scan(&state, source, &pool, &diagnostic_store)
expected [13]TokenKind :: [
TokenKind.and, .or, .ident, .ident, .ident, .ident,
.bang, .not_equal, .bang, .bang, .bang, .true, .eof,
]
try testing.expect_equal(expected.len, state.tokens.items.len)
for (expected) |kind, index| try testing.expect_equal(kind, state.tokens.items[index].kind)
try testing.expect_equal("android", strpool.get_str(&strpool.strings, state.tokens.items[2].data.str_id)?)
try testing.expect_equal("orbit", strpool.get_str(&strpool.strings, state.tokens.items[3].data.str_id)?)
try testing.expect_equal("and_1", strpool.get_str(&strpool.strings, state.tokens.items[4].data.str_id)?)
try testing.expect_equal("or2", strpool.get_str(&strpool.strings, state.tokens.items[5].data.str_id)?)
try testing.expect_equal("android", strpool.get_str(&pool, state.tokens.items[2].data.str_id)?)
try testing.expect_equal("orbit", strpool.get_str(&pool, state.tokens.items[3].data.str_id)?)
try testing.expect_equal("and_1", strpool.get_str(&pool, state.tokens.items[4].data.str_id)?)
try testing.expect_equal("or2", strpool.get_str(&pool, state.tokens.items[5].data.str_id)?)
try testing.expect_equal(u32(31), state.tokens.items[6].span.start)
try testing.expect_equal(u32(32), state.tokens.items[6].span.end)
try testing.expect_equal(u32(33), state.tokens.items[7].span.start)
@@ -81,14 +81,14 @@ scans_logical_operators_without_splitting_identifiers test {
}
scans_loop_controls_with_exact_keyword_boundaries test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
source :: "break continue breakfast continued break_1 continue2"
try scan(&state, source, &diagnostic_store)
try scan(&state, source, &pool, &diagnostic_store)
expected [7]TokenKind :: [.break, .continue, .ident, .ident, .ident, .ident, .eof]
try testing.expect_equal(expected.len, state.tokens.items.len)
for (expected) |kind, index| try testing.expect_equal(kind, state.tokens.items[index].kind)
@@ -96,19 +96,19 @@ scans_loop_controls_with_exact_keyword_boundaries test {
try testing.expect_equal(u32(5), state.tokens.items[0].span.end)
try testing.expect_equal(u32(6), state.tokens.items[1].span.start)
try testing.expect_equal(u32(14), state.tokens.items[1].span.end)
try testing.expect_equal("breakfast", strpool.get_str(&strpool.strings, state.tokens.items[2].data.str_id)?)
try testing.expect_equal("continued", strpool.get_str(&strpool.strings, state.tokens.items[3].data.str_id)?)
try testing.expect_equal("breakfast", strpool.get_str(&pool, state.tokens.items[2].data.str_id)?)
try testing.expect_equal("continued", strpool.get_str(&pool, state.tokens.items[3].data.str_id)?)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
}
scans_ranges_without_consuming_float_dots test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
try scan(&state, "0..10 0..=10 1.5..2.5 |@item, _| ... 1.", &diagnostic_store)
try scan(&state, "0..10 0..=10 1.5..2.5 |@item, _| ... 1.", &pool, &diagnostic_store)
expected [19]TokenKind :: [
.int, .range, .int, .int, .range_inclusive, .int,
.float, .range, .float, .pipe, .at, .ident, .comma, .ident, .pipe,
@@ -124,13 +124,13 @@ scans_ranges_without_consuming_float_dots test {
}
scans_array_delimiters_and_mut_keyword test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
try scan(&state, "[_]mut [2]i64 [1,2] [] mutable mut_1", &diagnostic_store)
try scan(&state, "[_]mut [2]i64 [1,2] [] mutable mut_1", &pool, &diagnostic_store)
expected [18]TokenKind :: [
.open_bracket, .ident, .close_bracket, .mut,
.open_bracket, .int, .close_bracket, .ident,
@@ -141,3 +141,80 @@ scans_array_delimiters_and_mut_keyword test {
for (expected) |kind, index| try testing.expect_equal(kind, state.tokens.items[index].kind)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
}
reuses_identifiers_without_interning_keywords test {
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
try scan(&state, "alpha beta alpha if beta", &pool, &diagnostic_store)
first :: state.tokens.items[0].data.str_id
second :: state.tokens.items[1].data.str_id
try testing.expect(first != second)
try testing.expect_equal(first, state.tokens.items[2].data.str_id)
try testing.expect_equal(second, state.tokens.items[4].data.str_id)
try testing.expect_equal(null, strpool.get_id(&pool, "if"))
try testing.expect_equal(usize(2), pool.strings.items.len)
}
@hide:file
AllocationState :: struct {
remaining usize
live usize = 0
}
@hide:file
limited_alloc proc(context ?@mut anyopaque, size usize, alignment usize) ?*mut u8 {
state @mut AllocationState :: ptrcast!(context?)
if (state.remaining == 0) return null
state.remaining -= 1
memory :: mem.raw_alloc(mem.c_allocator, size, alignment)
if (memory) |_| state.live += 1
return memory
}
@hide:file
limited_realloc proc(context ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 {
state @mut AllocationState :: ptrcast!(context?)
if (state.remaining == 0) return null
state.remaining -= 1
resized :: mem.raw_realloc(mem.c_allocator, memory, old_size, new_size, alignment)
if (resized) |_| {
if (memory) |_| {} else state.live += 1
}
return resized
}
@hide:file
limited_free proc(context ?@mut anyopaque, memory ?*mut u8, size usize, alignment usize) void {
state @mut AllocationState :: ptrcast!(context?)
if (memory) |_| state.live -= 1
mem.raw_free(mem.c_allocator, memory, size, alignment)
}
@hide:file
limited_vtable :: mem.AllocatorVTable{ alloc = limited_alloc, realloc = limited_realloc, free = limited_free }
propagates_identifier_interning_allocation_failure test {
for (usize(0)..usize(3)) |remaining| {
allocation := AllocationState{ remaining = remaining }
allocator :: mem.Allocator{ context = &allocation, vtable = &limited_vtable }
pool := strpool.init(allocator)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
state := init(mem.c_allocator)
defer deinit(&state)
failed := false
scan(&state, "identifier", &pool, &diagnostic_store) catch |error| {
failed = error == .out_of_memory
}
empty :: state.tokens.items.len == 0 and pool.strings.items.len == 0
absent :: strpool.get_id(&pool, "identifier") == null
strpool.deinit(&pool)
try testing.expect(failed and empty and absent)
try testing.expect_equal(usize(0), diagnostics.count(&diagnostic_store))
try testing.expect_equal(usize(0), allocation.live)
}
}
+3 -9
View File
@@ -69,16 +69,10 @@ TokenKind :: enum {
render_token proc(token Token, program []u8) void {
match token.kind {
.ident: {
if (strpool.get_str(&strpool.strings, token.data.str_id)) |str| {
debug.print("{}({})\n", {token.kind, str})
} else {
debug.print("{}({})\n", {token.kind, program[token.span.start..token.span.end]})
}
}
.string, .int, .float:
.ident, .string, .int, .float:
debug.print("{}({})\n", {token.kind, program[token.span.start..token.span.end]})
else: debug.print("{}\n", {token.kind})
else:
debug.print("{}\n", {token.kind})
}
}
+8 -8
View File
@@ -20,14 +20,14 @@ compile_owned proc(text []u8, diagnostic_store @mut diagnostics.Store) ir.Module
source :: try mem.alloc(u8, mem.c_allocator, text.len)
defer mem.free(mem.c_allocator, source)
for (text) |byte, i| source[i] = byte
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, diagnostic_store)
try lexer.scan(&scan_state, source, &strings, diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, diagnostic_store)
defer sema.deinit(&resolution)
checked := try typecheck.check(mem.c_allocator, &tree, &resolution, diagnostic_store)
defer typecheck.deinit(&checked)
@@ -469,8 +469,8 @@ limited_free proc(context ?@mut anyopaque, memory ?*mut u8, size usize, alignmen
limited_vtable :: mem.AllocatorVTable{ alloc = limited_alloc, realloc = limited_realloc, free = limited_free }
releases_temporaries_and_partially_owned_modules_on_allocation_failure test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -529,10 +529,10 @@ releases_temporaries_and_partially_owned_modules_on_allocation_failure test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
checked := try typecheck.check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer typecheck.deinit(&checked)
+4 -4
View File
@@ -112,14 +112,14 @@ read_source proc(allocator mem.Allocator, runtime io.Io, path [;0]u8) arraylist.
@hide:file
compile proc(allocator mem.Allocator, source []u8, diagnostic_store @mut diagnostics.Store) ir.Module ! DriverError {
strpool.strings = strpool.init(allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(allocator)
defer strpool.deinit(&strings)
scan_state := lexer.init(allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, diagnostic_store)
try lexer.scan(&scan_state, source, &strings, diagnostic_store)
tree := try parser.parse(allocator, scan_state.tokens.items, source, diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(allocator, &tree, diagnostic_store)
resolution := try sema.resolve(allocator, &tree, &strings, diagnostic_store)
defer sema.deinit(&resolution)
checked := try typecheck.check(allocator, &tree, &resolution, diagnostic_store)
defer typecheck.deinit(&checked)
+11 -8
View File
@@ -95,25 +95,26 @@ parse_func_decl proc(state @mut State) ast.NodeId ! ParseError {
params arraylist.ArrayList(ast.NodeId) := arraylist.init(state.allocator)
defer arraylist.deinit(&params)
names arraylist.ArrayList(ast.Span) := arraylist.init(state.allocator)
names arraylist.ArrayList(lexer.Token) := arraylist.init(state.allocator)
defer arraylist.deinit(&names)
while !next_is(state, .close_paren) {
arraylist.clear(&names)
while true {
token :: try consume(state, .ident)
try arraylist.append(&names, token.span)
try arraylist.append(&names, token)
if (next_is(state, .ident) or next_is(state, .open_bracket)) break
_ = try consume(state, .comma)
}
type_id :: try parse_type(state)
type_span :: ast.builder_span(&state.builder, type_id)
for (names.items) |name_span| {
for (names.items) |parameter_name| {
param_id :: try ast.add_param(
&state.builder,
ast.Span{ start = name_span.start, end = type_span.end },
name_span,
ast.Span{ start = parameter_name.span.start, end = type_span.end },
parameter_name.span,
parameter_name.data.str_id,
type_id,
)
try arraylist.append(&params, param_id)
@@ -129,6 +130,7 @@ parse_func_decl proc(state @mut State) ast.NodeId ! ParseError {
&state.builder,
ast.Span{ start = name.span.start, end = body_span.end },
name.span,
name.data.str_id,
return_type,
params.items,
body,
@@ -315,7 +317,7 @@ parse_capture_name proc(state @mut State) ?ast.NodeId ! ParseError {
if (
name.span.end != name.span.start + 1
or state.builder.source[usize(name.span.start)] != '_'
) capture = try ast.add_identifier(&state.builder, name.span)
) capture = try ast.add_identifier(&state.builder, name.span, name.data.str_id)
return capture
}
@@ -480,6 +482,7 @@ parse_statement_decl proc(state @mut State) ast.NodeId ! ParseError {
&state.builder,
ast.Span{ start = name.span.start, end = end },
name.span,
name.data.str_id,
type_id,
mutability,
initializer,
@@ -511,7 +514,7 @@ parse_type proc(state @mut State) ast.NodeId ! ParseError {
)
}
token :: try consume(state, .ident)
return try ast.add_identifier(&state.builder, token.span)
return try ast.add_identifier(&state.builder, token.span, token.data.str_id)
}
@hide:file
@@ -774,7 +777,7 @@ parse_primary proc(state @mut State) ast.NodeId ! ParseError {
}
.ident: {
state.next_token += 1
return try ast.add_identifier(&state.builder, token.span)
return try ast.add_identifier(&state.builder, token.span, token.data.str_id)
}
else: {
diagnostic :: if (token.data.diagnostic != diagnostics.no_diagnostic)
+130 -105
View File
@@ -8,14 +8,14 @@ import "@source/lexer"
import "@source/ast"
parses_expression_precedence_through_tree_views test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "value :: 1 + 2 * 3\n"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -24,6 +24,7 @@ parses_expression_precedence_through_tree_views test {
declaration :: ast.package_decl(&tree, 0)
statement :: ast.statement_decl(&tree, declaration)
try testing.expect_equal("value", ast.source_text(&tree, statement.name))
try testing.expect_equal("value", strpool.get_str(&strings, ast.name_id(&tree, declaration))?)
try testing.expect_equal(ast.ExprKind.binary, ast.expr_kind(&tree, statement.initializer))
add :: ast.binary_expr(&tree, statement.initializer)
try testing.expect_equal(ast.BinaryOperator.add, add.operator)
@@ -35,14 +36,14 @@ parses_expression_precedence_through_tree_views test {
}
parses_grouped_expression_precedence test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "value :: a + ((b - c)) * 2 / 3\n"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -66,8 +67,8 @@ parses_grouped_expression_precedence test {
}
parses_function_structure_through_tree_views test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -76,7 +77,7 @@ parses_function_structure_through_tree_views test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -85,6 +86,7 @@ parses_function_structure_through_tree_views test {
try testing.expect_equal(ast.DeclKind.function, ast.decl_kind(&tree, declaration))
function :: ast.function_decl(&tree, declaration)
try testing.expect_equal("grouped", ast.source_text(&tree, function.name))
try testing.expect_equal("grouped", strpool.get_str(&strings, ast.name_id(&tree, declaration))?)
try testing.expect_equal(3, ast.function_param_count(&tree, declaration))
first :: ast.param(&tree, ast.function_param(&tree, declaration, 0))
second :: ast.param(&tree, ast.function_param(&tree, declaration, 1))
@@ -92,6 +94,17 @@ parses_function_structure_through_tree_views test {
try testing.expect_equal("a", ast.source_text(&tree, first.name))
try testing.expect_equal("b", ast.source_text(&tree, second.name))
try testing.expect_equal("c", ast.source_text(&tree, third.name))
try testing.expect_equal(
"a", strpool.get_str(&strings, ast.name_id(&tree, ast.function_param(&tree, declaration, 0)))?,
)
try testing.expect_equal(
"b", strpool.get_str(&strings, ast.name_id(&tree, ast.function_param(&tree, declaration, 1)))?,
)
try testing.expect_equal(
"c", strpool.get_str(&strings, ast.name_id(&tree, ast.function_param(&tree, declaration, 2)))?,
)
try testing.expect_equal("T", strpool.get_str(&strings, ast.name_id(&tree, first.type))?)
try testing.expect_equal("U", strpool.get_str(&strings, ast.name_id(&tree, third.type))?)
try testing.expect_equal(first.type, second.type)
try testing.expect(first.type != third.type)
try testing.expect_equal(1, ast.block_statement_count(&tree, function.body))
@@ -99,14 +112,14 @@ parses_function_structure_through_tree_views test {
}
recovers_invalid_declaration_and_preserves_sibling test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "@ broken\nvalid :: 1\n"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -123,8 +136,8 @@ recovers_invalid_declaration_and_preserves_sibling test {
}
recovers_malformed_groups_and_preserves_following_statements test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -137,7 +150,7 @@ recovers_malformed_groups_and_preserves_following_statements test {
`after :: 4
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -162,8 +175,8 @@ recovers_malformed_groups_and_preserves_following_statements test {
}
parses_call_statements_and_postfix_precedence test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -174,7 +187,7 @@ parses_call_statements_and_postfix_precedence test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -238,8 +251,8 @@ parses_call_statements_and_postfix_precedence test {
}
recovers_malformed_calls_and_preserves_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -253,7 +266,7 @@ recovers_malformed_calls_and_preserves_siblings test {
`tail :: f()
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -288,8 +301,8 @@ recovers_malformed_calls_and_preserves_siblings test {
}
parses_return_boundaries_and_recovers_trailing_tokens test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -303,7 +316,7 @@ parses_return_boundaries_and_recovers_trailing_tokens test {
` return }
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -333,15 +346,15 @@ parses_return_boundaries_and_recovers_trailing_tokens test {
}
parses_boolean_comparison_precedence_and_associativity test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
`value :: -f() * 2 + 3 < 4 <= 5 > 6 >= 7 == true != false
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
different :: ast.binary_expr(&tree, ast.statement_decl(&tree, ast.package_decl(&tree, 0)).initializer)
@@ -368,8 +381,8 @@ parses_boolean_comparison_precedence_and_associativity test {
}
parses_factorial_and_canonical_conditional_arms test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -385,7 +398,7 @@ parses_factorial_and_canonical_conditional_arms test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
factorial :: ast.function_decl(&tree, ast.package_decl(&tree, 0))
@@ -410,14 +423,14 @@ parses_factorial_and_canonical_conditional_arms test {
}
attaches_dangling_else_to_nearest_if test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "main proc() int { if (true) if (false) return 1 else return 2 else return 3 }"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
body :: ast.function_decl(&tree, ast.package_decl(&tree, 0)).body
@@ -431,8 +444,8 @@ attaches_dangling_else_to_nearest_if test {
}
recovers_conditional_conditions_and_arms_without_losing_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -447,7 +460,7 @@ recovers_conditional_conditions_and_arms_without_losing_siblings test {
`tail :: 9
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(2, ast.package_decl_count(&tree))
@@ -475,8 +488,8 @@ recovers_conditional_conditions_and_arms_without_losing_siblings test {
}
recovers_invalid_guard_syntax_and_missing_arm_at_enclosing_brace test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -488,7 +501,7 @@ recovers_invalid_guard_syntax_and_missing_arm_at_enclosing_brace test {
`tail :: 4
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(2, ast.package_decl_count(&tree))
@@ -513,8 +526,8 @@ recovers_invalid_guard_syntax_and_missing_arm_at_enclosing_brace test {
}
parses_iterative_factorial_assignments_and_loop test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -529,7 +542,7 @@ parses_iterative_factorial_assignments_and_loop test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -552,8 +565,8 @@ parses_iterative_factorial_assignments_and_loop test {
}
parses_assignment_precedence_grouped_span_and_rhs_boundaries test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -564,7 +577,7 @@ parses_assignment_precedence_grouped_span_and_rhs_boundaries test {
` value = 6 }
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -590,8 +603,8 @@ parses_assignment_precedence_grouped_span_and_rhs_boundaries test {
}
parses_nested_loops_and_preserves_nearest_if_else test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -604,7 +617,7 @@ parses_nested_loops_and_preserves_nearest_if_else test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -628,8 +641,8 @@ parses_nested_loops_and_preserves_nearest_if_else test {
}
recovers_loop_guards_bodies_and_assignments_without_losing_braces test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -645,7 +658,7 @@ recovers_loop_guards_bodies_and_assignments_without_losing_braces test {
`tail :: 8
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -675,8 +688,8 @@ recovers_loop_guards_bodies_and_assignments_without_losing_braces test {
}
rejects_top_level_assignment_loop_else_and_assignment_expressions test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -689,7 +702,7 @@ rejects_top_level_assignment_loop_else_and_assignment_expressions test {
`tail :: 6
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -707,8 +720,8 @@ rejects_top_level_assignment_loop_else_and_assignment_expressions test {
}
recovers_nested_braces_in_malformed_loop_body_and_assignment test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -724,7 +737,7 @@ recovers_nested_braces_in_malformed_loop_body_and_assignment test {
`tail :: 8
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -742,14 +755,14 @@ recovers_nested_braces_in_malformed_loop_body_and_assignment test {
}
parses_logical_precedence_and_associativity test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "value :: !probe() == a + b * c < d and e and f or g or h\n"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -780,14 +793,14 @@ parses_logical_precedence_and_associativity test {
}
parses_right_associative_mixed_prefix_operators test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source :: "value :: !-!probe()\nother :: -!false\n"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -809,8 +822,8 @@ parses_right_associative_mixed_prefix_operators test {
}
parses_logical_expressions_in_all_expression_positions test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -853,7 +866,7 @@ parses_logical_expressions_in_all_expression_positions test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -884,8 +897,8 @@ parses_logical_expressions_in_all_expression_positions test {
}
multiline_group_errors_preserve_statement_boundaries test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -900,7 +913,7 @@ multiline_group_errors_preserve_statement_boundaries test {
`tail :: 9
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -918,8 +931,8 @@ multiline_group_errors_preserve_statement_boundaries test {
}
recovers_missing_logical_operands_and_preserves_enclosing_nodes test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -932,7 +945,7 @@ recovers_missing_logical_operands_and_preserves_enclosing_nodes test {
`after :: true
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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)
@@ -964,8 +977,8 @@ recovers_missing_logical_operands_and_preserves_enclosing_nodes test {
}
parses_leaf_loop_controls_and_nearest_else test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -979,7 +992,7 @@ parses_leaf_loop_controls_and_nearest_else test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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))
@@ -1006,8 +1019,8 @@ parses_leaf_loop_controls_and_nearest_else test {
}
rejects_control_tails_and_preserves_following_declarations test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1029,7 +1042,7 @@ rejects_control_tails_and_preserves_following_declarations test {
`last :: 4
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(9, diagnostics.count(&diagnostic_store))
@@ -1057,8 +1070,8 @@ rejects_control_tails_and_preserves_following_declarations test {
}
preserves_control_bodies_after_malformed_guards test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1070,7 +1083,7 @@ preserves_control_bodies_after_malformed_guards test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(2, diagnostics.count(&diagnostic_store))
@@ -1086,8 +1099,8 @@ preserves_control_bodies_after_malformed_guards test {
}
parses_range_endpoints_and_capture_shapes test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1104,7 +1117,7 @@ parses_range_endpoints_and_capture_shapes test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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))
@@ -1119,6 +1132,9 @@ parses_range_endpoints_and_capture_shapes test {
if (first.capture) |capture| {
try testing.expect_equal(ast.ExprKind.identifier, ast.expr_kind(&tree, capture))
try testing.expect_equal("item", ast.source_text(&tree, ast.node_span(&tree, capture)))
try testing.expect_equal("item", strpool.get_str(&strings, ast.name_id(&tree, capture))?)
reference :: ast.statement_expr(&tree, ast.block_statement(&tree, first.body, 0))
try testing.expect_equal(ast.name_id(&tree, capture), ast.name_id(&tree, reference))
} else return .expectation_failed
second :: ast.for_stmt(&tree, ast.block_statement(&tree, body, 1))
try testing.expect(second.capture == null)
@@ -1129,11 +1145,16 @@ parses_range_endpoints_and_capture_shapes test {
try testing.expect(third.pointer_capture and third.index_capture and third.index == null)
fourth :: ast.for_stmt(&tree, ast.block_statement(&tree, body, 3))
try testing.expect(fourth.index_capture and fourth.index != null)
try testing.expect_equal(ast.name_id(&tree, first.capture?), ast.name_id(&tree, third.capture?))
try testing.expect_equal(ast.name_id(&tree, first.capture?), ast.name_id(&tree, fourth.capture?))
try testing.expect_equal("index", strpool.get_str(&strings, ast.name_id(&tree, fourth.index?))?)
index_reference :: ast.statement_expr(&tree, ast.block_statement(&tree, fourth.body, 0))
try testing.expect_equal(ast.name_id(&tree, fourth.index?), ast.name_id(&tree, index_reference))
}
rejects_bro_invalid_range_headers_without_losing_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
cases [13][]u8 :: [
"for -2..1 |i| {}",
"for 0..limit+1 |i| {}",
@@ -1159,7 +1180,7 @@ rejects_bro_invalid_range_headers_without_losing_siblings test {
for ("\nkept :: 7\n}\nafter :: 9\n") |byte| try arraylist.append(&source, byte)
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source.items, &diagnostic_store)
try lexer.scan(&scan_state, source.items, &strings, &diagnostic_store)
tree := try parse(mem.c_allocator, scan_state.tokens.items, source.items, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect(diagnostics.count(&diagnostic_store) > 0)
@@ -1175,8 +1196,8 @@ rejects_bro_invalid_range_headers_without_losing_siblings test {
}
range_loop_preserves_nearest_else_and_canonical_body test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1186,7 +1207,7 @@ range_loop_preserves_nearest_else_and_canonical_body test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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))
@@ -1202,8 +1223,8 @@ range_loop_preserves_nearest_else_and_canonical_body test {
}
parses_recursive_array_annotations_literals_and_grouped_parameters test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1219,7 +1240,7 @@ parses_recursive_array_annotations_literals_and_grouped_parameters test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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))
@@ -1232,6 +1253,10 @@ parses_recursive_array_annotations_literals_and_grouped_parameters test {
try testing.expect(inner.mutable)
try testing.expect_equal(ast.ExprKind.identifier, ast.expr_kind(&tree, inner.count?))
try testing.expect_equal("i64", ast.source_text(&tree, ast.node_span(&tree, inner.element)))
try testing.expect_equal(
ast.name_id(&tree, ast.package_decl(&tree, 3)), ast.name_id(&tree, inner.count?),
)
try testing.expect_equal("i64", strpool.get_str(&strings, ast.name_id(&tree, inner.element))?)
try testing.expect_equal(2, ast.array_element_count(&tree, declaration.initializer))
for (0..ast.array_element_count(&tree, declaration.initializer)) |i| {
try testing.expect_equal(2, ast.array_element_count(
@@ -1253,8 +1278,8 @@ parses_recursive_array_annotations_literals_and_grouped_parameters test {
}
parses_postfix_indices_and_general_assignment_targets test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1266,7 +1291,7 @@ parses_postfix_indices_and_general_assignment_targets test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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))
@@ -1293,8 +1318,8 @@ parses_postfix_indices_and_general_assignment_targets test {
}
mirrors_array_type_and_leading_declaration_ambiguities test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1307,7 +1332,7 @@ mirrors_array_type_and_leading_declaration_ambiguities test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(2, diagnostics.count(&diagnostic_store))
@@ -1325,8 +1350,8 @@ mirrors_array_type_and_leading_declaration_ambiguities test {
}
preserves_array_error_ids_control_bodies_and_following_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1340,7 +1365,7 @@ preserves_array_error_ids_control_bodies_and_following_siblings test {
`tail :: 4
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
try testing.expect_equal(2, diagnostics.count(&diagnostic_store))
tree := try parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
@@ -1370,8 +1395,8 @@ preserves_array_error_ids_control_bodies_and_following_siblings test {
}
recovers_nested_square_and_parenthesis_delimiters_without_consuming_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1385,7 +1410,7 @@ recovers_nested_square_and_parenthesis_delimiters_without_consuming_siblings tes
`tail :: 5
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
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(diagnostics.count(&diagnostic_store) > 0)
+123 -137
View File
@@ -46,8 +46,8 @@ code_count proc(diagnostic_store @diagnostics.Store, code diagnostics.Code) usiz
}
propagates_numeric_context_before_defaulting_forward_and_mutable_aliases test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -66,10 +66,10 @@ propagates_numeric_context_before_defaulting_forward_and_mutable_aliases test {
`nested float :: quotient / (alias + 1)
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -102,8 +102,8 @@ propagates_numeric_context_before_defaulting_forward_and_mutable_aliases test {
}
rejects_fixed_family_conversion_integer_division_and_conflicting_demands test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -124,10 +124,10 @@ rejects_fixed_family_conversion_integer_division_and_conflicting_demands test {
`good :: 9
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -169,8 +169,8 @@ rejects_fixed_family_conversion_integer_division_and_conflicting_demands test {
}
checks_forward_alias_calls_grouped_parameters_and_mutual_recursion test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -189,10 +189,10 @@ checks_forward_alias_calls_grouped_parameters_and_mutual_recursion test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -244,8 +244,8 @@ checks_forward_alias_calls_grouped_parameters_and_mutual_recursion test {
}
separates_type_annotations_from_values_and_restricts_void_storage test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -266,10 +266,10 @@ separates_type_annotations_from_values_and_restricts_void_storage test {
`good string :: "ok"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -336,8 +336,8 @@ separates_type_annotations_from_values_and_restricts_void_storage test {
}
reports_nonvoid_fallthrough_without_poisoning_signatures_and_checks_unused_bodies test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -353,10 +353,10 @@ reports_nonvoid_fallthrough_without_poisoning_signatures_and_checks_unused_bodie
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -391,8 +391,8 @@ reports_nonvoid_fallthrough_without_poisoning_signatures_and_checks_unused_bodie
}
checks_arguments_even_for_wrong_arity_noncallable_and_chained_callees test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -410,10 +410,10 @@ checks_arguments_even_for_wrong_arity_noncallable_and_chained_callees test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -455,8 +455,8 @@ checks_arguments_even_for_wrong_arity_noncallable_and_chained_callees test {
}
terminates_unanchored_cycles_and_keeps_grounded_cycles_typed test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -474,10 +474,10 @@ terminates_unanchored_cycles_and_keeps_grounded_cycles_typed test {
`contextual_b :: contextual_a
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -530,8 +530,8 @@ terminates_unanchored_cycles_and_keeps_grounded_cycles_typed test {
}
preserves_existing_syntax_name_and_duplicate_ids_while_checking_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -548,10 +548,10 @@ preserves_existing_syntax_name_and_duplicate_ids_while_checking_siblings test {
`same :: -"initializer"
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
previous_count :: diagnostics.count(&diagnostic_store)
function :: ast.package_decl(&tree, 1)
@@ -608,8 +608,8 @@ preserves_existing_syntax_name_and_duplicate_ids_while_checking_siblings test {
}
returns_supply_numeric_context_and_resolve_forward_local_and_parameter_names test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -624,10 +624,10 @@ returns_supply_numeric_context_and_resolve_forward_local_and_parameter_names tes
`seed :: 3
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -666,8 +666,8 @@ returns_supply_numeric_context_and_resolve_forward_local_and_parameter_names tes
}
return_errors_preserve_identity_check_unreachable_code_and_suppress_missing_return_cascades test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -687,10 +687,10 @@ return_errors_preserve_identity_check_unreachable_code_and_suppress_missing_retu
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -733,8 +733,8 @@ return_errors_preserve_identity_check_unreachable_code_and_suppress_missing_retu
}
checks_bool_comparisons_recursive_returns_and_nested_numeric_context test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -769,10 +769,10 @@ checks_bool_comparisons_recursive_returns_and_nested_numeric_context test {
`main proc() bool { return identity(flag) }
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -815,8 +815,8 @@ checks_bool_comparisons_recursive_returns_and_nested_numeric_context test {
}
rejects_bool_numeric_mixing_and_preserves_invalid_condition_identity test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -835,10 +835,10 @@ rejects_bool_numeric_mixing_and_preserves_invalid_condition_identity test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -882,8 +882,8 @@ rejects_bool_numeric_mixing_and_preserves_invalid_condition_identity test {
}
analyzes_return_paths_after_trap_propagation_without_poisoning_signatures test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -918,10 +918,10 @@ analyzes_return_paths_after_trap_propagation_without_poisoning_signatures test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -970,8 +970,8 @@ analyzes_return_paths_after_trap_propagation_without_poisoning_signatures test {
}
assignments_preserve_established_types_and_contextualize_numeric_values test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -996,10 +996,10 @@ assignments_preserve_established_types_and_contextualize_numeric_values test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -1065,8 +1065,8 @@ assignments_preserve_established_types_and_contextualize_numeric_values test {
}
assignment_target_errors_preserve_bindings_and_independent_rhs_diagnostics test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1084,10 +1084,10 @@ assignment_target_errors_preserve_bindings_and_independent_rhs_diagnostics test
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1124,8 +1124,8 @@ assignment_target_errors_preserve_bindings_and_independent_rhs_diagnostics test
}
function_assignment_checks_complete_signatures_without_retargeting_calls test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1145,10 +1145,10 @@ function_assignment_checks_complete_signatures_without_retargeting_calls test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -1178,8 +1178,8 @@ function_assignment_checks_complete_signatures_without_retargeting_calls test {
}
while_checks_nested_bodies_without_claiming_a_zero_iteration_return test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1203,10 +1203,10 @@ while_checks_nested_bodies_without_claiming_a_zero_iteration_return test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1251,8 +1251,8 @@ while_checks_nested_bodies_without_claiming_a_zero_iteration_return test {
}
logical_types_preserve_comparison_context_and_assignment_isolation test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1270,10 +1270,10 @@ logical_types_preserve_comparison_context_and_assignment_isolation test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1316,8 +1316,8 @@ logical_types_preserve_comparison_context_and_assignment_isolation test {
}
logical_operand_errors_are_independent_and_skipped_rhs_preserves_bool test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1342,10 +1342,10 @@ logical_operand_errors_are_independent_and_skipped_rhs_preserves_bool test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1412,8 +1412,8 @@ logical_operand_errors_are_independent_and_skipped_rhs_preserves_bool test {
}
logical_external_mismatches_and_always_demanded_not_preserve_errors test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1435,10 +1435,10 @@ logical_external_mismatches_and_always_demanded_not_preserve_errors test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1491,8 +1491,8 @@ logical_external_mismatches_and_always_demanded_not_preserve_errors test {
}
short_circuit_skip_paths_do_not_guarantee_a_return test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1514,10 +1514,10 @@ short_circuit_skip_paths_do_not_guarantee_a_return test {
`take proc(value bool) void {}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1550,8 +1550,8 @@ short_circuit_skip_paths_do_not_guarantee_a_return test {
}
loop_controls_follow_lexical_bodies_and_check_unreachable_code test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1583,10 +1583,10 @@ loop_controls_follow_lexical_bodies_and_check_unreachable_code test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1639,8 +1639,8 @@ loop_controls_follow_lexical_bodies_and_check_unreachable_code test {
}
loop_controls_do_not_guarantee_function_returns test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1661,10 +1661,10 @@ loop_controls_do_not_guarantee_function_returns test {
`invalid proc() int { break }
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1694,8 +1694,8 @@ loop_controls_do_not_guarantee_function_returns test {
}
range_bounds_receive_integer_context_without_joining_the_range_or_capture test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1714,10 +1714,10 @@ range_bounds_receive_integer_context_without_joining_the_range_or_capture test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1753,8 +1753,8 @@ range_bounds_receive_integer_context_without_joining_the_range_or_capture test {
}
range_checks_both_bounds_and_preserves_fixed_declarations_and_source_errors test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1776,10 +1776,10 @@ range_checks_both_bounds_and_preserves_fixed_declarations_and_source_errors test
`flexible := 3
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1826,8 +1826,8 @@ range_checks_both_bounds_and_preserves_fixed_declarations_and_source_errors test
}
range_values_nonrange_iterables_and_capture_modes_have_explicit_errors test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1851,10 +1851,10 @@ range_values_nonrange_iterables_and_capture_modes_have_explicit_errors test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1901,8 +1901,8 @@ range_values_nonrange_iterables_and_capture_modes_have_explicit_errors test {
}
range_captures_are_fixed_readonly_and_assignment_values_do_not_retarget_bounds test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -1927,10 +1927,10 @@ range_captures_are_fixed_readonly_and_assignment_values_do_not_retarget_bounds t
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -1986,8 +1986,8 @@ range_captures_are_fixed_readonly_and_assignment_values_do_not_retarget_bounds t
}
range_loop_return_flow_and_controls_are_lexical_and_body_errors_are_isolated test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -2025,10 +2025,10 @@ range_loop_return_flow_and_controls_are_lexical_and_body_errors_are_isolated tes
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
defer deinit(&result)
@@ -2080,8 +2080,8 @@ range_loop_return_flow_and_controls_are_lexical_and_body_errors_are_isolated tes
}
invalid_range_capture_bindings_keep_resolver_diagnostic_ids_without_erasing_headers test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
strings := strpool.init(mem.c_allocator)
defer strpool.deinit(&strings)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -2094,10 +2094,10 @@ invalid_range_capture_bindings_keep_resolver_diagnostic_ids_without_erasing_head
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &strings, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &diagnostic_store)
defer sema.deinit(&resolution)
previous_count :: diagnostics.count(&diagnostic_store)
result := try check(mem.c_allocator, &tree, &resolution, &diagnostic_store)
@@ -2132,6 +2132,7 @@ invalid_range_capture_bindings_keep_resolver_diagnostic_ids_without_erasing_head
@hide:file
ArrayFixture :: struct {
strings strpool.StringPool
tree ast.Tree
resolution sema.Resolution
diagnostics diagnostics.Store
@@ -2140,17 +2141,19 @@ ArrayFixture :: struct {
@hide:file
array_fixture proc(source []u8) ArrayFixture ! (mem.AllocError | strpool.InternError | diagnostics.CapacityError | lexer.SourceError) {
strings := strpool.init(mem.c_allocator)
errdefer strpool.deinit(&strings)
store := diagnostics.init(mem.c_allocator)
errdefer diagnostics.deinit(&store)
scan := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan)
try lexer.scan(&scan, source, &store)
try lexer.scan(&scan, source, &strings, &store)
tree := try parser.parse(mem.c_allocator, scan.tokens.items, source, &store)
errdefer ast.deinit(&tree)
resolution := try sema.resolve(mem.c_allocator, &tree, &store)
resolution := try sema.resolve(mem.c_allocator, &tree, &strings, &store)
errdefer sema.deinit(&resolution)
result :: try check(mem.c_allocator, &tree, &resolution, &store)
return ArrayFixture{ tree = tree, resolution = resolution, diagnostics = store, result = result }
return ArrayFixture{ strings = strings, tree = tree, resolution = resolution, diagnostics = store, result = result }
}
@hide:file
@@ -2159,6 +2162,7 @@ deinit_array_fixture proc(fixture @mut ArrayFixture) void {
sema.deinit(&fixture.resolution)
ast.deinit(&fixture.tree)
diagnostics.deinit(&fixture.diagnostics)
strpool.deinit(&fixture.strings)
}
@hide:file
@@ -2172,8 +2176,6 @@ expect_array proc(result @Result, id ast.NodeId, len usize, mutable bool, elemen
}
fixed_arrays_contextualize_forward_aliases_counts_nested_literals_and_signatures test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`context [2]f64 :: alias
`alias :: seed
@@ -2225,8 +2227,6 @@ fixed_arrays_contextualize_forward_aliases_counts_nested_literals_and_signatures
}
nested_array_numeric_context_flows_through_index_children_before_defaults test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`first float :: later[0][0]
`later := [[1, 2], [3, 4]]
@@ -2262,8 +2262,6 @@ nested_array_numeric_context_flows_through_index_children_before_defaults test {
}
fixed_index_errors_are_occurrence_local_and_preserve_sources_and_siblings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`fixed i64 :: 0
`inferred := 0
@@ -2298,8 +2296,6 @@ fixed_index_errors_are_occurrence_local_and_preserve_sources_and_siblings test {
}
array_lengths_require_supported_constexpr_and_finalize_nested_inferred_counts test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`two :: tail
`tail :: 2
@@ -2355,8 +2351,6 @@ array_lengths_require_supported_constexpr_and_finalize_nested_inferred_counts te
}
indexed_writes_require_mutable_local_root_and_each_array_level_but_copies_are_values test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`global [1]mut i64 := [1]
`main proc(parameter [1]mut i64) void {
@@ -2408,8 +2402,6 @@ indexed_writes_require_mutable_local_root_and_each_array_level_but_copies_are_va
}
usize_arithmetic_ranges_and_readonly_captures_keep_the_bound_family test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`limit usize :: 18446744073709551615
`arithmetic usize :: (limit - 2) * 1 + 1
@@ -2470,8 +2462,6 @@ usize_arithmetic_ranges_and_readonly_captures_keep_the_bound_family test {
}
array_assignment_rhs_is_contextual_but_does_not_retarget_established_sources test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`main proc() void {
` target [2]mut f64 := [1, 2]
@@ -2513,8 +2503,6 @@ array_assignment_rhs_is_contextual_but_does_not_retarget_established_sources tes
}
array_signature_identity_includes_recursive_counts_and_mutability test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`accept proc(value [1]mut i64) [1]mut i64 { return value }
`different_count proc(value [2]mut i64) [1]mut i64 { return [1] }
@@ -2559,8 +2547,6 @@ array_signature_identity_includes_recursive_counts_and_mutability test {
}
inferred_counts_follow_forward_fixed_aliases_empty_shapes_and_reject_local_counts test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
source ::
`forward [_]i64 :: later
`later [_]i64 :: [1, 2]
+63 -27
View File
@@ -1,7 +1,7 @@
import "@std/debug"
import "@std/mem"
import "@std/hashmap"
import "@std/strmap"
import "@source/strpool"
import "@source/ast"
import "@source/diagnostics"
@@ -14,16 +14,22 @@ BuiltinType :: enum {
}
@hide:file
builtins strmap.StaticStringMap(BuiltinType) :: strmap.init([
{ "int", .int },
{ "float", .float },
{ "bool", .bool },
{ "string", .string },
{ "void", .void },
{ "i64", .i64 },
{ "f64", .f64 },
{ "usize", .usize },
])
Builtin :: struct {
name []u8
type BuiltinType
}
@hide:file
builtins [8]Builtin :: [
{ name = "int", type = .int },
{ name = "float", type = .float },
{ name = "bool", type = .bool },
{ name = "string", type = .string },
{ name = "void", type = .void },
{ name = "i64", type = .i64 },
{ name = "f64", type = .f64 },
{ name = "usize", type = .usize },
]
BindingKind :: enum { none, declaration, builtin, invalid }
@@ -50,7 +56,7 @@ Resolution :: struct { storage Storage }
@hide:file
Scope :: struct {
names hashmap.StringHashMap(Binding)
names hashmap.HashMap(strpool.StringId, Binding, name_hash, names_equal)
parent ?@Scope
}
@@ -59,17 +65,19 @@ State :: struct {
tree @ast.Tree
diagnostics @mut diagnostics.Store
bindings []mut Binding
builtin_ids [8]mut strpool.StringId = [0, 0, 0, 0, 0, 0, 0, 0]
allocator mem.Allocator
}
#! borrows `tree` and `diagnostic_store` during resolution, without retaining their storage.
#! borrows `tree`, its identifier `pool`, and `diagnostic_store` during resolution.
#! `allocator` supplies caller-owned bindings and temporary scopes released before return.
#! release the returned Resolution with deinit, which uses the retained allocator.
resolve proc(
allocator mem.Allocator,
tree @ast.Tree,
pool @mut strpool.StringPool,
diagnostic_store @mut diagnostics.Store,
) Resolution ! (mem.AllocError | diagnostics.CapacityError) {
) Resolution ! (mem.AllocError | strpool.InternError | diagnostics.CapacityError) {
bindings :: try mem.alloc(Binding, allocator, ast.node_count(tree))
errdefer mem.free(allocator, bindings)
mem.set(bindings, Binding{})
@@ -81,7 +89,13 @@ resolve proc(
allocator = allocator,
}
package_scope := Scope{ names = hashmap.init(allocator), parent = null }
for (builtins) |builtin, index| {
state.builtin_ids[index] = try strpool.intern(pool, builtin.name)
}
package_scope := Scope{
names = hashmap.init(strpool.StringId, Binding, name_hash, names_equal, allocator),
parent = null,
}
defer hashmap.deinit(&package_scope.names)
for (0..ast.package_decl_count(tree)) |i| {
id :: ast.package_decl(tree, i)
@@ -115,19 +129,22 @@ binding proc(resolution @Resolution, id ast.NodeId) Binding {
}
@hide:file
lookup proc(scope ?@Scope, name []u8) ?Binding {
lookup proc(state @State, scope ?@Scope, name strpool.StringId) ?Binding {
if scope |current| {
if hashmap.get(&current.names, name) |found| return found
return lookup(current.parent, name)
return lookup(state, current.parent, name)
}
if strmap.get(&builtins, name) |type| {
return Binding{ kind = .builtin, data = BindingData{ builtin = type } }
for (state.builtin_ids) |id, index| {
if (id == name) return Binding{
kind = .builtin,
data = BindingData{ builtin = builtins[index].type },
}
}
return null
}
@hide:file
put_name proc(scope @mut Scope, name []u8, value Binding) void ! mem.AllocError {
put_name proc(scope @mut Scope, name strpool.StringId, value Binding) void ! mem.AllocError {
hashmap.put(&scope.names, name, value) catch |err| {
match err {
.key_exists: unreachable
@@ -143,7 +160,7 @@ predeclare proc(
id ast.NodeId,
name_span ast.Span,
) void ! (mem.AllocError | diagnostics.CapacityError) {
name :: ast.source_text(state.tree, name_span)
name :: ast.name_id(state.tree, id)
if hashmap.get(&scope.names, name) |_| {
diagnostic :: try diagnostics.add(state.diagnostics, .duplicate_name, name_span)
state.bindings[usize(id)] = Binding{
@@ -154,7 +171,7 @@ predeclare proc(
}
value := Binding{ kind = .declaration, data = BindingData{ declaration = id } }
if lookup(scope.parent, name) |_| {
if lookup(state, scope.parent, name) |_| {
diagnostic :: try diagnostics.add(state.diagnostics, .duplicate_name, name_span)
# poison the inner name rather than silently binding uses to its ancestor.
value = Binding{ kind = .invalid, data = BindingData{ diagnostic = diagnostic } }
@@ -178,7 +195,10 @@ resolve_function proc(
try resolve_expr(state, package_scope, ast.param(tree, parameter).type)
}
scope := Scope{ names = hashmap.init(state.allocator), parent = package_scope }
scope := Scope{
names = hashmap.init(strpool.StringId, Binding, name_hash, names_equal, state.allocator),
parent = package_scope,
}
defer hashmap.deinit(&scope.names)
for (0..ast.function_param_count(tree, id)) |i| {
parameter :: ast.function_param(tree, id, i)
@@ -189,7 +209,10 @@ resolve_function proc(
@hide:file
resolve_arm proc(state @mut State, parent @Scope, id ast.NodeId) void ! (mem.AllocError | diagnostics.CapacityError) {
scope := Scope{ names = hashmap.init(state.allocator), parent = parent }
scope := Scope{
names = hashmap.init(strpool.StringId, Binding, name_hash, names_equal, state.allocator),
parent = parent,
}
defer hashmap.deinit(&scope.names)
try resolve_block(state, &scope, id)
}
@@ -231,7 +254,10 @@ resolve_block proc(state @mut State, scope @mut Scope, id ast.NodeId) void ! (me
.for_stmt: {
loop :: ast.for_stmt(tree, statement)
try resolve_expr(state, scope, loop.iterable)
body_scope := Scope{ names = hashmap.init(state.allocator), parent = scope }
body_scope := Scope{
names = hashmap.init(strpool.StringId, Binding, name_hash, names_equal, state.allocator),
parent = scope,
}
defer hashmap.deinit(&body_scope.names)
if (loop.capture) |capture| {
try predeclare(state, &body_scope, capture, ast.node_span(tree, capture))
@@ -279,8 +305,8 @@ resolve_expr proc(
.literal_int, .literal_float, .literal_bool, .literal_string: {}
.identifier: {
span :: ast.node_span(tree, id)
name :: ast.source_text(tree, span)
if lookup(scope, name) |found| {
name :: ast.name_id(tree, id)
if lookup(state, scope, name) |found| {
state.bindings[usize(id)] = found
} else {
diagnostic :: try diagnostics.add(state.diagnostics, .unknown_name, span)
@@ -325,3 +351,13 @@ resolve_expr proc(
.invalid: resolve_invalid(state, id)
}
}
@hide:file
name_hash proc(name strpool.StringId) usize {
return usize(name)
}
@hide:file
names_equal proc(left, right strpool.StringId) bool {
return left == right
}
+98 -44
View File
@@ -8,8 +8,8 @@ import "@source/parser"
import "@source/ast"
resolves_forward_references_recursion_and_builtin_signatures test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -25,10 +25,10 @@ resolves_forward_references_recursion_and_builtin_signatures test {
`later int :: 1
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
first :: ast.package_decl(&tree, 0)
@@ -110,8 +110,8 @@ resolves_forward_references_recursion_and_builtin_signatures test {
}
rejects_shadowing_and_duplicates_without_cascades test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -132,11 +132,11 @@ rejects_shadowing_and_duplicates_without_cascades test {
`same :: same
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
function :: ast.package_decl(&tree, 0)
@@ -228,8 +228,8 @@ rejects_shadowing_and_duplicates_without_cascades test {
}
preserves_syntax_diagnostics_and_resolves_shared_unknown_types_once test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -243,7 +243,7 @@ preserves_syntax_diagnostics_and_resolves_shared_unknown_types_once test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
syntax_count :: diagnostics.count(&diagnostic_store)
@@ -255,7 +255,7 @@ preserves_syntax_diagnostics_and_resolves_shared_unknown_types_once test {
try testing.expect_equal(ast.ExprKind.invalid, ast.expr_kind(&tree, empty))
invalid_statement :: ast.block_statement(&tree, view.body, 4)
try testing.expect_equal(ast.StmtKind.invalid, ast.stmt_kind(&tree, invalid_statement))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
invalid_nodes [3]ast.NodeId :: [invalid_decl, empty, invalid_statement]
@@ -300,8 +300,8 @@ preserves_syntax_diagnostics_and_resolves_shared_unknown_types_once test {
}
resolves_conditional_arm_scopes_without_leaks_or_shadowing test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -323,11 +323,11 @@ resolves_conditional_arm_scopes_without_leaks_or_shadowing test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
function :: ast.package_decl(&tree, 0)
@@ -368,8 +368,8 @@ resolves_conditional_arm_scopes_without_leaks_or_shadowing test {
}
resolves_loop_assignments_in_lexical_scopes_with_forward_local_bindings test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -394,11 +394,11 @@ resolves_loop_assignments_in_lexical_scopes_with_forward_local_bindings test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
function :: ast.package_decl(&tree, 0)
@@ -441,8 +441,8 @@ resolves_loop_assignments_in_lexical_scopes_with_forward_local_bindings test {
}
resolves_all_code_and_preserves_scopes_after_loop_controls test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -464,11 +464,11 @@ resolves_all_code_and_preserves_scopes_after_loop_controls test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
try testing.expect_equal(4, diagnostics.count(&diagnostic_store))
body :: ast.function_decl(&tree, ast.package_decl(&tree, 0)).body
@@ -487,8 +487,8 @@ resolves_all_code_and_preserves_scopes_after_loop_controls test {
}
range_bounds_use_outer_scope_and_captures_are_body_declarations test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -506,10 +506,10 @@ range_bounds_use_outer_scope_and_captures_are_body_declarations test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
body :: ast.function_decl(&tree, ast.package_decl(&tree, 0)).body
loop :: ast.for_stmt(&tree, ast.block_statement(&tree, body, 0))
@@ -540,8 +540,8 @@ range_bounds_use_outer_scope_and_captures_are_body_declarations test {
}
range_captures_preserve_duplicate_builtin_and_discard_errors test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -563,10 +563,10 @@ range_captures_preserve_duplicate_builtin_and_discard_errors test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
body :: ast.function_decl(&tree, ast.package_decl(&tree, 0)).body
for (usize(1)..usize(3)) |index| {
@@ -605,8 +605,8 @@ range_captures_preserve_duplicate_builtin_and_discard_errors test {
}
resolves_array_counts_elements_indices_and_unreachable_targets test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -621,10 +621,10 @@ resolves_array_counts_elements_indices_and_unreachable_targets test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
size :: ast.package_decl(&tree, 0)
@@ -669,8 +669,8 @@ resolves_array_counts_elements_indices_and_unreachable_targets test {
}
array_signature_counts_use_package_scope_and_local_counts_see_parameters test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -682,11 +682,11 @@ array_signature_counts_use_package_scope_and_local_counts_see_parameters test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
try testing.expect_equal(2, diagnostics.count(&diagnostic_store))
function :: ast.package_decl(&tree, 1)
@@ -710,8 +710,8 @@ array_signature_counts_use_package_scope_and_local_counts_see_parameters test {
}
resolves_every_array_child_error_and_preserves_lexer_diagnostics test {
strpool.strings = strpool.init(mem.c_allocator)
defer strpool.deinit(&strpool.strings)
pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&pool)
diagnostic_store := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&diagnostic_store)
source ::
@@ -723,11 +723,11 @@ resolves_every_array_child_error_and_preserves_lexer_diagnostics test {
`}
scan_state := lexer.init(mem.c_allocator)
defer lexer.deinit(&scan_state)
try lexer.scan(&scan_state, source, &diagnostic_store)
try lexer.scan(&scan_state, source, &pool, &diagnostic_store)
tree := try parser.parse(mem.c_allocator, scan_state.tokens.items, source, &diagnostic_store)
defer ast.deinit(&tree)
try testing.expect_equal(2, diagnostics.count(&diagnostic_store))
resolution := try resolve(mem.c_allocator, &tree, &diagnostic_store)
resolution := try resolve(mem.c_allocator, &tree, &pool, &diagnostic_store)
defer deinit(&resolution)
try testing.expect_equal(10, diagnostics.count(&diagnostic_store))
body :: ast.function_decl(&tree, ast.package_decl(&tree, 0)).body
@@ -755,3 +755,57 @@ resolves_every_array_child_error_and_preserves_lexer_diagnostics test {
try testing.expect_equal(diagnostics.DiagnosticId(0), binding(&resolution, malformed_count).data.diagnostic)
try testing.expect_equal(diagnostics.DiagnosticId(1), binding(&resolution, malformed_element).data.diagnostic)
}
resolves_interleaved_compilations_with_independent_identifier_orders test {
first_pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&first_pool)
second_pool := strpool.init(mem.c_allocator)
defer strpool.deinit(&second_pool)
first_diagnostics := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&first_diagnostics)
second_diagnostics := diagnostics.init(mem.c_allocator)
defer diagnostics.deinit(&second_diagnostics)
first_source :: "alpha :: beta\nbeta i64 :: 1\nmain proc() bool { return true }\n"
second_source :: "beta :: alpha\nalpha bool :: false\nmain proc() i64 { return 1 }\n"
first_scan := lexer.init(mem.c_allocator)
defer lexer.deinit(&first_scan)
second_scan := lexer.init(mem.c_allocator)
defer lexer.deinit(&second_scan)
try lexer.scan(&first_scan, first_source, &first_pool, &first_diagnostics)
first_tree := try parser.parse(mem.c_allocator, first_scan.tokens.items, first_source, &first_diagnostics)
defer ast.deinit(&first_tree)
try lexer.scan(&second_scan, second_source, &second_pool, &second_diagnostics)
second_tree := try parser.parse(mem.c_allocator, second_scan.tokens.items, second_source, &second_diagnostics)
defer ast.deinit(&second_tree)
first_name :: ast.name_id(&first_tree, ast.package_decl(&first_tree, 0))
second_name :: ast.name_id(&second_tree, ast.package_decl(&second_tree, 0))
try testing.expect_equal(first_name, second_name)
try testing.expect_equal("alpha", strpool.get_str(&first_pool, first_name)?)
try testing.expect_equal("beta", strpool.get_str(&second_pool, second_name)?)
first_resolution := try resolve(mem.c_allocator, &first_tree, &first_pool, &first_diagnostics)
defer deinit(&first_resolution)
second_resolution := try resolve(mem.c_allocator, &second_tree, &second_pool, &second_diagnostics)
defer deinit(&second_resolution)
first_decl :: ast.package_decl(&first_tree, 0)
second_decl :: ast.package_decl(&second_tree, 0)
first_target :: ast.package_decl(&first_tree, 1)
second_target :: ast.package_decl(&second_tree, 1)
first_use :: ast.statement_decl(&first_tree, first_decl).initializer
second_use :: ast.statement_decl(&second_tree, second_decl).initializer
try testing.expect_equal(BindingKind.declaration, binding(&first_resolution, first_use).kind)
try testing.expect_equal(first_target, binding(&first_resolution, first_use).data.declaration)
try testing.expect_equal(BindingKind.declaration, binding(&second_resolution, second_use).kind)
try testing.expect_equal(second_target, binding(&second_resolution, second_use).data.declaration)
first_type :: ast.statement_decl(&first_tree, first_target).type?
second_type :: ast.statement_decl(&second_tree, second_target).type?
try testing.expect_equal(BindingKind.builtin, binding(&first_resolution, first_type).kind)
try testing.expect_equal(BuiltinType.i64, binding(&first_resolution, first_type).data.builtin)
try testing.expect_equal(BindingKind.builtin, binding(&second_resolution, second_type).kind)
try testing.expect_equal(BuiltinType.bool, binding(&second_resolution, second_type).data.builtin)
first_return :: ast.function_decl(&first_tree, ast.package_decl(&first_tree, 2)).return_type
second_return :: ast.function_decl(&second_tree, ast.package_decl(&second_tree, 2)).return_type
try testing.expect_equal(BuiltinType.bool, binding(&first_resolution, first_return).data.builtin)
try testing.expect_equal(BuiltinType.i64, binding(&second_resolution, second_return).data.builtin)
try testing.expect_equal(usize(0), diagnostics.count(&first_diagnostics))
try testing.expect_equal(usize(0), diagnostics.count(&second_diagnostics))
}
+1 -3
View File
@@ -4,13 +4,11 @@ import "@std/hashmap"
InternError :: enum { out_of_space }
#! identifies a string only within its owning pool.
StringId :: alias u32
no_str :: maxval!(StringId)
#! global pool owned by main.hon; initialize before scanning and release with deinit.
strings StringPool := undefined
#! retains its allocator and owns interned copies; release all storage with deinit.
StringPool :: struct {
ids hashmap.StringHashMap(StringId) # string → id
+16
View File
@@ -22,3 +22,19 @@ handles_interning test {
try testing.expect_equal(null, invalid_str)
try testing.expect_equal("hello", hello_str?)
}
keeps_independent_pool_ids_local test {
first := init(mem.c_allocator)
defer deinit(&first)
second := init(mem.c_allocator)
defer deinit(&second)
hello :: try intern(&first, "hello")
world :: try intern(&second, "world")
try testing.expect_equal(hello, world)
try testing.expect_equal("hello", get_str(&first, hello)?)
try testing.expect_equal("world", get_str(&second, world)?)
different :: try intern(&first, "world")
try testing.expect(different != hello)
try testing.expect_equal(hello, try intern(&first, "hello"))
try testing.expect_equal(world, try intern(&second, "world"))
}