io interface (first pass)

This commit is contained in:
2026-07-13 12:02:06 +02:00
parent 2ed333c70d
commit 288df082e2
11 changed files with 589 additions and 20 deletions
+113 -1
View File
@@ -2051,6 +2051,116 @@ bodyless_root_main_recovers_as_a_trap_definition :: proc(t: ^testing.T) {
testing.expect(t, !strings.contains(llvm_text, "declare i32 @main()"))
}
@(test)
milestone_33_injects_explicit_io_provider_and_runs_std_io :: proc(t: ^testing.T) {
sources := source.init_store()
defer source.destroy_store(&sources)
diagnostics := source.init_store_diagnostics(&sources)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
ast_module, loaded := loader.load(
"examples/programs/io",
&sources,
&diagnostics,
&symbols,
project_root_path=".",
)
defer ast.destroy_module(&ast_module)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
defer hir.destroy_module(&hir_module)
ir_module := lower.lower(&hir_module)
defer ir.destroy_module(&ir_module)
llvm_text := llvm.emit(&ir_module, &diagnostics, &symbols)
defer delete(llvm_text)
testing.expect(t, loaded)
testing.expect_value(t, len(diagnostics.items), 0)
testing.expect(t, hir_module.injected_main != hir.INVALID_FUNCTION)
testing.expect(t, hir_module.io_provider != hir.INVALID_FUNCTION)
testing.expect_value(t, count_substring_occurrences(llvm_text, "define i32 @main()"), 1)
testing.expect_value(t, count_substring_occurrences(llvm_text, "define internal fastcc i32 @bro__p0__main__"), 1)
testing.expect_value(t, count_substring_occurrences(llvm_text, "declare i64 @write("), 1)
output := "/tmp/brolang-test-io"
defer _ = os.remove(output)
status := compiler_core.compile_package(
"examples/programs/io",
output,
nil,
target.DEFAULT,
cimport.Options{},
".",
)
testing.expect_value(t, status, 0)
state, stdout, stderr, _ := os2.process_exec(
os2.Process_Desc{command=[]string{output}},
context.allocator,
)
defer delete(stdout)
defer delete(stderr)
testing.expect_value(t, state.exit_code, 0)
testing.expect_value(t, string(stdout), "io-ok\n")
}
@(test)
milestone_33_rejects_non_io_and_extra_main_parameters :: proc(t: ^testing.T) {
cases := [?]string{
"main func(value i32) void {}\n",
"main func(left, right i32) void {}\n",
}
for text in cases {
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
symbols := symbol.init_table()
stream := lexer.lex(&source_file, &diagnostics, &symbols)
ast_module := parser.parse(&stream, &source_file, &diagnostics)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
found := false
for diagnostic in diagnostics.items {
found = found || strings.contains(
diagnostic.message,
"take no parameters or one @std/io Io",
)
}
testing.expect(t, found)
hir.destroy_module(&hir_module)
ast.destroy_module(&ast_module)
delete(stream.items)
symbol.destroy_table(&symbols)
source.destroy_diagnostics(&diagnostics)
}
}
@(test)
milestone_33_rejects_an_incompatible_runtime_write_declaration :: proc(t: ^testing.T) {
text := `write c_func(_ c_int, _ c_int, _ c_ulong) c_long
main func() void {}
`
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
stream := lexer.lex(&source_file, &diagnostics, &symbols)
defer delete(stream.items)
ast_module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&ast_module)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
defer hir.destroy_module(&hir_module)
found := false
for diagnostic in diagnostics.items {
found = found || strings.contains(
diagnostic.message,
"external C function 'write' conflicts with the compiler runtime declaration",
)
}
testing.expect(t, found)
}
@(test)
literal_addition_trees_fold_with_contextual_types :: proc(t: ^testing.T) {
text := `return_i16 func() i16 {
@@ -9911,8 +10021,9 @@ main func() i32 {
value Animal = .cat
values [2]Animal :: [.dog, Animal.bird]
number Nat = identity(.two)
ordinal c_int :: c_int(number)
_ = variadic(0, number)
if take(value) == Animal.cat and values[0] != values[1] and number == Nat.two {
if take(value) == Animal.cat and values[0] != values[1] and number == Nat.two and ordinal == 2 {
return 0
}
return 1
@@ -9954,6 +10065,7 @@ main func() i32 {
testing.expect_value(t, nat_members[0].value, i128(1))
testing.expect_value(t, nat_members[1].value, i128(2))
testing.expect_value(t, nat_members[2].value, i128(5))
testing.expect(t, strings.contains(llvm_text, "zext i16"))
testing.expect_value(t, types.runtime_representation(animal, &ast_module.type_store), types.U16)
testing.expect_value(t, types.size(animal, &ast_module.type_store), u64(2))
testing.expect(t, hir_module.globals[0].is_static)