1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix comptime interpolation (#18281)

This commit is contained in:
Felipe Pena 2023-05-27 15:41:40 -03:00 committed by GitHub
parent 43bc85d3bb
commit 6bfa6ec93c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 11 deletions

View File

@ -46,7 +46,7 @@ fn (mut g Gen) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
} }
} }
fn (mut g Gen) str_format(node ast.StringInterLiteral, i int) (u64, string) { fn (mut g Gen) str_format(node ast.StringInterLiteral, i int, fmts []u8) (u64, string) {
mut base := 0 // numeric base mut base := 0 // numeric base
mut upper_case := false // set upercase for the result string mut upper_case := false // set upercase for the result string
mut typ := g.unwrap_generic(node.expr_types[i]) mut typ := g.unwrap_generic(node.expr_types[i])
@ -59,7 +59,7 @@ fn (mut g Gen) str_format(node ast.StringInterLiteral, i int) (u64, string) {
typ = (sym.info as ast.Alias).parent_type typ = (sym.info as ast.Alias).parent_type
} }
mut remove_tail_zeros := false mut remove_tail_zeros := false
fspec := node.fmts[i] fspec := fmts[i]
mut fmt_type := StrIntpType.si_no_str mut fmt_type := StrIntpType.si_no_str
g.write('/*${fspec} ${sym}*/') g.write('/*${fspec} ${sym}*/')
// upper cases // upper cases
@ -159,9 +159,9 @@ fn (mut g Gen) str_format(node ast.StringInterLiteral, i int) (u64, string) {
return res, fmt_type.str() return res, fmt_type.str()
} }
fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) { fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {
expr := node.exprs[i] expr := node.exprs[i]
fmt := fmts[i]
typ := g.unwrap_generic(node.expr_types[i]) typ := g.unwrap_generic(node.expr_types[i])
typ_sym := g.table.sym(typ) typ_sym := g.table.sym(typ)
if typ == ast.string_type && g.comptime_for_method.len == 0 { if typ == ast.string_type && g.comptime_for_method.len == 0 {
@ -187,7 +187,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
g.expr(expr) g.expr(expr)
g.write('${dot}_object') g.write('${dot}_object')
g.write(')') g.write(')')
} else if node.fmts[i] == `s` || typ.has_flag(.variadic) { } else if fmt == `s` || typ.has_flag(.variadic) {
mut exp_typ := typ mut exp_typ := typ
if expr is ast.Ident { if expr is ast.Ident {
if expr.obj is ast.Var { if expr.obj is ast.Var {
@ -203,8 +203,8 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
} }
} }
g.gen_expr_to_string(expr, exp_typ) g.gen_expr_to_string(expr, exp_typ)
} else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` { } else if typ.is_number() || typ.is_pointer() || fmt == `d` {
if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] { if typ.is_signed() && fmt in [`x`, `X`, `o`] {
// convert to unsigned first befors C's integer propagation strikes // convert to unsigned first befors C's integer propagation strikes
if typ == ast.i8_type { if typ == ast.i8_type {
g.write('(byte)(') g.write('(byte)(')
@ -237,6 +237,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
// fn (mut g Gen) str_int2(node ast.StringInterLiteral) { // fn (mut g Gen) str_int2(node ast.StringInterLiteral) {
mut node_ := unsafe { node } mut node_ := unsafe { node }
mut fmts := node_.fmts.clone()
for i, mut expr in node_.exprs { for i, mut expr in node_.exprs {
if g.is_comptime_var(expr) { if g.is_comptime_var(expr) {
ctyp := g.get_comptime_var_type(expr) ctyp := g.get_comptime_var_type(expr)
@ -249,7 +250,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
} else { } else {
ctyp ctyp
} }
node_.fmts[i] = g.get_default_fmt(ctyp, typ) fmts[i] = g.get_default_fmt(ctyp, typ)
} }
} }
} }
@ -271,16 +272,16 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
break break
} }
ft_u64, ft_str := g.str_format(node, i) ft_u64, ft_str := g.str_format(node, i, fmts)
g.write('0x${ft_u64.hex()}, {.d_${ft_str} = ') g.write('0x${ft_u64.hex()}, {.d_${ft_str} = ')
// for pointers we need a void* cast // for pointers we need a void* cast
if unsafe { ft_str.str[0] } == `p` { if unsafe { ft_str.str[0] } == `p` {
g.write('(void*)(') g.write('(void*)(')
g.str_val(node, i) g.str_val(node, i, fmts)
g.write(')') g.write(')')
} else { } else {
g.str_val(node, i) g.str_val(node, i, fmts)
} }
g.write('}}') g.write('}}')

View File

@ -0,0 +1,27 @@
struct Foo {
a int
b f32
c string
}
fn print_struct[T](x &T) []string {
mut a := []string{}
$for field in T.fields {
typ := typeof((*x).$(field.name)).name
val := (*x).$(field.name)
a << '${field.name} (${typ}) = ${val}'
}
return a
}
fn test_main() {
foo := Foo{
a: 123
b: 4.56
c: 'hello'
}
out := print_struct(&foo)
assert out[0] == 'a (int) = 123'
assert out[1] == 'b (f32) = 4.56'
assert out[2] == 'c (string) = hello'
}