fix comptime yield targeting

This commit is contained in:
2026-07-22 12:01:22 +02:00
parent ec5880e757
commit 21ff291788
4 changed files with 597 additions and 84 deletions
+59 -1
View File
@@ -5064,7 +5064,7 @@ main func() void {
found_expired = found_expired || strings.contains(message, "expired storage")
found_quota = found_quota || strings.contains(message, "comptime evaluation exceeded the step quota")
found_missing = found_missing || strings.contains(message, "did not return a value")
found_yield = found_yield || strings.contains(message, "comptime block must yield a value")
found_yield = found_yield || strings.contains(message, "a value block must end with an explicit 'yield'")
}
testing.expect(t, found_runtime)
testing.expect(t, runtime_only_count >= 2)
@@ -7428,6 +7428,64 @@ yield_misuse_is_diagnosed :: proc(t: ^testing.T) {
testing.expect(t, misplaced_yield)
}
@(test)
comptime_yield_targets_match_value_source_semantics :: proc(t: ^testing.T) {
directory := "/tmp/brolang-test-comptime-yield-targets"
main_path := "/tmp/brolang-test-comptime-yield-targets/main.bro"
output := "/tmp/brolang-test-comptime-yield-targets-output"
valid_text := `selected :: ${
via_if :: if true {
yield 1
} else {
yield 2
}
via_label :: done: {
if true {
yield :done 3
}
yield :done 4
}
yield via_if + via_label
}
main func() i32 { return selected - 4 }
`
_ = os2.remove_all(directory)
defer _ = os2.remove_all(directory)
defer _ = os.remove(output)
testing.expect(t, os.make_directory(directory) == nil)
testing.expect(t, os.write_entire_file(main_path, transmute([]byte)valid_text))
testing.expect_value(t, compiler_core.compile_package(directory, output), 0)
state := run_executable(output)
testing.expect_value(t, state.exit_code, 0)
invalid_text := `invalid :: ${
if false {
yield 1
}
yield 2
}
main func() void {}
`
source_file := source.Source{path="invalid_comptime_yield.bro", text=invalid_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, "'yield' is only valid as the final statement of a value block")
}
testing.expect(t, found)
}
@(test)
yield_control_flow_is_diagnosed :: proc(t: ^testing.T) {
// Value if/loop/block misuse: an `if` value without an `else`; a branch that neither