refactor: integrate compilation-owned identifier interning
This commit is contained in:
+37
-6
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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(¶ms)
|
||||
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(¶ms, 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
@@ -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
@@ -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
@@ -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(¤t.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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user