Skip to content

Commit

Permalink
cgen: make generics printable (#6700)
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldaeschle committed Oct 31, 2020
1 parent db59585 commit 9fdf04b
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
2 changes: 1 addition & 1 deletion vlib/v/checker/check_types.v
Expand Up @@ -314,7 +314,7 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
} else if typ.is_pointer() {
return `p`
} else {
mut sym := c.table.get_type_symbol(ftyp)
mut sym := c.table.get_type_symbol(c.unwrap_generic(ftyp))
if sym.kind == .alias {
// string aliases should be printable
info := sym.info as table.Alias
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/auto_str_methods.v
Expand Up @@ -8,7 +8,7 @@ import v.util

// already generated styp, reuse it
fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
mut sym := g.table.get_type_symbol(typ)
mut sym := g.table.get_type_symbol(g.unwrap_generic(typ))
mut str_fn_name := styp_to_str_fn_name(styp)
if sym.info is table.Alias {
sym = g.table.get_type_symbol((sym.info as table.Alias).parent_type)
Expand Down
31 changes: 16 additions & 15 deletions vlib/v/gen/str.v
Expand Up @@ -336,30 +336,31 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
if node.precisions[i] != 987698 {
fmt = '${fmt}.${node.precisions[i]}'
}
typ := g.unwrap_generic(node.expr_types[i])
if fspec == `s` {
if node.fwidths[i] == 0 {
g.write('.*s')
} else {
g.write('*.*s')
}
} else if node.expr_types[i].is_float() {
} else if typ.is_float() {
g.write('$fmt${fspec:c}')
} else if node.expr_types[i].is_pointer() {
} else if typ.is_pointer() {
if fspec == `p` {
g.write('${fmt}p')
} else {
g.write('$fmt"PRI${fspec:c}PTR"')
}
} else if node.expr_types[i].is_int() {
} else if typ.is_int() {
if fspec == `c` {
g.write('${fmt}c')
} else {
g.write('$fmt"PRI${fspec:c}')
if node.expr_types[i] in [table.i8_type, table.byte_type] {
if typ in [table.i8_type, table.byte_type] {
g.write('8')
} else if node.expr_types[i] in [table.i16_type, table.u16_type] {
} else if typ in [table.i16_type, table.u16_type] {
g.write('16')
} else if node.expr_types[i] in [table.i64_type, table.u64_type] {
} else if typ in [table.i64_type, table.u64_type] {
g.write('64')
} else {
g.write('32')
Expand All @@ -378,26 +379,26 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write('", $num_string_parts, ')
// Build args
for i, expr in node.exprs {
if node.expr_types[i] == table.string_type {
typ := g.unwrap_generic(node.expr_types[i])
if typ == table.string_type {
if g.inside_vweb_tmpl {
g.write('vweb__filter(')
g.expr(expr)
g.write(')')
} else {
g.expr(expr)
}
} else if node.expr_types[i] == table.bool_type {
} else if typ == table.bool_type {
g.expr(expr)
g.write(' ? _SLIT("true") : _SLIT("false")')
} else if node.expr_types[i].is_number() || node.expr_types[i].is_pointer() ||
node.fmts[i] == `d` {
if node.expr_types[i].is_signed() && node.fmts[i] in [`x`, `X`, `o`] {
} else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` {
if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] {
// convert to unsigned first befors C's integer propagation strikes
if node.expr_types[i] == table.i8_type {
if typ == table.i8_type {
g.write('(byte)(')
} else if node.expr_types[i] == table.i16_type {
} else if typ == table.i16_type {
g.write('(u16)(')
} else if node.expr_types[i] == table.int_type {
} else if typ == table.int_type {
g.write('(u32)(')
} else {
g.write('(u64)(')
Expand All @@ -408,7 +409,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.expr(expr)
}
} else if node.fmts[i] == `s` {
g.gen_expr_to_string(expr, node.expr_types[i])
g.gen_expr_to_string(expr, typ)
} else {
g.expr(expr)
}
Expand Down
13 changes: 13 additions & 0 deletions vlib/v/tests/str_gen_test.v
Expand Up @@ -218,3 +218,16 @@ fn test_map_with_struct() {
assert a.str() == 'MapWithStruct{\n foo: {\'test\': TestStruct{\n x: 0\n }}\n}'
assert '$a' == 'MapWithStruct{\n foo: {\'test\': TestStruct{\n x: 0\n }}\n}'
}

struct ForGeneric {}
fn generic_fn_interpolation<T>(p T) string {
return '$p'
}
fn generic_fn_str<T>(p T) string {
return p.str()
}
fn test_generic_auto_str() {
s := ForGeneric{}
assert generic_fn_interpolation(s) == 'ForGeneric{}'
assert generic_fn_str(s) == 'ForGeneric{}'
}

0 comments on commit 9fdf04b

Please sign in to comment.