cgen: fix `for match {...} {` and `for select {...} {` (#6441)

pull/6457/head
Uwe Krüger 2020-09-23 06:05:12 +02:00 committed by GitHub
parent 4774c89381
commit 9c0758639b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 5 deletions

View File

@ -2295,6 +2295,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
} }
ast.ForStmt { ast.ForStmt {
c.in_for_count++ c.in_for_count++
c.expected_type = table.bool_type
typ := c.expr(node.cond) typ := c.expr(node.cond)
if !node.is_inf && typ.idx() != table.bool_type_idx && !c.pref.translated { if !node.is_inf && typ.idx() != table.bool_type_idx && !c.pref.translated {
c.error('non-bool used as for condition', node.pos) c.error('non-bool used as for condition', node.pos)

View File

@ -897,13 +897,15 @@ fn (mut g Gen) stmt(node ast.Stmt) {
ast.ForStmt { ast.ForStmt {
g.write_v_source_line_info(node.pos) g.write_v_source_line_info(node.pos)
g.is_vlines_enabled = false g.is_vlines_enabled = false
g.write('while (') g.writeln('for (;;) {')
if node.is_inf { if !node.is_inf {
g.write('1') g.indent++
} else { g.stmt_path_pos << g.out.len
g.write('if (!(')
g.expr(node.cond) g.expr(node.cond)
g.writeln(')) break;')
g.indent--
} }
g.writeln(') {')
g.is_vlines_enabled = true g.is_vlines_enabled = true
g.stmts(node.stmts) g.stmts(node.stmts)
g.writeln('}') g.writeln('}')
@ -2888,6 +2890,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
} }
g.writeln('}') g.writeln('}')
if is_expr { if is_expr {
g.empty_line = false
g.write(cur_line) g.write(cur_line)
g.write('($select_result != -2)') g.write('($select_result != -2)')
} }

View File

@ -0,0 +1,55 @@
fn test_for_match() {
mut a := 2
mut b := 0
for match a {
2 {
println('a == 2')
a = 0
true
}
0 {
println('a == 0')
a = 5
false
}
else {
println('unexpected branch')
false
}
} {
b++
println('${b}. run')
}
assert a == 5
assert b == 1
}
fn test_for_select() {
ch1 := chan int{}
ch2 := chan f64{}
go do_send(ch1, ch2)
mut a := 0
mut b := 0
for select {
x := <-ch1 {
a += x
}
y := <- ch2 {
a += int(y)
}
} {
// count number of receive events
b++
println('${b}. event')
}
assert a == 10
assert b == 3
}
fn do_send(ch1 chan int, ch2 chan f64) {
ch1 <- 3
ch2 <- 5.0
ch2.close()
ch1 <- 2
ch1.close()
}