cgen: implement sum type str gen (#6454)
parent
b0a2c28c19
commit
4f09ddccb4
|
@ -315,7 +315,7 @@ pub fn (c &Checker) get_default_fmt(ftyp, 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 [.enum_, .array, .array_fixed, .struct_, .map, .multi_return] || ftyp.has_flag(.optional) ||
|
sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type] || ftyp.has_flag(.optional) ||
|
||||||
sym.has_method('str') {
|
sym.has_method('str') {
|
||||||
return `s`
|
return `s`
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
||||||
table.Struct { g.gen_str_for_struct(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) }
|
table.Map { g.gen_str_for_map(it, styp, str_fn_name) }
|
||||||
table.MultiReturn { g.gen_str_for_multi_return(it, styp, str_fn_name) }
|
table.MultiReturn { g.gen_str_for_multi_return(it, styp, str_fn_name) }
|
||||||
table.SumType {}
|
table.SumType { g.gen_str_for_sum_type(it, styp, str_fn_name) }
|
||||||
else { verror("could not generate string method $str_fn_name for type \'$styp\'") }
|
else { verror("could not generate string method $str_fn_name for type \'$styp\'") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,8 +298,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
||||||
}
|
}
|
||||||
// _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('string ${str_fn_name}($styp x); // auto')
|
g.type_definitions.writeln('string ${str_fn_name}($styp x); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x,0);}')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0);}')
|
||||||
//
|
|
||||||
g.type_definitions.writeln('string indent_${str_fn_name}($styp x, int indent_count); // auto')
|
g.type_definitions.writeln('string indent_${str_fn_name}($styp x, int indent_count); // auto')
|
||||||
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp x, int indent_count) {')
|
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp x, int indent_count) {')
|
||||||
mut clean_struct_v_type_name := styp.replace('__', '.')
|
mut clean_struct_v_type_name := styp.replace('__', '.')
|
||||||
|
@ -346,6 +345,8 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
||||||
} else if sym.kind in [.array, .array_fixed, .map] {
|
} else if sym.kind in [.array, .array_fixed, .map] {
|
||||||
g.auto_str_funcs.write('indents, ')
|
g.auto_str_funcs.write('indents, ')
|
||||||
g.auto_str_funcs.write('${field_styp_fn_name}( it->${c_name(field.name)}) ')
|
g.auto_str_funcs.write('${field_styp_fn_name}( it->${c_name(field.name)}) ')
|
||||||
|
} else if sym.kind == .sum_type {
|
||||||
|
g.auto_str_funcs.write('indents, indent_${field_styp_fn_name}(it->${c_name(field.name)}, indent_count + 1)')
|
||||||
} else {
|
} else {
|
||||||
g.auto_str_funcs.write('indents, it->${c_name(field.name)}')
|
g.auto_str_funcs.write('indents, it->${c_name(field.name)}')
|
||||||
if field.typ == table.bool_type {
|
if field.typ == table.bool_type {
|
||||||
|
@ -381,3 +382,50 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
||||||
g.auto_str_funcs.writeln('\t}')
|
g.auto_str_funcs.writeln('\t}')
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_str_for_sum_type(info table.SumType, styp, str_fn_name string) {
|
||||||
|
mut gen_fn_names := map[string]string
|
||||||
|
for typ in info.variants {
|
||||||
|
sym := g.table.get_type_symbol(typ)
|
||||||
|
if !sym.has_method('str') {
|
||||||
|
field_styp := g.typ(typ)
|
||||||
|
field_fn_name := g.gen_str_for_type_with_styp(typ, field_styp)
|
||||||
|
gen_fn_names[field_styp] = field_fn_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// _str() functions should have a single argument, the indenting ones take 2:
|
||||||
|
g.type_definitions.writeln('string ${str_fn_name}($styp x); // auto')
|
||||||
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0); }')
|
||||||
|
g.type_definitions.writeln('string indent_${str_fn_name}($styp x, int indent_count); // auto')
|
||||||
|
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp x, int indent_count) {')
|
||||||
|
mut clean_sum_type_v_type_name := styp.replace('__', '.')
|
||||||
|
if styp.ends_with('*') {
|
||||||
|
clean_sum_type_v_type_name = '&' + clean_sum_type_v_type_name.replace('*', '')
|
||||||
|
}
|
||||||
|
clean_sum_type_v_type_name = util.strip_main_name(clean_sum_type_v_type_name)
|
||||||
|
g.auto_str_funcs.writeln('\tswitch(x.typ) {')
|
||||||
|
for typ in info.variants {
|
||||||
|
mut value_fmt := '%.*s\\000'
|
||||||
|
if typ == table.string_type {
|
||||||
|
value_fmt = '\'$value_fmt\''
|
||||||
|
}
|
||||||
|
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, typ_str)
|
||||||
|
}
|
||||||
|
sym := g.table.get_type_symbol(typ)
|
||||||
|
if sym.kind == .struct_ {
|
||||||
|
func_name = 'indent_$func_name'
|
||||||
|
}
|
||||||
|
g.auto_str_funcs.write('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(*($typ_str*)x._object')
|
||||||
|
if sym.kind == .struct_ {
|
||||||
|
g.auto_str_funcs.write(', indent_count')
|
||||||
|
}
|
||||||
|
g.auto_str_funcs.writeln('));')
|
||||||
|
}
|
||||||
|
g.auto_str_funcs.writeln('\t\tdefault: return tos_lit("unknown sum type value");')
|
||||||
|
g.auto_str_funcs.writeln('\t}')
|
||||||
|
g.auto_str_funcs.writeln('}')
|
||||||
|
}
|
||||||
|
|
|
@ -4159,7 +4159,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
|
||||||
g.enum_expr(expr)
|
g.enum_expr(expr)
|
||||||
g.write('")')
|
g.write('")')
|
||||||
}
|
}
|
||||||
} else if sym_has_str_method || sym.kind in [.array, .array_fixed, .map, .struct_, .multi_return] {
|
} else if sym_has_str_method || sym.kind in
|
||||||
|
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type] {
|
||||||
is_p := etype.is_ptr()
|
is_p := etype.is_ptr()
|
||||||
val_type := if is_p { etype.deref() } else { etype }
|
val_type := if is_p { etype.deref() } else { etype }
|
||||||
str_fn_name := g.gen_str_for_type(val_type)
|
str_fn_name := g.gen_str_for_type(val_type)
|
||||||
|
@ -5073,6 +5074,8 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
|
||||||
return '%g\\000' // g removes trailing zeros unlike %f
|
return '%g\\000' // g removes trailing zeros unlike %f
|
||||||
} else if typ == table.u64_type {
|
} else if typ == table.u64_type {
|
||||||
return '%lld\\000'
|
return '%lld\\000'
|
||||||
|
} else if sym.kind == .sum_type {
|
||||||
|
return '%.*s\\000'
|
||||||
}
|
}
|
||||||
return '%d\\000'
|
return '%d\\000'
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
struct Abc {
|
||||||
|
foo int
|
||||||
|
bar bool
|
||||||
|
str string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ST = int | string | bool | Abc
|
||||||
|
|
||||||
|
fn test_int_st_str() {
|
||||||
|
a := ST(0)
|
||||||
|
assert '$a' == 'ST(0)'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_string_st_str() {
|
||||||
|
a := ST('test')
|
||||||
|
assert '$a' == 'ST(\'test\')'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_struct_st_str() {
|
||||||
|
a := ST(Abc{})
|
||||||
|
assert '$a' == 'ST(Abc {\n foo: 0\n bar: false\n str: \'\'\n})'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_bool_st_str() {
|
||||||
|
a := ST(false)
|
||||||
|
assert '$a' == 'ST(false)'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_str() {
|
||||||
|
a := ST(false)
|
||||||
|
assert a.str() == 'ST(false)'
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Container {
|
||||||
|
st ST
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_in_struct() {
|
||||||
|
c := Container{ST(0)}
|
||||||
|
assert '$c' == 'Container {\n st: ST(0)\n}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_unknown_value() {
|
||||||
|
c := Container{}
|
||||||
|
assert '$c' == 'Container {\n st: unknown sum type value\n}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_nested_in_struct() {
|
||||||
|
abc := Abc{}
|
||||||
|
c := Container{ST(abc)}
|
||||||
|
assert '$c' == 'Container {\n st: ST(Abc {\n foo: 0\n bar: false\n str: \'\'\n })\n}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_pointer() {
|
||||||
|
st := ST(0)
|
||||||
|
assert '${&st}' == '&ST(0)'
|
||||||
|
}
|
Loading…
Reference in New Issue