diff --git a/cmd/tools/vtest-fixed.v b/cmd/tools/vtest-fixed.v index aca809d767..cace4867d0 100644 --- a/cmd/tools/vtest-fixed.v +++ b/cmd/tools/vtest-fixed.v @@ -16,7 +16,6 @@ const ( 'vlib/v/tests/fixed_array_test.v', 'vlib/v/tests/num_lit_call_method_test.v', 'vlib/v/tests/pointers_test.v', - 'vlib/v/tests/string_interpolation_variadic_test.v', 'vlib/v/tests/type_test.v', 'vlib/v/tests/interface_test.v', 'vlib/v/tests/valgrind/valgrind_test.v', // ubuntu-musl only diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c3be41f517..eb50373ee3 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2369,16 +2369,24 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.expr(expr) } else { sym := g.table.get_type_symbol(node.expr_types[i]) - if sym.kind == .enum_ { + if node.expr_types[i].flag_is(.variadic) { + str_fn_name := g.gen_str_for_type(node.expr_types[i]) + g.write('${str_fn_name}(') + g.expr(expr) + g.write(')') + g.write('.len, ') + g.write('${str_fn_name}(') + g.expr(expr) + g.write(').str') + } + else if sym.kind == .enum_ { is_var := match node.exprs[i] { ast.SelectorExpr { true } ast.Ident { true } else { false } } if is_var { - styp := g.typ(node.expr_types[i]) - str_fn_name := styp_to_str_fn_name(styp) - g.gen_str_for_type(sym, styp, str_fn_name) + str_fn_name := g.gen_str_for_type(node.expr_types[i]) g.write('${str_fn_name}(') g.enum_expr(expr) g.write(')') @@ -2396,9 +2404,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('"') } } else if sym.kind in [.array, .array_fixed] { - styp := g.typ(node.expr_types[i]) - str_fn_name := styp_to_str_fn_name(styp) - g.gen_str_for_type(sym, styp, str_fn_name) + str_fn_name := g.gen_str_for_type(node.expr_types[i]) g.write('${str_fn_name}(') g.expr(expr) g.write(')') @@ -2407,9 +2413,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.expr(expr) g.write(').str') } else if sym.kind == .map && !sym.has_method('str') { - styp := g.typ(node.expr_types[i]) - str_fn_name := styp_to_str_fn_name(styp) - g.gen_str_for_type(sym, styp, str_fn_name) + str_fn_name := g.gen_str_for_type(node.expr_types[i]) g.write('${str_fn_name}(') g.expr(expr) g.write(')') @@ -2418,9 +2422,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.expr(expr) g.write(').str') } else if sym.kind == .struct_ && !sym.has_method('str') { - styp := g.typ(node.expr_types[i]) - str_fn_name := styp_to_str_fn_name(styp) - g.gen_str_for_type(sym, styp, str_fn_name) + str_fn_name := g.gen_str_for_type(node.expr_types[i]) g.write('${str_fn_name}(') g.expr(expr) g.write(',0)') @@ -2961,27 +2963,45 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) { g.expr(node.right) } +[inline] fn styp_to_str_fn_name(styp string) string { - res := styp.replace('.', '__').replace('*', '_ptr') + '_str' - return res + return styp.replace('*', '_ptr') + '_str' +} + +[inline] +fn (mut g Gen) gen_str_for_type(typ table.Type) string { + styp := g.typ(typ) + return g.gen_str_for_type_with_styp(typ, styp) } // already generated styp, reuse it -fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp, str_fn_name string) { +fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string { + sym := g.table.get_type_symbol(typ) + str_fn_name := styp_to_str_fn_name(styp) already_generated_key := '${styp}:${str_fn_name}' - if sym.has_method('str') || already_generated_key in g.str_types { - return + // generate for type + if !sym.has_method('str') && !(already_generated_key in g.str_types) { + g.str_types << already_generated_key + match sym.info { + table.Alias { g.gen_str_default(sym, styp, str_fn_name) } + table.Array { g.gen_str_for_array(it, styp, str_fn_name) } + table.ArrayFixed { g.gen_str_for_array_fixed(it, styp, str_fn_name) } + table.Enum { g.gen_str_for_enum(it, styp, str_fn_name) } + table.Struct { g.gen_str_for_struct(it, styp, str_fn_name) } + table.Map { g.gen_str_for_map(it, styp, str_fn_name) } + else { verror("could not generate string method $str_fn_name for type \'${styp}\'") } + } } - g.str_types << already_generated_key - match sym.info { - table.Alias { g.gen_str_default(sym, styp, str_fn_name) } - table.Array { g.gen_str_for_array(it, styp, str_fn_name) } - table.ArrayFixed { g.gen_str_for_array_fixed(it, styp, str_fn_name) } - table.Enum { g.gen_str_for_enum(it, styp, str_fn_name) } - table.Struct { g.gen_str_for_struct(it, styp, str_fn_name) } - table.Map { g.gen_str_for_map(it, styp, str_fn_name) } - else { verror("could not generate string method $str_fn_name for type \'${styp}\'") } + // if varg, generate str for varg + if typ.flag_is(.variadic) { + varg_already_generated_key := 'varg_$already_generated_key' + if !(varg_already_generated_key in g.str_types) { + g.gen_str_for_varg(styp, str_fn_name) + g.str_types << varg_already_generated_key + } + return 'varg_$str_fn_name' } + return str_fn_name } fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp, str_fn_name string) { @@ -3038,9 +3058,8 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) { sym := g.table.get_type_symbol(field.typ) if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] { field_styp := g.typ(field.typ) - field_fn_name := styp_to_str_fn_name(field_styp) + field_fn_name := g.gen_str_for_type_with_styp(field.typ, field_styp) fnames2strfunc[field_styp] = field_fn_name - g.gen_str_for_type(sym, field_styp, field_fn_name) } } g.definitions.writeln('string ${str_fn_name}($styp x, int indent_count); // auto') @@ -3103,7 +3122,7 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp, str_fn_name string) { sym := g.table.get_type_symbol(info.elem_type) field_styp := g.typ(info.elem_type) if sym.kind == .struct_ && !sym.has_method('str') { - g.gen_str_for_type(sym, field_styp, styp_to_str_fn_name(field_styp)) + g.gen_str_for_type_with_styp(info.elem_type, field_styp) } g.definitions.writeln('string ${str_fn_name}($styp a); // auto') g.auto_str_funcs.writeln('string ${str_fn_name}($styp a) {') @@ -3131,7 +3150,7 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp, str_fn_name sym := g.table.get_type_symbol(info.elem_type) field_styp := g.typ(info.elem_type) if sym.kind == .struct_ && !sym.has_method('str') { - g.gen_str_for_type(sym, field_styp, styp_to_str_fn_name(field_styp)) + g.gen_str_for_type_with_styp(info.elem_type, field_styp) } g.definitions.writeln('string ${str_fn_name}($styp a); // auto') g.auto_str_funcs.writeln('string ${str_fn_name}($styp a) {') @@ -3160,12 +3179,12 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp, str_fn_name string) { key_sym := g.table.get_type_symbol(info.key_type) key_styp := g.typ(info.key_type) if key_sym.kind == .struct_ && !key_sym.has_method('str') { - g.gen_str_for_type(key_sym, key_styp, styp_to_str_fn_name(key_styp)) + g.gen_str_for_type_with_styp(info.key_type, key_styp) } val_sym := g.table.get_type_symbol(info.value_type) val_styp := g.typ(info.value_type) if val_sym.kind == .struct_ && !val_sym.has_method('str') { - g.gen_str_for_type(val_sym, val_styp, styp_to_str_fn_name(val_styp)) + g.gen_str_for_type_with_styp(info.value_type, val_styp) } zero := g.type_default(info.value_type) g.definitions.writeln('string ${str_fn_name}($styp m); // auto') @@ -3198,6 +3217,22 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp, str_fn_name string) { g.auto_str_funcs.writeln('}') } +fn (mut g Gen) gen_str_for_varg(styp, str_fn_name string) { + g.definitions.writeln('string varg_${str_fn_name}(varg_$styp it); // auto') + g.auto_str_funcs.writeln('string varg_${str_fn_name}(varg_$styp it) {') + g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(it.len);') + g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos3("["));') + g.auto_str_funcs.writeln('\tfor(int i=0; i