Skip to content

Commit 36c98b3

Browse files
authored
cgen: implement fixed array 'for in' for lvalue condition (#6151)
1 parent 46b4e2a commit 36c98b3

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

vlib/v/ast/ast.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,16 @@ pub fn (expr Expr) position() token.Position {
10591059
}
10601060
}
10611061

1062+
pub fn (expr Expr) is_lvalue() bool {
1063+
match expr {
1064+
Ident {return true}
1065+
IndexExpr {return expr.left.is_lvalue()}
1066+
SelectorExpr {return expr.expr.is_lvalue()}
1067+
else {}
1068+
}
1069+
return false
1070+
}
1071+
10621072
pub fn (stmt Stmt) position() token.Position {
10631073
match stmt {
10641074
AssertStmt { return stmt.pos }

vlib/v/gen/cgen.v

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,33 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
975975
}
976976
g.stmts(it.stmts)
977977
g.writeln('}')
978+
} else if it.kind == .array_fixed {
979+
atmp := g.new_tmp_var()
980+
atmp_type := g.typ(it.cond_type)
981+
if !it.cond.is_lvalue() {
982+
g.error('for in: unhandled condition `$it.cond`', it.pos)
983+
}
984+
// TODO rvalue cond
985+
g.write('$atmp_type *$atmp = &')
986+
g.expr(it.cond)
987+
g.writeln(';')
988+
i := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
989+
cond_sym := g.table.get_type_symbol(it.cond_type)
990+
info := cond_sym.info as table.ArrayFixed
991+
g.writeln('for (int $i = 0; $i != $info.size; ++$i) {')
992+
if it.val_var != '_' {
993+
val_sym := g.table.get_type_symbol(it.val_type)
994+
if val_sym.kind == .function {
995+
g.write('\t')
996+
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var))
997+
} else {
998+
styp := g.typ(it.val_type)
999+
g.write('\t$styp ${c_name(it.val_var)}')
1000+
}
1001+
g.writeln(' = (*$atmp)[$i];')
1002+
}
1003+
g.stmts(it.stmts)
1004+
g.writeln('}')
9781005
} else if it.kind == .map {
9791006
// `for key, val in map {`
9801007
g.writeln('// FOR IN map')
@@ -1038,7 +1065,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
10381065
g.writeln('}')
10391066
} else {
10401067
s := g.table.type_to_str(it.cond_type)
1041-
g.error('`for`: unhandled symbol `$it.cond` of type `$s`', it.pos)
1068+
g.error('for in: unhandled symbol `$it.cond` of type `$s`', it.pos)
10421069
}
10431070
}
10441071

vlib/v/tests/fixed_array_test.v

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ fn test_fixed_array_can_be_assigned() {
44
assert v[1] == 0
55
v = [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
66
assert v[1] == x
7+
v[1] = 2.0
8+
for i, e in v {
9+
assert e == i + 1
10+
}
711
v = [8]f64{}
812
assert v[1] == 0
913
// test slicing
@@ -32,6 +36,9 @@ fn test_fixed_array_can_be_assigned_to_a_struct_field() {
3236
ctx.vb = [1.1, x, 3.3, 4.4, 5.0, 6.0, 7.0, 8.9]!!
3337
assert ctx.vb[1] == x
3438
assert ctx.vb[7] == 8.9
39+
for i, e in ctx.vb {
40+
assert e == ctx.vb[i]
41+
}
3542
assert ctx.vb == ctx.vb
3643
/*
3744
println( ctx.vb[0] )

0 commit comments

Comments
 (0)