cgen: implement for_stmt of multi_init_vars or multi_assign_vars (#8917)
parent
63ed3c0d41
commit
05a08530ff
|
@ -766,6 +766,7 @@ pub:
|
||||||
has_cond bool
|
has_cond bool
|
||||||
inc Stmt // i++; i += 2
|
inc Stmt // i++; i += 2
|
||||||
has_inc bool
|
has_inc bool
|
||||||
|
is_multi bool // for a,b := 0,1; a < 10; a,b = a+b, a {...}
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
|
|
|
@ -1091,74 +1091,21 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
prev_branch_parent_pos := g.branch_parent_pos
|
prev_branch_parent_pos := g.branch_parent_pos
|
||||||
g.branch_parent_pos = node.pos.pos
|
g.branch_parent_pos = node.pos.pos
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
g.is_vlines_enabled = false
|
g.for_c_stmt(node)
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('$node.label:')
|
|
||||||
}
|
|
||||||
g.write('for (')
|
|
||||||
if !node.has_init {
|
|
||||||
g.write('; ')
|
|
||||||
} else {
|
|
||||||
g.stmt(node.init)
|
|
||||||
// Remove excess return and add space
|
|
||||||
if g.out.last_n(1) == '\n' {
|
|
||||||
g.out.go_back(1)
|
|
||||||
g.empty_line = false
|
|
||||||
g.write(' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node.has_cond {
|
|
||||||
g.expr(node.cond)
|
|
||||||
}
|
|
||||||
g.write('; ')
|
|
||||||
if node.has_inc {
|
|
||||||
g.stmt(node.inc)
|
|
||||||
}
|
|
||||||
g.writeln(') {')
|
|
||||||
g.is_vlines_enabled = true
|
|
||||||
g.stmts(node.stmts)
|
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('${node.label}__continue: {}')
|
|
||||||
}
|
|
||||||
g.writeln('}')
|
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('${node.label}__break: {}')
|
|
||||||
}
|
|
||||||
g.branch_parent_pos = prev_branch_parent_pos
|
g.branch_parent_pos = prev_branch_parent_pos
|
||||||
}
|
}
|
||||||
ast.ForInStmt {
|
ast.ForInStmt {
|
||||||
prev_branch_parent_pos := g.branch_parent_pos
|
prev_branch_parent_pos := g.branch_parent_pos
|
||||||
g.branch_parent_pos = node.pos.pos
|
g.branch_parent_pos = node.pos.pos
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
g.for_in(node)
|
g.for_in_stmt(node)
|
||||||
g.branch_parent_pos = prev_branch_parent_pos
|
g.branch_parent_pos = prev_branch_parent_pos
|
||||||
}
|
}
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
prev_branch_parent_pos := g.branch_parent_pos
|
prev_branch_parent_pos := g.branch_parent_pos
|
||||||
g.branch_parent_pos = node.pos.pos
|
g.branch_parent_pos = node.pos.pos
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
g.is_vlines_enabled = false
|
g.for_stmt(node)
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('$node.label:')
|
|
||||||
}
|
|
||||||
g.writeln('for (;;) {')
|
|
||||||
if !node.is_inf {
|
|
||||||
g.indent++
|
|
||||||
g.stmt_path_pos << g.out.len
|
|
||||||
g.write('if (!(')
|
|
||||||
g.expr(node.cond)
|
|
||||||
g.writeln(')) break;')
|
|
||||||
g.indent--
|
|
||||||
}
|
|
||||||
g.is_vlines_enabled = true
|
|
||||||
g.stmts(node.stmts)
|
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('\t${node.label}__continue: {}')
|
|
||||||
}
|
|
||||||
g.writeln('}')
|
|
||||||
if node.label.len > 0 {
|
|
||||||
g.writeln('${node.label}__break: {}')
|
|
||||||
}
|
|
||||||
g.branch_parent_pos = prev_branch_parent_pos
|
g.branch_parent_pos = prev_branch_parent_pos
|
||||||
}
|
}
|
||||||
ast.GlobalDecl {
|
ast.GlobalDecl {
|
||||||
|
@ -1286,7 +1233,108 @@ fn (mut g Gen) write_defer_stmts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) for_in(it ast.ForInStmt) {
|
fn (mut g Gen) for_c_stmt(node ast.ForCStmt) {
|
||||||
|
if node.is_multi {
|
||||||
|
g.is_vlines_enabled = false
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('$node.label:')
|
||||||
|
}
|
||||||
|
g.writeln('{')
|
||||||
|
g.indent++
|
||||||
|
if node.has_init {
|
||||||
|
g.stmt(node.init)
|
||||||
|
}
|
||||||
|
g.writeln('bool _is_first = true;')
|
||||||
|
g.writeln('while (true) {')
|
||||||
|
g.writeln('\tif (_is_first) {')
|
||||||
|
g.writeln('\t\t_is_first = false;')
|
||||||
|
g.writeln('\t} else {')
|
||||||
|
if node.has_inc {
|
||||||
|
g.indent++
|
||||||
|
g.stmt(node.inc)
|
||||||
|
g.writeln(';')
|
||||||
|
g.indent--
|
||||||
|
}
|
||||||
|
g.writeln('}')
|
||||||
|
if node.has_cond {
|
||||||
|
g.write('if (!(')
|
||||||
|
g.expr(node.cond)
|
||||||
|
g.writeln(')) break;')
|
||||||
|
}
|
||||||
|
g.is_vlines_enabled = true
|
||||||
|
g.stmts(node.stmts)
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('${node.label}__continue: {}')
|
||||||
|
}
|
||||||
|
g.writeln('}')
|
||||||
|
g.indent--
|
||||||
|
g.writeln('}')
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('${node.label}__break: {}')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.is_vlines_enabled = false
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('$node.label:')
|
||||||
|
}
|
||||||
|
g.write('for (')
|
||||||
|
if !node.has_init {
|
||||||
|
g.write('; ')
|
||||||
|
} else {
|
||||||
|
g.stmt(node.init)
|
||||||
|
// Remove excess return and add space
|
||||||
|
if g.out.last_n(1) == '\n' {
|
||||||
|
g.out.go_back(1)
|
||||||
|
g.empty_line = false
|
||||||
|
g.write(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.has_cond {
|
||||||
|
g.expr(node.cond)
|
||||||
|
}
|
||||||
|
g.write('; ')
|
||||||
|
if node.has_inc {
|
||||||
|
g.stmt(node.inc)
|
||||||
|
}
|
||||||
|
g.writeln(') {')
|
||||||
|
g.is_vlines_enabled = true
|
||||||
|
g.stmts(node.stmts)
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('${node.label}__continue: {}')
|
||||||
|
}
|
||||||
|
g.writeln('}')
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('${node.label}__break: {}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
||||||
|
g.is_vlines_enabled = false
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('$node.label:')
|
||||||
|
}
|
||||||
|
g.writeln('for (;;) {')
|
||||||
|
if !node.is_inf {
|
||||||
|
g.indent++
|
||||||
|
g.stmt_path_pos << g.out.len
|
||||||
|
g.write('if (!(')
|
||||||
|
g.expr(node.cond)
|
||||||
|
g.writeln(')) break;')
|
||||||
|
g.indent--
|
||||||
|
}
|
||||||
|
g.is_vlines_enabled = true
|
||||||
|
g.stmts(node.stmts)
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('\t${node.label}__continue: {}')
|
||||||
|
}
|
||||||
|
g.writeln('}')
|
||||||
|
if node.label.len > 0 {
|
||||||
|
g.writeln('${node.label}__break: {}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) for_in_stmt(it ast.ForInStmt) {
|
||||||
if it.label.len > 0 {
|
if it.label.len > 0 {
|
||||||
g.writeln('\t$it.label: {}')
|
g.writeln('\t$it.label: {}')
|
||||||
}
|
}
|
||||||
|
@ -2191,7 +2239,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
g.right_is_opt = false
|
g.right_is_opt = false
|
||||||
g.is_assign_rhs = false
|
g.is_assign_rhs = false
|
||||||
if g.inside_ternary == 0 && !assign_stmt.is_simple {
|
if g.inside_ternary == 0 && (assign_stmt.left.len > 1 || !assign_stmt.is_simple) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
}
|
}
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
return for_stmt
|
return for_stmt
|
||||||
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon {
|
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon]
|
||||||
// `for i := 0; i < 10; i++ {`
|
|| p.tok.kind == .semicolon || (p.peek_tok.kind == .comma && p.peek_tok2.kind != .key_mut
|
||||||
|
&& p.peek_tok3.kind != .key_in) {
|
||||||
|
// `for i := 0; i < 10; i++ {` or `for a,b := 0,1; a < 10; a++ {`
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
|
@ -41,7 +43,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
mut has_init := false
|
mut has_init := false
|
||||||
mut has_cond := false
|
mut has_cond := false
|
||||||
mut has_inc := false
|
mut has_inc := false
|
||||||
if p.peek_tok.kind in [.assign, .decl_assign] {
|
mut is_multi := p.peek_tok.kind == .comma && p.peek_tok2.kind != .key_mut
|
||||||
|
&& p.peek_tok3.kind != .key_in
|
||||||
|
if p.peek_tok.kind in [.assign, .decl_assign] || is_multi {
|
||||||
init = p.assign_stmt()
|
init = p.assign_stmt()
|
||||||
has_init = true
|
has_init = true
|
||||||
}
|
}
|
||||||
|
@ -58,6 +62,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
has_cond = true
|
has_cond = true
|
||||||
}
|
}
|
||||||
p.check(.semicolon)
|
p.check(.semicolon)
|
||||||
|
if !is_multi {
|
||||||
|
is_multi = p.peek_tok.kind == .comma
|
||||||
|
}
|
||||||
if p.tok.kind != .lcbr {
|
if p.tok.kind != .lcbr {
|
||||||
inc = p.stmt(false)
|
inc = p.stmt(false)
|
||||||
has_inc = true
|
has_inc = true
|
||||||
|
@ -70,6 +77,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
has_init: has_init
|
has_init: has_init
|
||||||
has_cond: has_cond
|
has_cond: has_cond
|
||||||
has_inc: has_inc
|
has_inc: has_inc
|
||||||
|
is_multi: is_multi
|
||||||
init: init
|
init: init
|
||||||
cond: cond
|
cond: cond
|
||||||
inc: inc
|
inc: inc
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
fn test_for_c_multi_init_vars() {
|
||||||
|
mut rets := []string{}
|
||||||
|
for a,b := 0,1; a < 5; a++ {
|
||||||
|
if a == 3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b = a + 1
|
||||||
|
println('$a, $b')
|
||||||
|
rets << '$a, $b'
|
||||||
|
}
|
||||||
|
println(rets)
|
||||||
|
assert rets[0] == '0, 1'
|
||||||
|
assert rets[1] == '1, 2'
|
||||||
|
assert rets[2] == '2, 3'
|
||||||
|
assert rets[3] == '4, 5'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_for_c_multi_inc_vars() {
|
||||||
|
mut rets := []string{}
|
||||||
|
mut b := 1
|
||||||
|
for a := 0; a < 10; a,b = b,a+b {
|
||||||
|
if a in [2, 3] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println('$a, $b')
|
||||||
|
rets << '$a, $b'
|
||||||
|
}
|
||||||
|
println(rets)
|
||||||
|
assert rets[0] == '0, 1'
|
||||||
|
assert rets[1] == '1, 1'
|
||||||
|
assert rets[2] == '1, 2'
|
||||||
|
assert rets[3] == '5, 8'
|
||||||
|
assert rets[4] == '8, 13'
|
||||||
|
}
|
Loading…
Reference in New Issue