gen: fix errors of string interpolation of fn values in struct/array/map (#7367)
parent
c4c0b5eb06
commit
b10f692c43
|
@ -160,25 +160,29 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
|||
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(a.len * 10);')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT("["));')
|
||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < a.len; ++i) {')
|
||||
g.auto_str_funcs.writeln('\t\t$field_styp it = (*($field_styp*)array_get(a, i));')
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
if is_elem_ptr {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(*it, indent_count);')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(it, indent_count);')
|
||||
}
|
||||
} else if sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = _STR("%g", 1, it);')
|
||||
if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
||||
} else {
|
||||
// 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);')
|
||||
g.auto_str_funcs.writeln('\t\t$field_styp it = (*($field_styp*)array_get(a, i));')
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
if is_elem_ptr {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(*it, indent_count);')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(it, indent_count);')
|
||||
}
|
||||
} else if sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = _STR("%g", 1, it);')
|
||||
} else {
|
||||
// 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);')
|
||||
}
|
||||
}
|
||||
}
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, x);')
|
||||
|
@ -224,20 +228,24 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f
|
|||
g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp a, int indent_count) {')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder($info.size * 10);')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT("["));')
|
||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < $info.size; ++i) {')
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${elem_str_fn_name}(a[i], indent_count));')
|
||||
} else if sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("%g", 1, a[i]));')
|
||||
} else if sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, a[i]));')
|
||||
if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
||||
} 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(&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(&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(&sb, ${elem_str_fn_name}(*a[i]));')
|
||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < $info.size; ++i) {')
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${elem_str_fn_name}(a[i], indent_count));')
|
||||
} else if sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("%g", 1, a[i]));')
|
||||
} else if sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, 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(&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(&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(&sb, ${elem_str_fn_name}(*a[i]));')
|
||||
}
|
||||
}
|
||||
}
|
||||
g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {')
|
||||
|
@ -271,15 +279,19 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string)
|
|||
g.auto_str_funcs.writeln('\t\tstring key = *(string*)DenseArray_key(&m.key_values, i);')
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, key));')
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _SLIT(": "));')
|
||||
g.auto_str_funcs.writeln('\t\t$val_styp it = *($val_styp*)DenseArray_value(&m.key_values, i);')
|
||||
if val_sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, it));')
|
||||
} else if val_sym.kind == .struct_ && !val_sym.has_method('str') {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, indent_${elem_str_fn_name}(it, indent_count));')
|
||||
} else if val_sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("%g", 1, it));')
|
||||
if val_sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${elem_str_fn_name}());')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${elem_str_fn_name}(it));')
|
||||
g.auto_str_funcs.writeln('\t\t$val_styp it = *($val_styp*)DenseArray_value(&m.key_values, i);')
|
||||
if val_sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, it));')
|
||||
} else if val_sym.kind == .struct_ && !val_sym.has_method('str') {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, indent_${elem_str_fn_name}(it, indent_count));')
|
||||
} else if val_sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("%g", 1, it));')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${elem_str_fn_name}(it));')
|
||||
}
|
||||
}
|
||||
g.auto_str_funcs.writeln('\t\tif (i != m.key_values.len-1) {')
|
||||
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write(&sb, _SLIT(", "));')
|
||||
|
@ -335,6 +347,8 @@ fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str
|
|||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _STR("%g", 1, a.arg$i));')
|
||||
} else if sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _STR("\'%.*s\\000\'", 2, a.arg$i));')
|
||||
} else if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, ${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(&sb, ${arg_str_fn_name}(a.arg$i));')
|
||||
|
@ -447,6 +461,8 @@ fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name str
|
|||
return '${fn_name}(it.${c_name(field_name)})'
|
||||
}
|
||||
return 'indent_${fn_name}(it.${c_name(field_name)}, indent_count + 1)'
|
||||
} else if sym.kind == .function {
|
||||
return '${fn_name}()'
|
||||
} else {
|
||||
mut method_str := 'it.${c_name(field_name)}'
|
||||
if sym.kind == .bool {
|
||||
|
|
|
@ -5659,7 +5659,8 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
|
|||
sym := g.table.get_type_symbol(typ)
|
||||
if typ.is_ptr() && (typ.is_int() || typ.is_float()) {
|
||||
return '%.*s\\000'
|
||||
} else if sym.kind in [.struct_, .array, .array_fixed, .map, .bool, .enum_, .sum_type] {
|
||||
} else if sym.kind in
|
||||
[.struct_, .array, .array_fixed, .map, .bool, .enum_, .sum_type, .function] {
|
||||
return '%.*s\\000'
|
||||
} else if sym.kind == .string {
|
||||
return "\'%.*s\\000\'"
|
||||
|
|
|
@ -177,7 +177,10 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
|
|||
typ := node.expr_types[i]
|
||||
g.write(g.typ(typ))
|
||||
g.write('_str(')
|
||||
g.expr(node.exprs[i])
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
if sym.kind != .function {
|
||||
g.expr(node.exprs[i])
|
||||
}
|
||||
g.writeln('));')
|
||||
}
|
||||
g.writeln('')
|
||||
|
@ -366,7 +369,9 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
|||
} else {
|
||||
str_fn_name := g.gen_str_for_type(typ)
|
||||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
if sym.kind != .function {
|
||||
g.expr(expr)
|
||||
}
|
||||
g.write(')')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,3 +10,30 @@ fn test_function_interpolation() {
|
|||
println(show)
|
||||
assert '$show' == 'fn (string) string'
|
||||
}
|
||||
|
||||
struct Info {
|
||||
aa fn()string
|
||||
bb int
|
||||
}
|
||||
|
||||
fn test_function_interpolation_in_struct() {
|
||||
a := Info{
|
||||
aa: fn()string {return 'aaa'}
|
||||
bb: 22
|
||||
}
|
||||
println(a)
|
||||
assert '$a'.contains(': fn () string')
|
||||
}
|
||||
|
||||
fn test_function_interpolation_in_array() {
|
||||
f := [fn()string{return 'aaa'}, fn()string{return 'bbb'}]
|
||||
println(f)
|
||||
assert '$f' == '[fn () string, fn () string]'
|
||||
}
|
||||
|
||||
fn test_function_interpolation_in_map() {
|
||||
m := {'aaa': fn()string{return 'aaa'}, 'bbb': fn()string{return 'bbb'}}
|
||||
println(m)
|
||||
assert '$m'.contains(': fn () string')
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue