import "@std/mem" import "@std/testing" import "@source/strpool" import "@source/diagnostics" 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) value_name :: Span{ start = 0, end = 5 } value :: try add_literal(&builder, .int, Span{ start = 9, end = 11 }) declaration :: try add_statement_decl( &builder, Span{ start = 0, end = 11 }, value_name, value_id, null, .constant, value, ) declarations [1]NodeId :: [declaration] package :: try add_package(&builder, Span{ start = 0, end = 11 }, declarations[..]) tree := finish(&builder, package) defer deinit(&tree) 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) try testing.expect_equal(value_name.end, statement.name.end) try testing.expect_equal(Mutability.constant, statement.mutability) try testing.expect_equal(null, statement.type) try testing.expect_equal(ExprKind.literal_int, expr_kind(&tree, statement.initializer)) try testing.expect_equal("value", source_text(&tree, statement.name)) } 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_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] literal :: try add_array_literal(&builder, span, elements[..]) empty :: try add_array_literal(&builder, span, &[]) indexed :: try add_index(&builder, span, literal, count) package :: try add_package(&builder, span, &[]) tree := finish(&builder, package) defer deinit(&tree) try testing.expect_equal(ExprKind.array_type, expr_kind(&tree, matrix)) try testing.expect_equal(null, array_type(&tree, matrix).count) try testing.expect(array_type(&tree, matrix).mutable) try testing.expect_equal(row, array_type(&tree, matrix).element) 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)) try testing.expect_equal(element, array_element(&tree, literal, 1)) try testing.expect_equal(0, array_element_count(&tree, empty)) try testing.expect_equal(ExprKind.index, expr_kind(&tree, indexed)) try testing.expect_equal(literal, index_expr(&tree, indexed).base) try testing.expect_equal(count, index_expr(&tree, indexed).index) } registers_borrowed_sources_and_removes_failed_source test { builder := init_builder(mem.c_allocator, "") defer deinit_builder(&builder) first :: try set_source(&builder, "first.hon", "first") root :: try add_package(&builder, Span{ start = 0, end = 5, source = first }, &[]) failed :: try set_source(&builder, "failed.hon", "failed") try testing.expect_equal(diagnostics.SourceId(1), failed) remove_source(&builder) try testing.expect_equal(first, builder.source_id) try testing.expect_equal("first", builder.source) next :: try set_source(&builder, "next.hon", "next") try testing.expect_equal(failed, next) # package roots may use a source other than the currently active source. declarations [1]NodeId :: [root] combined :: try add_package(&builder, Span{ start = 0, end = 5, source = first }, declarations[..]) tree :: view(&builder, combined) try testing.expect_equal(first, node_span(&tree, combined).source) try testing.expect_equal("first", source_text(&tree, node_span(&tree, combined))) try testing.expect_equal(2, source_files(&tree).len) try testing.expect_equal("first.hon", source_files(&tree)[usize(first)].path) try testing.expect_equal("next.hon", source_files(&tree)[usize(next)].path) try testing.expect_equal("next", source_files(&tree)[usize(next)].text) try testing.expect_equal(1, builder_package_decl_count(&builder, combined)) try testing.expect_equal(root, builder_package_decl(&builder, combined, 0)) } removes_only_registered_source_without_allocating_builder test { builder := init_builder(mem.c_allocator, "") defer deinit_builder(&builder) _ = try set_source(&builder, "failed.hon", "failed") remove_source(&builder) try testing.expect_equal(diagnostics.SourceId(0), builder.source_id) try testing.expect_equal("", builder.source) replacement :: try set_source(&builder, "replacement.hon", "") try testing.expect_equal(diagnostics.SourceId(0), replacement) } owns_generated_literal_text_across_finish test { tree Tree := undefined { builder := init_builder(mem.c_allocator, "") defer deinit_builder(&builder) source :: try set_source(&builder, "generated.hon", "input") at :: Span{ start = 0, end = 5, source = source } zero :: try add_integer(&builder, at, 0) maximum :: try add_integer(&builder, at, maxval!(u64)) enabled :: try add_boolean(&builder, at, true) disabled :: try add_boolean(&builder, at, false) try testing.expect_equal(source, builder.source_id) try testing.expect_equal("input", builder.source) declarations [4]NodeId :: [zero, maximum, enabled, disabled] root :: try add_package(&builder, at, declarations[..]) tree = finish(&builder, root) } defer deinit(&tree) zero :: package_decl(&tree, 0) maximum :: package_decl(&tree, 1) enabled :: package_decl(&tree, 2) disabled :: package_decl(&tree, 3) try testing.expect_equal(ExprKind.literal_int, expr_kind(&tree, zero)) try testing.expect_equal("0", literal_text(&tree, zero)) try testing.expect_equal("18446744073709551615", literal_text(&tree, maximum)) try testing.expect_equal(ExprKind.literal_bool, expr_kind(&tree, enabled)) try testing.expect_equal("true", literal_text(&tree, enabled)) try testing.expect_equal("false", literal_text(&tree, disabled)) try testing.expect_equal(1, source_files(&tree).len) try testing.expect_equal(diagnostics.SourceId(0), node_span(&tree, zero).source) try testing.expect_equal(0, node_span(&tree, zero).start) try testing.expect_equal(5, node_span(&tree, zero).end) try testing.expect_equal("input", source_text(&tree, node_span(&tree, zero))) try testing.expect_equal("generated.hon", source_files(&tree)[usize(node_span(&tree, zero).source)].path) try testing.expect_equal("generated.hon", source_files(&tree)[usize(node_span(&tree, maximum).source)].path) } streams_decoded_string_literal_bytes test { text :: "\"a\\\\\\\"\\n\\r\\t\\0\\x4a\\xFf\"" expected [9]u8 :: ['a', '\\', '"', '\n', '\r', '\t', 0, 'J', 255] cursor := usize(1) for (expected) |byte| try testing.expect_equal(byte, try string_next(text, &cursor)) try testing.expect_equal(text.len - 1, cursor) malformed [6][]u8 :: ["\"\\q\"", "\"\\x\"", "\"\\x1\"", "\"\\xG0\"", "\"\\x0G\"", "\"\\\""] for (malformed) |literal| { cursor = 1 _ = string_next(literal, &cursor) catch |error| { try testing.expect_equal(StringError.invalid_escape, error) continue } try testing.expect(false) } }