import "@std/mem" import "@std/testing" import "@source/strpool" import "@source/lexer" import "@source/ast" ast_renderer :: import "@source/ast/renderer" handles_package_declarations test { strpool.STRINGS = strpool.init(mem.c_allocator) defer strpool.deinit(&strpool.STRINGS) source :: `first int :: 42 `second float :: 2.15 + 3 `message :: "hello" scan_state := lexer.init(mem.c_allocator) defer lexer.deinit(&scan_state) try lexer.scan(&scan_state, source) parse_state := init(mem.c_allocator) defer deinit(&parse_state) root :: try parse(&parse_state, scan_state.tokens.items) renderer := ast_renderer.init(mem.c_allocator) defer ast_renderer.deinit(&renderer) try ast_renderer.render_token_stream(&renderer, root, &parse_state, scan_state.tokens.items) try testing.expect_equal(scan_state.tokens.items.len, renderer.tokens.items.len) for scan_state.tokens.items |expected, i| { actual :: renderer.tokens.items[i] try testing.expect_equal(expected.kind, actual.kind) try testing.expect_equal(expected.start, actual.start) try testing.expect_equal(expected.str_id, actual.str_id) } } handles_unary_arithmetic_prefix_expression test { strpool.STRINGS = strpool.init(mem.c_allocator) defer strpool.deinit(&strpool.STRINGS) source :: `first :: -42 + 1 scan_state := lexer.init(mem.c_allocator) defer lexer.deinit(&scan_state) try lexer.scan(&scan_state, source) parse_state := init(mem.c_allocator) defer deinit(&parse_state) root :: try parse(&parse_state, scan_state.tokens.items) renderer := ast_renderer.init(mem.c_allocator) defer ast_renderer.deinit(&renderer) try ast_renderer.render_token_stream(&renderer, root, &parse_state, scan_state.tokens.items) try testing.expect_equal(scan_state.tokens.items.len, renderer.tokens.items.len) for scan_state.tokens.items |expected, i| { actual :: renderer.tokens.items[i] try testing.expect_equal(expected.kind, actual.kind) try testing.expect_equal(expected.start, actual.start) try testing.expect_equal(expected.str_id, actual.str_id) } } handles_binary_arithmetic_expression test { strpool.STRINGS = strpool.init(mem.c_allocator) defer strpool.deinit(&strpool.STRINGS) source :: `first int :: 42 + 3 `second :: 134 + 5 `third float :: 1.35 + 2 `fourth :: first + second scan_state := lexer.init(mem.c_allocator) defer lexer.deinit(&scan_state) try lexer.scan(&scan_state, source) parse_state := init(mem.c_allocator) defer deinit(&parse_state) root :: try parse(&parse_state, scan_state.tokens.items) renderer := ast_renderer.init(mem.c_allocator) defer ast_renderer.deinit(&renderer) try ast_renderer.render_token_stream(&renderer, root, &parse_state, scan_state.tokens.items) try testing.expect_equal(scan_state.tokens.items.len, renderer.tokens.items.len) for scan_state.tokens.items |expected, i| { actual :: renderer.tokens.items[i] try testing.expect_equal(expected.kind, actual.kind) try testing.expect_equal(expected.start, actual.start) try testing.expect_equal(expected.str_id, actual.str_id) } } handles_statement_declaration test { strpool.STRINGS = strpool.init(mem.c_allocator) defer strpool.deinit(&strpool.STRINGS) source :: `value int :: 42 scan_state := lexer.init(mem.c_allocator) defer lexer.deinit(&scan_state) try lexer.scan(&scan_state, source) parse_state := init(mem.c_allocator) defer deinit(&parse_state) root :: try parse(&parse_state, scan_state.tokens.items) renderer := ast_renderer.init(mem.c_allocator) defer ast_renderer.deinit(&renderer) try ast_renderer.render_token_stream(&renderer, root, &parse_state, scan_state.tokens.items) try testing.expect_equal(scan_state.tokens.items.len, renderer.tokens.items.len) for scan_state.tokens.items |expected, i| { actual :: renderer.tokens.items[i] try testing.expect_equal(expected.kind, actual.kind) try testing.expect_equal(expected.start, actual.start) try testing.expect_equal(expected.str_id, actual.str_id) } } handles_function_declarations test { strpool.STRINGS = strpool.init(mem.c_allocator) defer strpool.deinit(&strpool.STRINGS) source :: `empty proc() void {} `grouped proc(a, b T, c U) void { ` value int :: 1 `} scan_state := lexer.init(mem.c_allocator) defer lexer.deinit(&scan_state) try lexer.scan(&scan_state, source) parse_state := init(mem.c_allocator) defer deinit(&parse_state) root_id :: try parse(&parse_state, scan_state.tokens.items) root :: parse_state.nodes.items[usize(root_id)] package_start :: usize(root.data0.extra_id) package_end :: usize(root.data1.extra_id) try testing.expect_equal(usize(2), package_end - package_start) empty_id :: ast.node_id(parse_state.extra.items[package_start]) empty :: parse_state.nodes.items[usize(empty_id)] empty_payload :: usize(empty.data1.extra_id) empty_block :: parse_state.nodes.items[usize(empty.data0.node_id)] try testing.expect_equal(ast.NodeKind.func_decl, empty.kind) try testing.expect_equal(u32(0), parse_state.extra.items[empty_payload + 1]) try testing.expect_equal( usize(empty_block.data0.extra_id), usize(empty_block.data1.extra_id), ) grouped_id :: ast.node_id(parse_state.extra.items[package_start + 1]) grouped :: parse_state.nodes.items[usize(grouped_id)] grouped_payload :: usize(grouped.data1.extra_id) try testing.expect_equal(ast.NodeKind.func_decl, grouped.kind) try testing.expect_equal(u32(3), parse_state.extra.items[grouped_payload + 1]) param_a_id :: ast.node_id(parse_state.extra.items[grouped_payload + 2]) param_b_id :: ast.node_id(parse_state.extra.items[grouped_payload + 3]) param_c_id :: ast.node_id(parse_state.extra.items[grouped_payload + 4]) param_a :: parse_state.nodes.items[usize(param_a_id)] param_b :: parse_state.nodes.items[usize(param_b_id)] param_c :: parse_state.nodes.items[usize(param_c_id)] try testing.expect_equal(ast.NodeKind.param_decl, param_a.kind) try testing.expect_equal(ast.NodeKind.param_decl, param_b.kind) try testing.expect_equal(ast.NodeKind.param_decl, param_c.kind) try testing.expect(param_a.data0.node_id == param_b.data0.node_id) try testing.expect(param_a.data0.node_id != param_c.data0.node_id) grouped_block :: parse_state.nodes.items[usize(grouped.data0.node_id)] try testing.expect_equal(ast.NodeKind.block, grouped_block.kind) try testing.expect_equal( usize(1), usize(grouped_block.data1.extra_id) - usize(grouped_block.data0.extra_id), ) renderer := ast_renderer.init(mem.c_allocator) defer ast_renderer.deinit(&renderer) try ast_renderer.render_token_stream( &renderer, root_id, &parse_state, scan_state.tokens.items, ) try testing.expect_equal(scan_state.tokens.items.len, renderer.tokens.items.len) for scan_state.tokens.items |expected, i| { actual :: renderer.tokens.items[i] try testing.expect_equal(expected.kind, actual.kind) try testing.expect_equal(expected.start, actual.start) try testing.expect_equal(expected.str_id, actual.str_id) } }