braceless one-statement for-loops

This commit is contained in:
2026-07-15 23:27:18 +02:00
parent 7de0b7f268
commit 3cc750b3b2
4 changed files with 107 additions and 22 deletions
+80 -1
View File
@@ -8798,7 +8798,7 @@ main func() void {
if (x == 2) x = 3 else x = 4
if (x > 0) { x = 10 } else x = 11
v ?i32 = 5
if v |u| _ = u
if (v) |u| _ = u
}
`
source_file := source.Source{path="test.bro", text=text}
@@ -8859,6 +8859,29 @@ parser_diagnoses_braceless_if_without_parens_or_call :: proc(t: ^testing.T) {
testing.expect(t, strings.contains(diagnostics.items[0].message, "parenthesized"))
}
@(test)
parser_diagnoses_braceless_for_and_unwrap_without_parens_or_call :: proc(t: ^testing.T) {
text := `main func() void {
for tokens.items |item| _ = item
value ?i32 = 1
if value |present| _ = present
}
`
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)
module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&module)
testing.expect_value(t, len(diagnostics.items), 2)
testing.expect(t, strings.contains(diagnostics.items[0].message, "brace-less 'for'"))
testing.expect(t, strings.contains(diagnostics.items[1].message, "brace-less 'if'"))
}
@(test)
braceless_if_compiles_and_runs :: proc(t: ^testing.T) {
directory := "/tmp/brolang-test-braceless-if"
@@ -9345,6 +9368,62 @@ for_loop_tokens_and_parser_capture_range_shape :: proc(t: ^testing.T) {
testing.expect_value(t, module.exprs[third.expr].integer, u64(1))
}
@(test)
parser_accepts_braceless_for_bodies :: proc(t: ^testing.T) {
text := `make_items func() [2]i32 { return [1, 2] }
main func() void {
for (tokens.items) |item| _ = item
for make_items() |item|
_ = item
}
`
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)
module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&module)
testing.expect_value(t, len(diagnostics.items), 0)
main := module.functions[1]
testing.expect_value(t, len(main.body), 2)
parenthesized := module.statements[main.body[0]]
call := module.statements[main.body[1]]
testing.expect_value(t, len(parenthesized.body), 1)
testing.expect(t, module.exprs[parenthesized.expr].parenthesized)
testing.expect_value(t, len(call.body), 1)
testing.expect_value(t, module.exprs[call.expr].kind, ast.Expr_Kind.Call)
}
@(test)
braceless_for_compiles_and_runs :: proc(t: ^testing.T) {
directory := "/tmp/brolang-test-braceless-for"
main_path := "/tmp/brolang-test-braceless-for/main.bro"
output := "/tmp/brolang-test-braceless-for-output"
text := `make_items func() [2]i32 { return [20, 2] }
main func() i32 {
total i32 = 0
items :: [10, 11]
for (items) |item| total += item
for make_items() |item|
total += item
return total
}
`
_ = 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)text))
status := compiler_core.compile_package(directory, output)
testing.expect_value(t, status, 0)
state := run_executable(output)
testing.expect_value(t, state.exit_code, 43)
}
@(test)
range_bound_parenthesization_is_enforced :: proc(t: ^testing.T) {
text := `main func() void {