Skip to content

Commit

Permalink
cgen: fill in the new FieldData fields, add tests (#16774)
Browse files Browse the repository at this point in the history
  • Loading branch information
spytheman committed Dec 26, 2022
1 parent 9b28a7a commit 6b3f8f5
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 2 deletions.
2 changes: 1 addition & 1 deletion vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ fn (mut c Checker) comptime_for(node ast.ComptimeFor) {

unwrapped_expr_type := c.unwrap_generic(field.typ)
tsym := c.table.sym(unwrapped_expr_type)
c.table.dumps[int(unwrapped_expr_type.clear_flag(.optional).clear_flag(.result))] = tsym.cname
c.table.dumps[int(unwrapped_expr_type.clear_flag(.optional).clear_flag(.result).clear_flag(.atomic_f))] = tsym.cname
}
c.comptime_for_field_var = ''
c.inside_comptime_for_field = false
Expand Down
12 changes: 11 additions & 1 deletion vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
'\t${node.val_var}.attrs = new_array_from_c_array(${attrs.len}, ${attrs.len}, sizeof(string), _MOV((string[${attrs.len}]){' +
attrs.join(', ') + '}));\n')
}
// field_sym := g.table.sym(field.typ)
field_sym := g.table.sym(field.typ)
// g.writeln('\t${node.val_var}.typ = _SLIT("$field_sym.name");')
styp := field.typ
unaliased_styp := g.table.unaliased_type(styp)
Expand All @@ -593,7 +593,17 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
g.writeln('\t${node.val_var}.unaliased_typ = ${unaliased_styp.idx()};')
g.writeln('\t${node.val_var}.is_pub = ${field.is_pub};')
g.writeln('\t${node.val_var}.is_mut = ${field.is_mut};')
//
g.writeln('\t${node.val_var}.is_shared = ${field.typ.has_flag(.shared_f)};')
g.writeln('\t${node.val_var}.is_atomic = ${field.typ.has_flag(.atomic_f)};')
g.writeln('\t${node.val_var}.is_optional = ${field.typ.has_flag(.optional)};')
//
g.writeln('\t${node.val_var}.is_array = ${field_sym.kind in [.array, .array_fixed]};')
g.writeln('\t${node.val_var}.is_map = ${field_sym.kind == .map};')
g.writeln('\t${node.val_var}.is_chan = ${field_sym.kind == .chan};')
g.writeln('\t${node.val_var}.is_struct = ${field_sym.kind == .struct_};')
g.writeln('\t${node.val_var}.indirections = ${field.typ.nr_muls()};')
//
g.comptime_var_type_map['${node.val_var}.typ'] = styp
g.stmts(node.stmts)
i++
Expand Down
126 changes: 126 additions & 0 deletions vlib/v/tests/comptime_for_in_fields_FieldData_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
struct Abc {
x int
y int
name string
}

struct Complex {
s string
i int
ch_i chan int
atomic_i atomic int
//
pointer1_i &int = unsafe { nil }
pointer2_i &&int = unsafe { nil }
pointer3_i &&&int = unsafe { nil }
//
array_i []int
map_i map[int]int
my_struct Abc
my_struct_shared shared Abc
//
o_s ?string
o_i ?int
o_ch_i ?chan int = chan int{cap: 10}
// o_atomic_i ?atomic int // TODO: cgen error, but should be probably a checker one, since optional atomics do not make sense
o_pointer1_i ?&int = unsafe { nil }
o_pointer2_i ?&&int = unsafe { nil }
o_pointer3_i ?&&&int = unsafe { nil }
//
o_array_i ?[]int
o_map_i ?map[int]int
o_my_struct ?Abc
o_my_struct_shared ?shared Abc
}

fn test_is_shared() {
$for f in Complex.fields {
if f.name.contains('_shared') {
assert f.is_shared, 'Complex.${f.name} should have f.is_shared set'
} else {
assert !f.is_shared, 'Complex.${f.name} should NOT have f.is_shared set'
}
}
}

fn test_is_atomic() {
$for f in Complex.fields {
if f.name.contains('atomic_') {
assert f.is_atomic, 'StructWithAtomicFields.${f.name} should have f.is_atomic set'
} else {
assert !f.is_atomic, 'StructWithAtomicFields.${f.name} should NOT have f.is_atomic set'
}
}
}

fn test_is_optional() {
$for f in Complex.fields {
if f.name.starts_with('o_') {
assert f.is_optional, 'Complex.${f.name} should have f.is_optional set'
} else {
assert !f.is_optional, 'Complex.${f.name} should NOT have f.is_optional set'
}
}
}

fn test_is_array() {
$for f in Complex.fields {
if f.name.contains('array_') {
assert f.is_array, 'Complex.${f.name} should have f.is_array set'
} else {
assert !f.is_array, 'Complex.${f.name} should NOT have f.is_array set'
}
}
}

fn test_is_map() {
$for f in Complex.fields {
if f.name.contains('map_') {
assert f.is_map, 'Complex.${f.name} should have f.is_map set'
} else {
assert !f.is_map, 'Complex.${f.name} should NOT have f.is_map set'
}
}
}

fn test_is_chan() {
$for f in Complex.fields {
if f.name.contains('ch_') {
assert f.is_chan, 'Complex.${f.name} should have f.is_chan set'
} else {
assert !f.is_chan, 'Complex.${f.name} should NOT have f.is_chan set'
}
}
}

fn test_is_struct() {
$for f in Complex.fields {
if f.name.contains('_struct') {
assert f.is_struct, 'Complex.${f.name} should have f.is_struct set'
} else {
assert !f.is_struct, 'Complex.${f.name} should NOT have f.is_struct set'
}
}
}

fn test_indirections() {
$for f in Complex.fields {
if f.name.contains('pointer') || f.name in ['my_struct_shared', 'o_my_struct_shared'] {
assert f.indirections > 0, 'Complex.${f.name} should have f.indirections > 0'
} else {
assert !(f.indirections > 0), 'Complex.${f.name} should NOT have f.indirections > 0'
}
if f.name.contains('pointer1') {
assert f.indirections == 1
}
if f.name.contains('pointer2') {
assert f.indirections == 2
}
if f.name.contains('pointer3') {
assert f.indirections == 3
}
if f.name.contains('my_struct_shared') {
assert f.indirections == 1
}
}
}

0 comments on commit 6b3f8f5

Please sign in to comment.