From 6b3f8f519dda8f1ac20ecd6a79da01b0b5c11872 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 26 Dec 2022 23:35:13 +0200 Subject: [PATCH] cgen: fill in the new `FieldData` fields, add tests (#16774) --- vlib/v/checker/comptime.v | 2 +- vlib/v/gen/c/comptime.v | 12 +- .../comptime_for_in_fields_FieldData_test.v | 126 ++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/comptime_for_in_fields_FieldData_test.v diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index 8654ade577..8c5da31649 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -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 diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 30e413a3d0..3508d2884a 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -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) @@ -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++ diff --git a/vlib/v/tests/comptime_for_in_fields_FieldData_test.v b/vlib/v/tests/comptime_for_in_fields_FieldData_test.v new file mode 100644 index 0000000000..4cdfe296c4 --- /dev/null +++ b/vlib/v/tests/comptime_for_in_fields_FieldData_test.v @@ -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 + } + } +}