cgen: simplify .str() generation (#7038)
parent
54e03f60b9
commit
5b6eb7b2c9
|
@ -327,7 +327,8 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
|
||||||
}
|
}
|
||||||
if ftyp in [table.string_type, table.bool_type] ||
|
if ftyp in [table.string_type, table.bool_type] ||
|
||||||
sym.kind in
|
sym.kind in
|
||||||
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type] || sym.has_method('str') {
|
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_] || ftyp.has_flag(.optional) ||
|
||||||
|
sym.has_method('str') {
|
||||||
return `s`
|
return `s`
|
||||||
} else {
|
} else {
|
||||||
return `_`
|
return `_`
|
||||||
|
|
|
@ -6,45 +6,21 @@ import v.table
|
||||||
import v.pref
|
import v.pref
|
||||||
import v.util
|
import v.util
|
||||||
|
|
||||||
// already generated styp, reuse it
|
fn (mut g Gen) gen_str_for_type(typ table.Type) string {
|
||||||
fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
styp := g.typ(typ).replace('*', '')
|
||||||
mut sym := g.table.get_type_symbol(g.unwrap_generic(typ))
|
mut sym := g.table.get_type_symbol(g.unwrap_generic(typ))
|
||||||
mut str_fn_name := styp_to_str_fn_name(styp)
|
mut str_fn_name := styp_to_str_fn_name(styp)
|
||||||
if mut sym.info is table.Alias {
|
if mut sym.info is table.Alias {
|
||||||
if sym.info.is_import {
|
if sym.info.is_import {
|
||||||
sym = g.table.get_type_symbol(sym.info.parent_type)
|
sym = g.table.get_type_symbol(sym.info.parent_type)
|
||||||
str_fn_name = styp_to_str_fn_name(sym.name.replace('.', '__'))
|
str_fn_name = styp_to_str_fn_name(sym.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym_has_str_method, str_method_expects_ptr, str_nr_args := sym.str_method_info()
|
sym_has_str_method, str_method_expects_ptr, str_nr_args := sym.str_method_info()
|
||||||
// generate for type
|
|
||||||
if sym_has_str_method && str_method_expects_ptr && str_nr_args == 1 {
|
|
||||||
// TODO: optimize out this.
|
|
||||||
// It is needed, so that println() can be called with &T and T has `fn (t &T).str() string`
|
|
||||||
/*
|
|
||||||
eprintln('>> gsftws: typ: $typ | typ_is_ptr $typ_is_ptr | styp: $styp ' +
|
|
||||||
'| $str_fn_name | sym.name: $sym.name has_str: $sym_has_str_method ' +
|
|
||||||
'| expects_ptr: $str_method_expects_ptr')
|
|
||||||
*/
|
|
||||||
str_fn_name_no_ptr := '${str_fn_name}_no_ptr'
|
|
||||||
already_generated_key_no_ptr := '$styp:$str_fn_name_no_ptr'
|
|
||||||
if already_generated_key_no_ptr !in g.str_types {
|
|
||||||
g.str_types << already_generated_key_no_ptr
|
|
||||||
g.type_definitions.writeln('static string ${str_fn_name_no_ptr}($styp it); // auto no_ptr version')
|
|
||||||
g.auto_str_funcs.writeln('static string ${str_fn_name_no_ptr}($styp it){ return ${str_fn_name}(&it); }')
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
typ_is_ptr := typ.is_ptr()
|
|
||||||
ret_type := if typ_is_ptr { str_fn_name } else { str_fn_name_no_ptr }
|
|
||||||
eprintln(' ret_type: $ret_type')
|
|
||||||
return ret_type
|
|
||||||
*/
|
|
||||||
return str_fn_name_no_ptr
|
|
||||||
}
|
|
||||||
already_generated_key := '$styp:$str_fn_name'
|
already_generated_key := '$styp:$str_fn_name'
|
||||||
if !sym_has_str_method && already_generated_key !in g.str_types && !typ.has_flag(.optional) {
|
if !sym_has_str_method && already_generated_key !in g.str_types && !typ.has_flag(.optional) {
|
||||||
$if debugautostr ? {
|
$if debugautostr ? {
|
||||||
eprintln('> gen_str_for_type_with_styp: |typ: ${typ:5}, ${sym.name:20}|has_str: ${sym_has_str_method:5}|expects_ptr: ${str_method_expects_ptr:5}|nr_args: ${str_nr_args:1}|fn_name: ${str_fn_name:20}')
|
eprintln('> gen_str_for_type: |typ: ${typ:5}, ${sym.name:20}|has_str: ${sym_has_str_method:5}|expects_ptr: ${str_method_expects_ptr:5}|nr_args: ${str_nr_args:1}|fn_name: ${str_fn_name:20}')
|
||||||
}
|
}
|
||||||
g.str_types << already_generated_key
|
g.str_types << already_generated_key
|
||||||
match mut sym.info {
|
match mut sym.info {
|
||||||
|
@ -108,8 +84,7 @@ fn (mut g Gen) gen_str_for_option(typ table.Type, styp string, str_fn_name strin
|
||||||
sym_name := sym.name.replace('.', '__')
|
sym_name := sym.name.replace('.', '__')
|
||||||
mut parent_str_fn_name := styp_to_str_fn_name(sym_name)
|
mut parent_str_fn_name := styp_to_str_fn_name(sym_name)
|
||||||
if !sym_has_str_method {
|
if !sym_has_str_method {
|
||||||
parent_styp := g.typ(parent_type)
|
parent_str_fn_name = g.gen_str_for_type(parent_type)
|
||||||
parent_str_fn_name = g.gen_str_for_type_with_styp(parent_type, parent_styp)
|
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0); }')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0); }')
|
||||||
|
@ -138,8 +113,7 @@ fn (mut g Gen) gen_str_for_alias(info table.Alias, styp string, str_fn_name stri
|
||||||
sym_has_str_method, _, _ := sym.str_method_info()
|
sym_has_str_method, _, _ := sym.str_method_info()
|
||||||
mut parent_str_fn_name := styp_to_str_fn_name(sym.name.replace('.', '__'))
|
mut parent_str_fn_name := styp_to_str_fn_name(sym.name.replace('.', '__'))
|
||||||
if !sym_has_str_method {
|
if !sym_has_str_method {
|
||||||
parent_styp := g.typ(info.parent_type)
|
parent_str_fn_name = g.gen_str_for_type(info.parent_type)
|
||||||
parent_str_fn_name = g.gen_str_for_type_with_styp(info.parent_type, parent_styp)
|
|
||||||
}
|
}
|
||||||
mut clean_type_v_type_name := util.strip_main_name(styp.replace('__', '.'))
|
mut clean_type_v_type_name := util.strip_main_name(styp.replace('__', '.'))
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto')
|
||||||
|
@ -175,7 +149,7 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
||||||
elem_str_fn_name = styp_to_str_fn_name(field_styp)
|
elem_str_fn_name = styp_to_str_fn_name(field_styp)
|
||||||
}
|
}
|
||||||
if !sym_has_str_method {
|
if !sym_has_str_method {
|
||||||
g.gen_str_for_type_with_styp(typ, field_styp)
|
g.gen_str_for_type(typ)
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
||||||
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}')
|
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}')
|
||||||
|
@ -240,7 +214,7 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f
|
||||||
elem_str_fn_name = styp_to_str_fn_name(field_styp)
|
elem_str_fn_name = styp_to_str_fn_name(field_styp)
|
||||||
}
|
}
|
||||||
if !sym.has_method('str') {
|
if !sym.has_method('str') {
|
||||||
elem_str_fn_name = g.gen_str_for_type_with_styp(typ, field_styp)
|
elem_str_fn_name = g.gen_str_for_type(typ)
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
||||||
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}')
|
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}')
|
||||||
|
@ -275,15 +249,14 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) {
|
||||||
key_sym := g.table.get_type_symbol(info.key_type)
|
key_sym := g.table.get_type_symbol(info.key_type)
|
||||||
key_styp := g.typ(info.key_type)
|
|
||||||
if !key_sym.has_method('str') {
|
if !key_sym.has_method('str') {
|
||||||
g.gen_str_for_type_with_styp(info.key_type, key_styp)
|
g.gen_str_for_type(info.key_type)
|
||||||
}
|
}
|
||||||
val_sym := g.table.get_type_symbol(info.value_type)
|
val_sym := g.table.get_type_symbol(info.value_type)
|
||||||
val_styp := g.typ(info.value_type)
|
val_styp := g.typ(info.value_type)
|
||||||
elem_str_fn_name := val_styp.replace('*', '') + '_str'
|
elem_str_fn_name := val_styp.replace('*', '') + '_str'
|
||||||
if !val_sym.has_method('str') {
|
if !val_sym.has_method('str') {
|
||||||
g.gen_str_for_type_with_styp(info.value_type, val_styp)
|
g.gen_str_for_type(info.value_type)
|
||||||
}
|
}
|
||||||
zero := g.type_default(info.value_type)
|
zero := g.type_default(info.value_type)
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp m); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp m); // auto')
|
||||||
|
@ -339,8 +312,7 @@ fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str
|
||||||
for typ in info.types {
|
for typ in info.types {
|
||||||
sym := g.table.get_type_symbol(typ)
|
sym := g.table.get_type_symbol(typ)
|
||||||
if !sym.has_method('str') {
|
if !sym.has_method('str') {
|
||||||
field_styp := g.typ(typ)
|
g.gen_str_for_type(typ)
|
||||||
g.gen_str_for_type_with_styp(typ, field_styp)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto')
|
||||||
|
@ -397,15 +369,15 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
typ = typ.deref()
|
typ = typ.deref()
|
||||||
}
|
}
|
||||||
field_styp := g.typ(typ)
|
field_styp := g.typ(typ)
|
||||||
field_fn_name := g.gen_str_for_type_with_styp(field.typ, field_styp)
|
field_fn_name := g.gen_str_for_type(field.typ)
|
||||||
fnames2strfunc[field_styp] = field_fn_name
|
fnames2strfunc[field_styp] = field_fn_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// _str() functions should have a single argument, the indenting ones take 2:
|
// _str() functions should have a single argument, the indenting ones take 2:
|
||||||
g.type_definitions.writeln('static string ${str_fn_name}($styp x); // auto')
|
g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto')
|
||||||
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0);}')
|
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0);}')
|
||||||
g.type_definitions.writeln('static string indent_${str_fn_name}($styp x, int indent_count); // auto')
|
g.type_definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto')
|
||||||
g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp x, int indent_count) {')
|
g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp it, int indent_count) {')
|
||||||
mut clean_struct_v_type_name := styp.replace('__', '.')
|
mut clean_struct_v_type_name := styp.replace('__', '.')
|
||||||
if clean_struct_v_type_name.contains('_T_') {
|
if clean_struct_v_type_name.contains('_T_') {
|
||||||
// TODO: this is a bit hacky. styp shouldn't be even parsed with _T_
|
// TODO: this is a bit hacky. styp shouldn't be even parsed with _T_
|
||||||
|
@ -413,14 +385,6 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
clean_struct_v_type_name = clean_struct_v_type_name.replace('_T_', '<').replace('_', ', ') +
|
clean_struct_v_type_name = clean_struct_v_type_name.replace('_T_', '<').replace('_', ', ') +
|
||||||
'>'
|
'>'
|
||||||
}
|
}
|
||||||
if styp.ends_with('*') {
|
|
||||||
deref_typ := styp.replace('*', '')
|
|
||||||
g.auto_str_funcs.writeln('\t$deref_typ *it = x;')
|
|
||||||
clean_struct_v_type_name = '&' + clean_struct_v_type_name.replace('*', '')
|
|
||||||
} else {
|
|
||||||
deref_typ := styp
|
|
||||||
g.auto_str_funcs.writeln('\t$deref_typ *it = &x;')
|
|
||||||
}
|
|
||||||
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
|
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
|
||||||
// generate ident / indent length = 4 spaces
|
// generate ident / indent length = 4 spaces
|
||||||
g.auto_str_funcs.writeln('\tstring indents = tos_lit("");')
|
g.auto_str_funcs.writeln('\tstring indents = tos_lit("");')
|
||||||
|
@ -428,14 +392,12 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
g.auto_str_funcs.writeln('\t\tindents = string_add(indents, tos_lit(" "));')
|
g.auto_str_funcs.writeln('\t\tindents = string_add(indents, tos_lit(" "));')
|
||||||
g.auto_str_funcs.writeln('\t}')
|
g.auto_str_funcs.writeln('\t}')
|
||||||
if info.fields.len == 0 {
|
if info.fields.len == 0 {
|
||||||
g.auto_str_funcs.write('\treturn tos_lit("$clean_struct_v_type_name{}");')
|
g.auto_str_funcs.write('\treturn _SLIT("$clean_struct_v_type_name{}");')
|
||||||
} else {
|
} else {
|
||||||
g.auto_str_funcs.write('\treturn _STR("$clean_struct_v_type_name{\\n"')
|
g.auto_str_funcs.write('\treturn _STR("$clean_struct_v_type_name{\\n"')
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
mut fmt := g.type_to_fmt(field.typ)
|
mut fmt := if field.typ.is_ptr() { '&' } else { '' }
|
||||||
if field.typ.is_ptr() {
|
fmt += g.type_to_fmt(field.typ)
|
||||||
fmt = '&$fmt'
|
|
||||||
}
|
|
||||||
g.auto_str_funcs.writeln('\t\t"%.*s\\000 $field.name: $fmt\\n"')
|
g.auto_str_funcs.writeln('\t\t"%.*s\\000 $field.name: $fmt\\n"')
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.write('\t\t"%.*s\\000}", ${2 * (info.fields.len + 1)}')
|
g.auto_str_funcs.write('\t\t"%.*s\\000}", ${2 * (info.fields.len + 1)}')
|
||||||
|
@ -444,16 +406,14 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
for i, field in info.fields {
|
for i, field in info.fields {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
has_custom_str := sym.has_method('str')
|
has_custom_str := sym.has_method('str')
|
||||||
mut field_styp := g.typ(field.typ)
|
mut field_styp := g.typ(field.typ).replace('*', '')
|
||||||
if field_styp.ends_with('*') {
|
|
||||||
field_styp = field_styp.replace('*', '')
|
|
||||||
}
|
|
||||||
field_styp_fn_name := if has_custom_str { '${field_styp}_str' } else { fnames2strfunc[field_styp] }
|
field_styp_fn_name := if has_custom_str { '${field_styp}_str' } else { fnames2strfunc[field_styp] }
|
||||||
g.auto_str_funcs.write('indents, ')
|
g.auto_str_funcs.write('indents, ')
|
||||||
func := struct_auto_str_func(sym, field.typ, field_styp_fn_name, field.name)
|
func := struct_auto_str_func(sym, field.typ, field_styp_fn_name, field.name)
|
||||||
|
// reference types can be "nil"
|
||||||
if field.typ.is_ptr() {
|
if field.typ.is_ptr() {
|
||||||
g.auto_str_funcs.write('isnil(it->${c_name(field.name)})')
|
g.auto_str_funcs.write('isnil(it.${c_name(field.name)})')
|
||||||
g.auto_str_funcs.write(' ? tos_lit("nil") : ')
|
g.auto_str_funcs.write(' ? _SLIT("nil") : ')
|
||||||
// struct, floats and ints have a special case through the _str function
|
// struct, floats and ints have a special case through the _str function
|
||||||
if sym.kind != .struct_ && !field.typ.is_int() && !field.typ.is_float() {
|
if sym.kind != .struct_ && !field.typ.is_int() && !field.typ.is_float() {
|
||||||
g.auto_str_funcs.write('*')
|
g.auto_str_funcs.write('*')
|
||||||
|
@ -474,9 +434,9 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name string, field_name string) string {
|
fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name string, field_name string) string {
|
||||||
has_custom_str := sym.has_method('str')
|
has_custom_str := sym.has_method('str')
|
||||||
if sym.kind == .enum_ {
|
if sym.kind == .enum_ {
|
||||||
return '${fn_name}(it->${c_name(field_name)})'
|
return '${fn_name}(it.${c_name(field_name)})'
|
||||||
} else if sym.kind == .struct_ {
|
} else if sym.kind == .struct_ {
|
||||||
mut obj := 'it->${c_name(field_name)}'
|
mut obj := 'it.${c_name(field_name)}'
|
||||||
if field_type.is_ptr() {
|
if field_type.is_ptr() {
|
||||||
obj = '*$obj'
|
obj = '*$obj'
|
||||||
}
|
}
|
||||||
|
@ -486,11 +446,11 @@ fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name str
|
||||||
return 'indent_${fn_name}($obj, indent_count + 1)'
|
return 'indent_${fn_name}($obj, indent_count + 1)'
|
||||||
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
|
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
|
||||||
if has_custom_str {
|
if has_custom_str {
|
||||||
return '${fn_name}(it->${c_name(field_name)})'
|
return '${fn_name}(it.${c_name(field_name)})'
|
||||||
}
|
}
|
||||||
return 'indent_${fn_name}(it->${c_name(field_name)}, indent_count + 1)'
|
return 'indent_${fn_name}(it.${c_name(field_name)}, indent_count + 1)'
|
||||||
} else {
|
} else {
|
||||||
mut method_str := 'it->${c_name(field_name)}'
|
mut method_str := 'it.${c_name(field_name)}'
|
||||||
if sym.kind == .bool {
|
if sym.kind == .bool {
|
||||||
method_str += ' ? _SLIT("true") : _SLIT("false")'
|
method_str += ' ? _SLIT("true") : _SLIT("false")'
|
||||||
} else if (field_type.is_int() || field_type.is_float()) && field_type.is_ptr() {
|
} else if (field_type.is_int() || field_type.is_float()) && field_type.is_ptr() {
|
||||||
|
@ -534,7 +494,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
|
||||||
sym := g.table.get_type_symbol(typ)
|
sym := g.table.get_type_symbol(typ)
|
||||||
if !sym.has_method('str') {
|
if !sym.has_method('str') {
|
||||||
field_styp := g.typ(typ)
|
field_styp := g.typ(typ)
|
||||||
field_fn_name := g.gen_str_for_type_with_styp(typ, field_styp)
|
field_fn_name := g.gen_str_for_type(typ)
|
||||||
gen_fn_names[field_styp] = field_fn_name
|
gen_fn_names[field_styp] = field_fn_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,8 +515,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
|
||||||
value_fmt = "'$value_fmt'"
|
value_fmt = "'$value_fmt'"
|
||||||
}
|
}
|
||||||
typ_str := g.typ(typ)
|
typ_str := g.typ(typ)
|
||||||
mut func_name := if typ_str in gen_fn_names { gen_fn_names[typ_str] } else { g.gen_str_for_type_with_styp(typ,
|
mut func_name := if typ_str in gen_fn_names { gen_fn_names[typ_str] } else { g.gen_str_for_type(typ) }
|
||||||
typ_str) }
|
|
||||||
sym := g.table.get_type_symbol(typ)
|
sym := g.table.get_type_symbol(typ)
|
||||||
if sym.kind == .struct_ {
|
if sym.kind == .struct_ {
|
||||||
func_name = 'indent_$func_name'
|
func_name = 'indent_$func_name'
|
||||||
|
@ -571,3 +530,8 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
|
||||||
g.auto_str_funcs.writeln('\t}')
|
g.auto_str_funcs.writeln('\t}')
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn styp_to_str_fn_name(styp string) string {
|
||||||
|
return styp.replace_each(['*', '', '.', '__']) + '_str'
|
||||||
|
}
|
||||||
|
|
|
@ -1453,9 +1453,7 @@ fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) {
|
||||||
// without special casing ast.CastExpr here
|
// without special casing ast.CastExpr here
|
||||||
g.write(ctoslit(unknown_value))
|
g.write(ctoslit(unknown_value))
|
||||||
} else {
|
} else {
|
||||||
g.gen_expr_to_string(e, t) or {
|
g.gen_expr_to_string(e, t)
|
||||||
g.write(ctoslit('[$err]'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Type {
|
ast.Type {
|
||||||
|
@ -1463,9 +1461,7 @@ fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) {
|
||||||
g.write(ctoslit('$sym.name'))
|
g.write(ctoslit('$sym.name'))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.gen_expr_to_string(e, t) or {
|
g.gen_expr_to_string(e, t)
|
||||||
g.write(ctoslit('[$err]'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write(' /* typeof: ' + typeof(e) + ' type: ' + t.str() + ' */ ')
|
g.write(' /* typeof: ' + typeof(e) + ' type: ' + t.str() + ' */ ')
|
||||||
|
@ -4664,90 +4660,6 @@ fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
||||||
return types_sorted
|
return types_sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
|
|
||||||
mut typ := etype
|
|
||||||
mut sym := g.table.get_type_symbol(typ)
|
|
||||||
if mut sym.info is table.Alias {
|
|
||||||
parent_sym := g.table.get_type_symbol(sym.info.parent_type)
|
|
||||||
if parent_sym.has_method('str') {
|
|
||||||
typ = sym.info.parent_type
|
|
||||||
sym = parent_sym
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
|
||||||
if typ.has_flag(.variadic) {
|
|
||||||
str_fn_name := g.gen_str_for_type(typ)
|
|
||||||
g.write('${str_fn_name}(')
|
|
||||||
g.expr(expr)
|
|
||||||
g.write(')')
|
|
||||||
} else if typ == table.string_type {
|
|
||||||
g.expr(expr)
|
|
||||||
} else if sym.kind == .enum_ {
|
|
||||||
is_var := match expr {
|
|
||||||
ast.SelectorExpr, ast.Ident { true }
|
|
||||||
else { false }
|
|
||||||
}
|
|
||||||
if is_var {
|
|
||||||
str_fn_name := g.gen_str_for_type(typ)
|
|
||||||
g.write('${str_fn_name}(')
|
|
||||||
g.enum_expr(expr)
|
|
||||||
g.write(')')
|
|
||||||
} else {
|
|
||||||
g.write('tos_lit("')
|
|
||||||
g.enum_expr(expr)
|
|
||||||
g.write('")')
|
|
||||||
}
|
|
||||||
} else if sym_has_str_method || sym.kind in
|
|
||||||
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type] {
|
|
||||||
is_p := typ.is_ptr()
|
|
||||||
val_type := if is_p { typ.deref() } else { typ }
|
|
||||||
str_fn_name := g.gen_str_for_type(val_type)
|
|
||||||
if is_p && str_method_expects_ptr {
|
|
||||||
g.write('string_add(_SLIT("&"), ${str_fn_name}((')
|
|
||||||
}
|
|
||||||
if is_p && !str_method_expects_ptr {
|
|
||||||
g.write('string_add(_SLIT("&"), ${str_fn_name}(*(')
|
|
||||||
}
|
|
||||||
if !is_p && !str_method_expects_ptr {
|
|
||||||
g.write('${str_fn_name}(')
|
|
||||||
}
|
|
||||||
if !is_p && str_method_expects_ptr {
|
|
||||||
g.write('${str_fn_name}(&')
|
|
||||||
}
|
|
||||||
if expr is ast.ArrayInit {
|
|
||||||
if expr.is_fixed {
|
|
||||||
s := g.typ(expr.typ)
|
|
||||||
g.write('($s)')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if expr is ast.CTempVar {
|
|
||||||
if expr.is_ptr {
|
|
||||||
g.write('*')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.expr(expr)
|
|
||||||
if sym.kind == .struct_ && !sym_has_str_method {
|
|
||||||
if is_p {
|
|
||||||
g.write(')))')
|
|
||||||
} else {
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if is_p {
|
|
||||||
g.write(')))')
|
|
||||||
} else {
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
str_fn_name := g.gen_str_for_type(typ)
|
|
||||||
g.write('${str_fn_name}(')
|
|
||||||
g.expr(expr)
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// `nums.map(it % 2 == 0)`
|
// `nums.map(it % 2 == 0)`
|
||||||
fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||||
g.inside_lambda = true
|
g.inside_lambda = true
|
||||||
|
@ -5555,21 +5467,6 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn styp_to_str_fn_name(styp string) string {
|
|
||||||
return styp.replace('*', '_ptr') + '_str'
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn (mut g Gen) gen_str_for_type(typ table.Type) string {
|
|
||||||
// note: why was this here, removed for --usecache fix
|
|
||||||
// if g.pref.build_mode == .build_module {
|
|
||||||
// return ''
|
|
||||||
// }
|
|
||||||
styp := g.typ(typ)
|
|
||||||
return g.gen_str_for_type_with_styp(typ, styp)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name string) {
|
||||||
mut convertor := ''
|
mut convertor := ''
|
||||||
mut typename_ := ''
|
mut typename_ := ''
|
||||||
|
|
|
@ -363,11 +363,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if node.name == 'str' {
|
if node.name == 'str' {
|
||||||
mut styp := g.typ(node.receiver_type)
|
g.gen_str_for_type(node.receiver_type)
|
||||||
if node.receiver_type.is_ptr() {
|
|
||||||
styp = styp.replace('*', '')
|
|
||||||
}
|
|
||||||
g.gen_str_for_type_with_styp(node.receiver_type, styp)
|
|
||||||
}
|
}
|
||||||
// TODO performance, detect `array` method differently
|
// TODO performance, detect `array` method differently
|
||||||
if left_sym.kind == .array && node.name in
|
if left_sym.kind == .array && node.name in
|
||||||
|
@ -549,55 +545,18 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
// check if alias parent also not a string
|
// check if alias parent also not a string
|
||||||
if typ != table.string_type {
|
if typ != table.string_type {
|
||||||
mut styp := g.typ(typ)
|
expr := node.args[0].expr
|
||||||
if typ.is_ptr() {
|
|
||||||
styp = styp.replace('*', '')
|
|
||||||
}
|
|
||||||
mut str_fn_name := g.gen_str_for_type_with_styp(typ, styp)
|
|
||||||
if g.autofree && !typ.has_flag(.optional) {
|
if g.autofree && !typ.has_flag(.optional) {
|
||||||
// Create a temporary variable so that the value can be freed
|
// Create a temporary variable so that the value can be freed
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
// tmps << tmp
|
// tmps << tmp
|
||||||
g.write('string $tmp = ${str_fn_name}(')
|
g.write('string $tmp = ')
|
||||||
g.expr(node.args[0].expr)
|
g.gen_expr_to_string(expr, typ)
|
||||||
g.writeln('); ${print_method}($tmp); string_free(&$tmp); //MEM2 $styp')
|
g.writeln('; ${print_method}($tmp); string_free(&$tmp);')
|
||||||
} else {
|
} else {
|
||||||
expr := node.args[0].expr
|
g.write('${print_method}(')
|
||||||
is_var := match expr {
|
g.gen_expr_to_string(expr, typ)
|
||||||
ast.SelectorExpr { true }
|
g.write(')')
|
||||||
ast.Ident { true }
|
|
||||||
else { false }
|
|
||||||
}
|
|
||||||
if typ.is_ptr() && sym.kind != .struct_ {
|
|
||||||
// ptr_str() for pointers
|
|
||||||
styp = 'ptr'
|
|
||||||
str_fn_name = 'ptr_str'
|
|
||||||
}
|
|
||||||
if sym.kind == .enum_ {
|
|
||||||
if is_var {
|
|
||||||
g.write('${print_method}(${str_fn_name}(')
|
|
||||||
} else {
|
|
||||||
// when no var, print string directly
|
|
||||||
g.write('${print_method}(tos3("')
|
|
||||||
}
|
|
||||||
if typ.is_ptr() {
|
|
||||||
// dereference
|
|
||||||
g.write('*')
|
|
||||||
}
|
|
||||||
g.enum_expr(expr)
|
|
||||||
if !is_var {
|
|
||||||
// end of string
|
|
||||||
g.write('"')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.write('${print_method}(${str_fn_name}(')
|
|
||||||
if typ.is_ptr() && sym.kind == .struct_ {
|
|
||||||
// dereference
|
|
||||||
g.write('*')
|
|
||||||
}
|
|
||||||
g.expr(expr)
|
|
||||||
}
|
|
||||||
g.write('))')
|
|
||||||
}
|
}
|
||||||
print_auto_str = true
|
print_auto_str = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,6 @@ fn (mut g Gen) encode_map(key_type table.Type, value_type table.Type) string {
|
||||||
if key_type.is_string() {
|
if key_type.is_string() {
|
||||||
key += '(($styp*)${keys_tmp}.data)[i];'
|
key += '(($styp*)${keys_tmp}.data)[i];'
|
||||||
} else {
|
} else {
|
||||||
// g.gen_str_for_type(key_type)
|
|
||||||
// key += '${styp}_str((($styp*)${keys_tmp}.data)[i]);'
|
// key += '${styp}_str((($styp*)${keys_tmp}.data)[i]);'
|
||||||
verror('json: encode only maps with string keys')
|
verror('json: encode only maps with string keys')
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
g.write(escaped_val)
|
g.write(escaped_val)
|
||||||
|
typ := g.unwrap_generic(node.expr_types[i])
|
||||||
// write correct format specifier to intermediate string
|
// write correct format specifier to intermediate string
|
||||||
g.write('%')
|
g.write('%')
|
||||||
fspec := node.fmts[i]
|
fspec := node.fmts[i]
|
||||||
|
@ -214,7 +215,6 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
if node.precisions[i] != 987698 {
|
if node.precisions[i] != 987698 {
|
||||||
fmt = '${fmt}.${node.precisions[i]}'
|
fmt = '${fmt}.${node.precisions[i]}'
|
||||||
}
|
}
|
||||||
typ := g.unwrap_generic(node.expr_types[i])
|
|
||||||
if fspec == `s` {
|
if fspec == `s` {
|
||||||
if node.fwidths[i] == 0 {
|
if node.fwidths[i] == 0 {
|
||||||
g.write('.*s')
|
g.write('.*s')
|
||||||
|
@ -268,12 +268,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
} else {
|
} else {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else if typ.has_flag(.variadic) {
|
} else if node.fmts[i] == `s` || typ.has_flag(.variadic) {
|
||||||
g.gen_expr_to_string(expr, typ)
|
|
||||||
} else if typ == table.bool_type {
|
|
||||||
g.expr(expr)
|
|
||||||
g.write(' ? _SLIT("true") : _SLIT("false")')
|
|
||||||
} else if node.fmts[i] == `s` {
|
|
||||||
g.gen_expr_to_string(expr, typ)
|
g.gen_expr_to_string(expr, typ)
|
||||||
} else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` {
|
} else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` {
|
||||||
if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] {
|
if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] {
|
||||||
|
@ -304,3 +299,74 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
||||||
|
mut typ := etype
|
||||||
|
mut sym := g.table.get_type_symbol(typ)
|
||||||
|
// when type is alias, print the aliased value
|
||||||
|
if mut sym.info is table.Alias {
|
||||||
|
parent_sym := g.table.get_type_symbol(sym.info.parent_type)
|
||||||
|
if parent_sym.has_method('str') {
|
||||||
|
typ = sym.info.parent_type
|
||||||
|
sym = parent_sym
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||||
|
if typ.has_flag(.variadic) {
|
||||||
|
str_fn_name := g.gen_str_for_type(typ)
|
||||||
|
g.write('${str_fn_name}(')
|
||||||
|
g.expr(expr)
|
||||||
|
g.write(')')
|
||||||
|
} else if typ == table.string_type {
|
||||||
|
g.expr(expr)
|
||||||
|
} else if typ == table.bool_type {
|
||||||
|
g.expr(expr)
|
||||||
|
g.write(' ? _SLIT("true") : _SLIT("false")')
|
||||||
|
} else if sym.kind == .none_ {
|
||||||
|
g.write('_SLIT("none")')
|
||||||
|
} else if sym.kind == .enum_ {
|
||||||
|
is_var := match expr {
|
||||||
|
ast.SelectorExpr, ast.Ident { true }
|
||||||
|
else { false }
|
||||||
|
}
|
||||||
|
if is_var {
|
||||||
|
str_fn_name := g.gen_str_for_type(typ)
|
||||||
|
g.write('${str_fn_name}(')
|
||||||
|
g.enum_expr(expr)
|
||||||
|
g.write(')')
|
||||||
|
} else {
|
||||||
|
g.write('_SLIT("')
|
||||||
|
g.enum_expr(expr)
|
||||||
|
g.write('")')
|
||||||
|
}
|
||||||
|
} else if sym_has_str_method || sym.kind in
|
||||||
|
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type] {
|
||||||
|
is_ptr := typ.is_ptr()
|
||||||
|
str_fn_name := g.gen_str_for_type(typ)
|
||||||
|
if is_ptr {
|
||||||
|
g.write('_STR("&%.*s\\000", 2, ')
|
||||||
|
}
|
||||||
|
g.write('${str_fn_name}(')
|
||||||
|
if str_method_expects_ptr && !is_ptr {
|
||||||
|
g.write('&')
|
||||||
|
} else if !str_method_expects_ptr && is_ptr {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
if expr is ast.ArrayInit {
|
||||||
|
if expr.is_fixed {
|
||||||
|
s := g.typ(expr.typ)
|
||||||
|
g.write('($s)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.expr(expr)
|
||||||
|
g.write(')')
|
||||||
|
if is_ptr {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str_fn_name := g.gen_str_for_type(typ)
|
||||||
|
g.write('${str_fn_name}(')
|
||||||
|
g.expr(expr)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ Aaa{
|
||||||
name: ''
|
name: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bbb{
|
&Bbb{
|
||||||
pass: false
|
pass: false
|
||||||
name: ''
|
name: ''
|
||||||
}
|
}
|
|
@ -205,7 +205,7 @@ pub mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fooo() {
|
fn fooo() {
|
||||||
a := AttrTest{1, 2, 3, 4, 5, 6}
|
_ := AttrTest{1, 2, 3, 4, 5, 6}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -275,7 +275,7 @@ struct Country {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_levels() {
|
fn test_levels() {
|
||||||
c := Country{
|
_ := Country{
|
||||||
name: 'UK'
|
name: 'UK'
|
||||||
capital: {
|
capital: {
|
||||||
name: 'London'
|
name: 'London'
|
||||||
|
|
Loading…
Reference in New Issue