expand yield to if-statements and loops
This commit is contained in:
+55
-2
@@ -2131,8 +2131,10 @@ yield_compiles_and_runs :: proc(t: ^testing.T) {
|
||||
status := compiler_core.compile_package("examples/programs/yield", output)
|
||||
testing.expect_value(t, status, 0)
|
||||
state := run_executable(output)
|
||||
// Untyped/typed value blocks, the value captured before block defers run, and
|
||||
// reassignment from a value block together produce 42.
|
||||
// Value blocks (untyped/typed, defer-spill, reassignment) plus value if-statements
|
||||
// (untyped/typed/reassign/else-if/defer) and value loops (a labeled `for` search
|
||||
// yielding `?usize` on both the found and not-found paths, and a labeled `while`)
|
||||
// together produce 42.
|
||||
testing.expect_value(t, state.exit_code, 42)
|
||||
}
|
||||
|
||||
@@ -2175,6 +2177,57 @@ yield_misuse_is_diagnosed :: proc(t: ^testing.T) {
|
||||
testing.expect(t, misplaced_yield)
|
||||
}
|
||||
|
||||
@(test)
|
||||
yield_control_flow_is_diagnosed :: proc(t: ^testing.T) {
|
||||
// Value if/loop misuse (milestone 20.5): an `if` value without an `else`; a
|
||||
// branch that does not end in `yield`; a value loop whose body lacks a trailing
|
||||
// fall-through `yield`; and a `yield :label` with no matching value loop.
|
||||
text := `main :: func() i32 {
|
||||
noelse :: if (true) {
|
||||
yield 1
|
||||
}
|
||||
badbranch :: if (true) {
|
||||
k :: 5
|
||||
} else {
|
||||
yield 2
|
||||
}
|
||||
noloopyield :: for 0..10 |i| blk: {
|
||||
if (i == 0) yield :blk i
|
||||
}
|
||||
for 0..10 |j| stray: {
|
||||
yield :stray j
|
||||
}
|
||||
return noelse + badbranch + noloopyield
|
||||
}
|
||||
`
|
||||
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)
|
||||
|
||||
no_else := false
|
||||
branch_no_yield := false
|
||||
loop_no_yield := false
|
||||
stray_label := false
|
||||
for diagnostic in diagnostics.items {
|
||||
no_else = no_else || strings.contains(diagnostic.message, "an 'if' used as a value must have an 'else'")
|
||||
branch_no_yield = branch_no_yield || strings.contains(diagnostic.message, "a value block must end with an explicit 'yield'")
|
||||
loop_no_yield = loop_no_yield || strings.contains(diagnostic.message, "a value loop's body must end with a 'yield'")
|
||||
stray_label = stray_label || strings.contains(diagnostic.message, "no enclosing value loop is labeled 'stray'")
|
||||
}
|
||||
testing.expect(t, no_else)
|
||||
testing.expect(t, branch_no_yield)
|
||||
testing.expect(t, loop_no_yield)
|
||||
testing.expect(t, stray_label)
|
||||
}
|
||||
|
||||
@(test)
|
||||
foreign_function_links_from_c_source :: proc(t: ^testing.T) {
|
||||
output := "/tmp/brolang-test-foreign-source"
|
||||
|
||||
Reference in New Issue
Block a user