From da090f91d8e0fb9d2d3ec4bd766b020d1c308df7 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 20 May 2021 15:59:02 +0300 Subject: [PATCH] cgen: fix using and auto printing `x := [16]&Type{}` --- vlib/v/ast/table.v | 4 +- vlib/v/gen/c/auto_str_methods.v | 53 +++++++++------- vlib/v/gen/c/cgen.v | 22 ++++--- .../printing_fixed_array_of_pointers.out | 60 +++++++++++++++++++ .../inout/printing_fixed_array_of_pointers.vv | 47 +++++++++++++++ 5 files changed, 152 insertions(+), 34 deletions(-) create mode 100644 vlib/v/tests/inout/printing_fixed_array_of_pointers.out create mode 100644 vlib/v/tests/inout/printing_fixed_array_of_pointers.vv diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index b58f0b3231..3b2343336b 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -623,7 +623,7 @@ pub fn (t &Table) array_fixed_cname(elem_type Type, size int) string { elem_type_sym := t.get_type_symbol(elem_type) mut res := '' if elem_type.is_ptr() { - res = '_ptr' + res = '_ptr$elem_type.nr_muls()' } return 'Array_fixed_${elem_type_sym.cname}_$size' + res } @@ -797,12 +797,12 @@ pub fn (mut t Table) find_or_register_array_with_dims(elem_type Type, nr_dims in pub fn (mut t Table) find_or_register_array_fixed(elem_type Type, size int, size_expr Expr) int { name := t.array_fixed_name(elem_type, size, size_expr) - cname := t.array_fixed_cname(elem_type, size) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { return existing_idx } + cname := t.array_fixed_cname(elem_type, size) // register array_fixed_type := TypeSymbol{ kind: .array_fixed diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index c3d76fd5dd..06cae0665c 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -249,13 +249,9 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string // There is a custom .str() method, so use it. // NB: we need to take account of whether the user has defined // `fn (x T) str() {` or `fn (x &T) str() {`, and convert accordingly - if (str_method_expects_ptr && is_elem_ptr) || (!str_method_expects_ptr && !is_elem_ptr) { - g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}(it);') - } else if str_method_expects_ptr && !is_elem_ptr { - g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}(&it);') - } else if !str_method_expects_ptr && is_elem_ptr { - g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}(*it);') - } + deref, deref_label := deref_kind(str_method_expects_ptr, is_elem_ptr, typ) + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("$deref_label"));') + g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}( $deref it);') } } g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);') @@ -306,23 +302,27 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_ if sym.kind == .function { g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();') } else { + deref, deref_label := deref_kind(str_method_expects_ptr, is_elem_ptr, typ) g.auto_str_funcs.writeln('\tfor (int i = 0; i < $info.size; ++i) {') if should_use_indent_func(sym.kind) && !sym_has_str_method { - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}(a[i]));') + if is_elem_ptr { + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("$deref_label"));') + g.auto_str_funcs.writeln('\t\tif ( 0 == a[i] ) {') + g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, _SLIT("0"));') + g.auto_str_funcs.writeln('\t\t}else{') + g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( $deref a[i]) );') + g.auto_str_funcs.writeln('\t\t}') + } else { + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( $deref a[i]) );') + } } else if sym.kind in [.f32, .f64] { g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("%g", 1, a[i]));') } else if sym.kind == .string { g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("\'%.*s\\000\'", 2, a[i]));') } else if sym.kind == .rune { - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("`%.*s\\000`", 2, ${elem_str_fn_name}(a[i])));') + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("`%.*s\\000`", 2, ${elem_str_fn_name}( $deref a[i])));') } else { - if (str_method_expects_ptr && is_elem_ptr) || (!str_method_expects_ptr && !is_elem_ptr) { - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}(a[i]));') - } else if str_method_expects_ptr && !is_elem_ptr { - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}(&a[i]));') - } else if !str_method_expects_ptr && is_elem_ptr { - g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}(*a[i]));') - } + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( $deref a[i]));') } } g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {') @@ -442,13 +442,9 @@ fn (mut g Gen) gen_str_for_multi_return(info ast.MultiReturn, styp string, str_f } else if sym.kind == .function { g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}());') } else { - if (str_method_expects_ptr && is_arg_ptr) || (!str_method_expects_ptr && !is_arg_ptr) { - g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}(a.arg$i));') - } else if str_method_expects_ptr && !is_arg_ptr { - g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}(&a.arg$i));') - } else if !str_method_expects_ptr && is_arg_ptr { - g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}(*a.arg$i));') - } + deref, deref_label := deref_kind(str_method_expects_ptr, is_arg_ptr, typ) + g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("$deref_label"));') + g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}( $deref a.arg$i));') } if i != info.types.len - 1 { g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT(", "));') @@ -748,3 +744,14 @@ fn (mut g Gen) gen_str_for_fn_type(info ast.FnType, styp string, str_fn_name str fn styp_to_str_fn_name(styp string) string { return styp.replace_each(['*', '', '.', '__', ' ', '__']) + '_str' } + +fn deref_kind(str_method_expects_ptr bool, is_elem_ptr bool, typ ast.Type) (string, string) { + if str_method_expects_ptr != is_elem_ptr { + if is_elem_ptr { + return '*'.repeat(typ.nr_muls()), '&'.repeat(typ.nr_muls()) + } else { + return '&', '' + } + } + return '', '' +} diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index a72dde4d44..4260a72c66 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5747,22 +5747,26 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { // .array_fixed { styp := typ.cname // array_fixed_char_300 => char x[300] - mut fixed := styp[12..] - len := styp.after('_') - fixed = fixed[..fixed.len - len.len - 1] - if fixed.starts_with('C__') { - fixed = fixed[3..] + // [16]&&&EventListener{} => Array_fixed_main__EventListener_16_ptr3 + // => typedef main__EventListener*** Array_fixed_main__EventListener_16_ptr3 [16] + mut fixed_elem_name := g.typ(typ.info.elem_type.set_nr_muls(0)) + if typ.info.elem_type.is_ptr() { + fixed_elem_name += '*'.repeat(typ.info.elem_type.nr_muls()) + } + len := typ.info.size + if fixed_elem_name.starts_with('C__') { + fixed_elem_name = fixed_elem_name[3..] } if elem_sym.info is ast.FnType { pos := g.out.len g.write_fn_ptr_decl(&elem_sym.info, '') - fixed = g.out.after(pos) - g.out.go_back(fixed.len) - mut def_str := 'typedef $fixed;' + fixed_elem_name = g.out.after(pos) + g.out.go_back(fixed_elem_name.len) + mut def_str := 'typedef $fixed_elem_name;' def_str = def_str.replace_once('(*)', '(*$styp[$len])') g.type_definitions.writeln(def_str) } else { - g.type_definitions.writeln('typedef $fixed $styp [$len];') + g.type_definitions.writeln('typedef $fixed_elem_name $styp [$len];') } } } diff --git a/vlib/v/tests/inout/printing_fixed_array_of_pointers.out b/vlib/v/tests/inout/printing_fixed_array_of_pointers.out new file mode 100644 index 0000000000..befcc58326 --- /dev/null +++ b/vlib/v/tests/inout/printing_fixed_array_of_pointers.out @@ -0,0 +1,60 @@ +------------------------------------ +[EventListener{ + x: 123 +}, EventListener{ + x: 0 +}, EventListener{ + x: 0 +}] +- 1 level of indirection - +[&EventListener{ + x: 123 +}, &0, &0] +[&EventListener{ + x: 123 +}, &0, &0] +- 2 level of indirection - +[&&EventListener{ + x: 123 +}, &&0, &&0] +- 3 level of indirection - +[&&&EventListener{ + x: 123 +}, &&&0, &&&0] +----------------------------------------------------- +- all: +StructOfFixedArraysOfListeners{ + elisteners: [EventListener{ + x: 123 +}, EventListener{ + x: 0 +}, EventListener{ + x: 0 +}] + apelisteners: [&EventListener{ + x: 123 +}, &0, &0] + pelisteners: [&EventListener{ + x: 123 +}, &0, &0] + ppelisteners: [&&EventListener{ + x: 123 +}, &&0, &&0] + pppelisteners: [&&&EventListener{ + x: 123 +}, &&&0, &&&0] +} +----------------------------------------------------- +[EventListener{ + x: 0 +}, EventListener{ + x: 0 +}] +[&0, &0] +[&&0, &&0] +----------------------------------------------------- +[EventListener{ + x: 123 +}, EventListener{ + x: 0 +}] diff --git a/vlib/v/tests/inout/printing_fixed_array_of_pointers.vv b/vlib/v/tests/inout/printing_fixed_array_of_pointers.vv new file mode 100644 index 0000000000..d29ea2e687 --- /dev/null +++ b/vlib/v/tests/inout/printing_fixed_array_of_pointers.vv @@ -0,0 +1,47 @@ +struct EventListener { +mut: + x int +} + +type PEventListener = &EventListener + +struct StructOfFixedArraysOfListeners { +mut: + elisteners [3]EventListener + apelisteners [3]PEventListener + pelisteners [3]&EventListener + ppelisteners [3]&&EventListener + pppelisteners [3]&&&EventListener +} + +fn main() { + mut x := StructOfFixedArraysOfListeners{} + x.elisteners[0].x = 123 + x.apelisteners[0] = &x.elisteners[0] + x.pelisteners[0] = &x.elisteners[0] + // + x.ppelisteners[0] = &x.pelisteners[0] + x.pppelisteners[0] = &x.ppelisteners[0] + eprintln('------------------------------------') + eprintln(x.elisteners) + eprintln('- 1 level of indirection -') + eprintln(x.apelisteners) + eprintln(x.pelisteners) + eprintln('- 2 level of indirection -') + eprintln(x.ppelisteners) + eprintln('- 3 level of indirection -') + eprintln(x.pppelisteners) + eprintln('-----------------------------------------------------') + eprintln('- all:') + eprintln(x) + eprintln('-----------------------------------------------------') + fa := [2]EventListener{} + eprintln(fa) + pfa := [2]&EventListener{} + eprintln(pfa) + ppfa := [2]&&EventListener{} + eprintln(ppfa) + eprintln('-----------------------------------------------------') + dynamic_pfa := [&x.elisteners[0], &x.elisteners[1]] + eprintln(dynamic_pfa) +}