mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: implement for_stmt of multi_init_vars or multi_assign_vars (#8917)
This commit is contained in:
parent
63ed3c0d41
commit
05a08530ff
@ -766,6 +766,7 @@ pub:
|
||||
has_cond bool
|
||||
inc Stmt // i++; i += 2
|
||||
has_inc bool
|
||||
is_multi bool // for a,b := 0,1; a < 10; a,b = a+b, a {...}
|
||||
stmts []Stmt
|
||||
pos token.Position
|
||||
pub mut:
|
||||
|
@ -1091,74 +1091,21 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
prev_branch_parent_pos := g.branch_parent_pos
|
||||
g.branch_parent_pos = node.pos.pos
|
||||
g.write_v_source_line_info(node.pos)
|
||||
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: {}')
|
||||
}
|
||||
g.for_c_stmt(node)
|
||||
g.branch_parent_pos = prev_branch_parent_pos
|
||||
}
|
||||
ast.ForInStmt {
|
||||
prev_branch_parent_pos := g.branch_parent_pos
|
||||
g.branch_parent_pos = node.pos.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
|
||||
}
|
||||
ast.ForStmt {
|
||||
prev_branch_parent_pos := g.branch_parent_pos
|
||||
g.branch_parent_pos = node.pos.pos
|
||||
g.write_v_source_line_info(node.pos)
|
||||
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: {}')
|
||||
}
|
||||
g.for_stmt(node)
|
||||
g.branch_parent_pos = prev_branch_parent_pos
|
||||
}
|
||||
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 {
|
||||
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.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(';')
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,10 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||
}
|
||||
p.close_scope()
|
||||
return for_stmt
|
||||
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon {
|
||||
// `for i := 0; i < 10; i++ {`
|
||||
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon]
|
||||
|| 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 {
|
||||
p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
||||
return ast.Stmt{}
|
||||
@ -41,7 +43,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||
mut has_init := false
|
||||
mut has_cond := 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()
|
||||
has_init = true
|
||||
}
|
||||
@ -58,6 +62,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||
has_cond = true
|
||||
}
|
||||
p.check(.semicolon)
|
||||
if !is_multi {
|
||||
is_multi = p.peek_tok.kind == .comma
|
||||
}
|
||||
if p.tok.kind != .lcbr {
|
||||
inc = p.stmt(false)
|
||||
has_inc = true
|
||||
@ -70,6 +77,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||
has_init: has_init
|
||||
has_cond: has_cond
|
||||
has_inc: has_inc
|
||||
is_multi: is_multi
|
||||
init: init
|
||||
cond: cond
|
||||
inc: inc
|
||||
|
34
vlib/v/tests/for_c_multi_vars.v
Normal file
34
vlib/v/tests/for_c_multi_vars.v
Normal file
@ -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
Block a user