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

cgen: use faster array_push instead of _PUSH; re-fmt cgen.v

This commit is contained in:
Alexander Medvednikov 2020-04-20 03:54:35 +02:00
parent be3bd520f6
commit 19a5436118

View File

@ -14,9 +14,13 @@ import term
const ( const (
c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', 'auto', c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', 'auto',
'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', 'char'
'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'default'
'void', 'volatile', 'while'] 'do'
'double', 'extern', 'float', 'inline', 'int', 'long', 'register', 'restrict', 'short',
'signed'
'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'
]
) )
fn foo(t token.Token) { fn foo(t token.Token) {
@ -64,12 +68,13 @@ mut:
const ( const (
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t', tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
'\t\t\t\t\t\t\t\t'] '\t\t\t\t\t\t\t\t'
]
) )
pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string { pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
if true { // if if true { // if
x := 10 // line x := 10 // line
// sep // sep
y := 20 y := 20
} else { } else {
@ -113,7 +118,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
g.stmts(file.stmts) g.stmts(file.stmts)
} }
if autofree_used { if autofree_used {
g.autofree = true // so that void _vcleanup is generated g.autofree = true // so that void _vcleanup is generated
} }
g.write_variadic_types() g.write_variadic_types()
// g.write_str_definitions() // g.write_str_definitions()
@ -140,7 +145,7 @@ pub fn (g Gen) hashes() string {
pub fn (var g Gen) init() { pub fn (var g Gen) init() {
g.cheaders.writeln('// Generated by the V compiler') g.cheaders.writeln('// Generated by the V compiler')
g.cheaders.writeln('#include <inttypes.h>') // int64_t etc g.cheaders.writeln('#include <inttypes.h>') // int64_t etc
g.cheaders.writeln(c_builtin_types) g.cheaders.writeln(c_builtin_types)
g.cheaders.writeln(c_headers) g.cheaders.writeln(c_headers)
g.definitions.writeln('\nstring _STR(const char*, ...);\n') g.definitions.writeln('\nstring _STR(const char*, ...);\n')
@ -219,7 +224,7 @@ pub fn (var g Gen) typ(t table.Type) string {
} }
if !(styp in g.optionals) { if !(styp in g.optionals) {
// println(styp) // println(styp)
x := styp // .replace('*', '_ptr') // handle option ptrs x := styp // .replace('*', '_ptr') // handle option ptrs
g.typedefs2.writeln('typedef Option $x;') g.typedefs2.writeln('typedef Option $x;')
g.optionals << styp g.optionals << styp
} }
@ -424,19 +429,16 @@ fn (var g Gen) stmt(node ast.Stmt) {
ast.ExprStmt { ast.ExprStmt {
g.expr(it.expr) g.expr(it.expr)
expr := it.expr expr := it.expr
// no ; after an if expression }
match expr { match expr {
ast.IfExpr { ast.IfExpr {}
// no ; after an if expression else { if !g.inside_ternary {
}
else {
if !g.inside_ternary {
g.writeln(';') g.writeln(';')
} } }
}
} }
} }
ast.FnDecl { ast.FnDecl {
g.fn_decl = it // &it g.fn_decl = it // &it
g.gen_fn_decl(it) g.gen_fn_decl(it)
g.writeln('') g.writeln('')
} }
@ -721,7 +723,7 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
} }
g.expr(ident) g.expr(ident)
if is_optional { if is_optional {
mr_styp2 := mr_styp[7..] // remove Option_ mr_styp2 := mr_styp[7..] // remove Option_
g.writeln(' = (*(${mr_styp2}*)${mr_var_name}.data).arg$i;') g.writeln(' = (*(${mr_styp2}*)${mr_var_name}.data).arg$i;')
} else { } else {
g.writeln(' = ${mr_var_name}.arg$i;') g.writeln(' = ${mr_var_name}.arg$i;')
@ -758,9 +760,7 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i]) right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
var is_fixed_array_init := false var is_fixed_array_init := false
match val { match val {
ast.ArrayInit { ast.ArrayInit { is_fixed_array_init = it.is_fixed }
is_fixed_array_init = it.is_fixed
}
else {} else {}
} }
is_decl := assign_stmt.op == .decl_assign is_decl := assign_stmt.op == .decl_assign
@ -799,15 +799,9 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
fn (var g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool { fn (var g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool {
var is_ident := false var is_ident := false
match val { match val {
ast.Ident { ast.Ident { is_ident = true }
is_ident = true ast.SelectorExpr { is_ident = true }
} else { return false }
ast.SelectorExpr {
is_ident = true
}
else {
return false
}
} }
if g.autofree && right_sym.kind == .array && is_ident { if g.autofree && right_sym.kind == .array && is_ident {
// `arr1 = arr2` => `arr1 = arr2.clone()` // `arr1 = arr2` => `arr1 = arr2.clone()`
@ -988,7 +982,7 @@ fn (var g Gen) expr(node ast.Expr) {
g.write('0') g.write('0')
g.write(it.val[2..]) g.write(it.val[2..])
} else { } else {
g.write(it.val) // .int().str()) g.write(it.val) // .int().str())
} }
} }
ast.MatchExpr { ast.MatchExpr {
@ -1094,7 +1088,6 @@ fn (var g Gen) expr(node ast.Expr) {
ast.AnonFn { ast.AnonFn {
sym := g.table.get_type_symbol(it.typ) sym := g.table.get_type_symbol(it.typ)
func := it.decl func := it.decl
// TODO: Fix hack and write function implementation directly to definitions // TODO: Fix hack and write function implementation directly to definitions
pos := g.out.len pos := g.out.len
type_name := g.typ(func.return_type) type_name := g.typ(func.return_type)
@ -1111,11 +1104,9 @@ fn (var g Gen) expr(node ast.Expr) {
g.out.writeln('}') g.out.writeln('}')
g.defer_stmts = [] g.defer_stmts = []
g.fn_decl = 0 g.fn_decl = 0
fn_body := g.out.after(pos) fn_body := g.out.after(pos)
g.definitions.write(fn_body) g.definitions.write(fn_body)
g.out.go_back(fn_body.len) g.out.go_back(fn_body.len)
g.out.write('&${sym.name}_impl') g.out.write('&${sym.name}_impl')
} }
else { else {
@ -1141,7 +1132,7 @@ fn (var g Gen) typeof_expr(node ast.TypeOf) {
} else if sym.kind == .function { } else if sym.kind == .function {
info := sym.info as table.FnType info := sym.info as table.FnType
fn_info := info.func fn_info := info.func
mut repr := 'fn (' var repr := 'fn ('
for i, arg in fn_info.args { for i, arg in fn_info.args {
if i > 0 { if i > 0 {
repr += ', ' repr += ', '
@ -1160,12 +1151,8 @@ fn (var g Gen) typeof_expr(node ast.TypeOf) {
fn (var g Gen) enum_expr(node ast.Expr) { fn (var g Gen) enum_expr(node ast.Expr) {
match node { match node {
ast.EnumVal { ast.EnumVal { g.write(it.val) }
g.write(it.val) else { g.expr(node) }
}
else {
g.expr(node)
}
} }
} }
@ -1261,30 +1248,14 @@ fn (var g Gen) infix_expr(node ast.InfixExpr) {
right_sym := g.table.get_type_symbol(node.right_type) right_sym := g.table.get_type_symbol(node.right_type)
if node.left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in { if node.left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in {
fn_name := match node.op { fn_name := match node.op {
.plus { .plus { 'string_add(' }
'string_add(' .eq { 'string_eq(' }
} .ne { 'string_ne(' }
.eq { .lt { 'string_lt(' }
'string_eq(' .le { 'string_le(' }
} .gt { 'string_gt(' }
.ne { .ge { 'string_ge(' }
'string_ne(' else { '/*node error*/' }
}
.lt {
'string_lt('
}
.le {
'string_le('
}
.gt {
'string_gt('
}
.ge {
'string_ge('
}
else {
'/*node error*/'
}
} }
g.write(fn_name) g.write(fn_name)
g.expr(node.left) g.expr(node.left)
@ -1358,13 +1329,20 @@ fn (var g Gen) infix_expr(node ast.InfixExpr) {
g.write('), $tmp, $styp)') g.write('), $tmp, $styp)')
} else { } else {
// push a single element // push a single element
/*
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
// g.write('array_push(&')
g.write('_PUSH(&') g.write('_PUSH(&')
g.expr(node.left) g.expr(node.left)
g.write(', (') g.write(', (')
g.expr_with_cast(node.right, node.right_type, info.elem_type) g.expr_with_cast(node.right, node.right_type, info.elem_type)
g.write('), $tmp, $elem_type_str)') g.write('), $tmp, $elem_type_str)')
*/
elem_type_str := g.typ(info.elem_type)
g.write('array_push(&')
g.expr(node.left)
g.write(', &($elem_type_str[]){ ')
g.expr_with_cast(node.right, node.right_type, info.elem_type)
g.write(' })')
} }
} else if (node.left_type == node.right_type) && node.left_type in [table.f32_type_idx, } else if (node.left_type == node.right_type) && node.left_type in [table.f32_type_idx,
table.f64_type_idx] && node.op in [.eq, .ne] { table.f64_type_idx] && node.op in [.eq, .ne] {
@ -1398,7 +1376,7 @@ fn (var g Gen) infix_expr(node ast.InfixExpr) {
g.expr(node.right) g.expr(node.right)
g.write(')') g.write(')')
} else { } else {
need_par := node.op in [.amp, .pipe, .xor] // `x & y == 0` => `(x & y) == 0` in C need_par := node.op in [.amp, .pipe, .xor] // `x & y == 0` => `(x & y) == 0` in C
if need_par { if need_par {
g.write('(') g.write('(')
} }
@ -1537,7 +1515,7 @@ fn (var g Gen) ident(node ast.Ident) {
// `println(x)` => `println(*(int*)x.data)` // `println(x)` => `println(*(int*)x.data)`
if it.is_optional && !(g.is_assign_lhs && g.right_is_opt) { if it.is_optional && !(g.is_assign_lhs && g.right_is_opt) {
g.write('/*opt*/') g.write('/*opt*/')
styp := g.typ(it.typ)[7..] // Option_int => int TODO perf? styp := g.typ(it.typ)[7..] // Option_int => int TODO perf?
g.write('(*($styp*)${name}.data)') g.write('(*($styp*)${name}.data)')
return return
} }
@ -1722,39 +1700,17 @@ fn (var g Gen) index_expr(node ast.IndexExpr) {
g.expr(node.index) g.expr(node.index)
g.write(') ') g.write(') ')
op := match g.assign_op { op := match g.assign_op {
.mult_assign { .mult_assign { '*' }
'*' .plus_assign { '+' }
} .minus_assign { '-' }
.plus_assign { .div_assign { '/' }
'+' .xor_assign { '^' }
} .mod_assign { '%' }
.minus_assign { .or_assign { '|' }
'-' .and_assign { '&' }
} .left_shift_assign { '<<' }
.div_assign { .right_shift_assign { '>>' }
'/' else { '' }
}
.xor_assign {
'^'
}
.mod_assign {
'%'
}
.or_assign {
'|'
}
.and_assign {
'&'
}
.left_shift_assign {
'<<'
}
.right_shift_assign {
'>>'
}
else {
''
}
} }
g.write(op) g.write(op)
} }
@ -1824,8 +1780,8 @@ fn (var g Gen) return_statement(node ast.Return) {
typ_sym := g.table.get_type_symbol(g.fn_decl.return_type) typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
mr_info := typ_sym.info as table.MultiReturn mr_info := typ_sym.info as table.MultiReturn
var styp := g.typ(g.fn_decl.return_type) var styp := g.typ(g.fn_decl.return_type)
if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] != if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
styp = styp[7..] // remove 'Option_' styp = styp[7..] // remove 'Option_'
var x := styp var x := styp
if x.ends_with('_ptr') { if x.ends_with('_ptr') {
x = x.replace('_ptr', '*') x = x.replace('_ptr', '*')
@ -1862,13 +1818,13 @@ fn (var g Gen) return_statement(node ast.Return) {
// TODO: why? // TODO: why?
// if !it.is_method { // if !it.is_method {
if it.name == 'error' { if it.name == 'error' {
is_error = true // TODO check name 'error' is_error = true // TODO check name 'error'
} }
} }
else {} else {}
} }
if !is_none && !is_error { if !is_none && !is_error {
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_'
var x := styp var x := styp
if x.ends_with('_ptr') { if x.ends_with('_ptr') {
x = x.replace('_ptr', '*') x = x.replace('_ptr', '*')
@ -1946,21 +1902,23 @@ fn (var g Gen) struct_init(struct_init ast.StructInit) {
styp := g.typ(struct_init.typ) styp := g.typ(struct_init.typ)
is_amp := g.is_amp is_amp := g.is_amp
if is_amp { if is_amp {
g.out.go_back(1) // delete the & already generated in `prefix_expr() g.out.go_back(1) // delete the & already generated in `prefix_expr()
g.write('($styp*)memdup(&($styp){') g.write('($styp*)memdup(&($styp){')
} else { } else {
g.writeln('($styp){') g.writeln('($styp){')
} }
// var fields := []string // var fields := []string
var inited_fields := []string // TODO this is done in checker, move to ast node var inited_fields := []string // TODO this is done in checker, move to ast node
/*if struct_init.fields.len == 0 && struct_init.exprs.len > 0 { /*
if struct_init.fields.len == 0 && struct_init.exprs.len > 0 {
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser. // Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
for f in info.fields { for f in info.fields {
fields << f.name fields << f.name
} }
} else { } else {
fields = struct_init.fields fields = struct_init.fields
}*/ }
*/
// User set fields // User set fields
for i, field in struct_init.fields { for i, field in struct_init.fields {
field_name := c_name(field.name) field_name := c_name(field.name)
@ -1983,7 +1941,6 @@ fn (var g Gen) struct_init(struct_init ast.StructInit) {
g.write('\t.$field_name = ') g.write('\t.$field_name = ')
if field.has_default_expr { if field.has_default_expr {
g.expr(field.default_expr) g.expr(field.default_expr)
} else { } else {
g.write(g.type_default(field.typ)) g.write(g.type_default(field.typ))
} }
@ -2122,7 +2079,7 @@ const (
) )
fn (var g Gen) write_builtin_types() { fn (var g Gen) write_builtin_types() {
var builtin_types := []table.TypeSymbol // builtin types var builtin_types := []table.TypeSymbol // builtin types
// builtin types need to be on top // builtin types need to be on top
// everything except builtin will get sorted // everything except builtin will get sorted
for builtin_name in builtins { for builtin_name in builtins {
@ -2135,7 +2092,7 @@ fn (var g Gen) write_builtin_types() {
// Sort the types, make sure types that are referenced by other types // Sort the types, make sure types that are referenced by other types
// are added before them. // are added before them.
fn (var g Gen) write_sorted_types() { fn (var g Gen) write_sorted_types() {
var types := []table.TypeSymbol // structs that need to be sorted var types := []table.TypeSymbol // structs that need to be sorted
for typ in g.table.types { for typ in g.table.types {
if !(typ.name in builtins) { if !(typ.name in builtins) {
types << typ types << typ
@ -2379,7 +2336,7 @@ fn (var g Gen) string_inter_literal(node ast.StringInterLiteral) {
// `nums.filter(it % 2 == 0)` // `nums.filter(it % 2 == 0)`
fn (var g Gen) gen_filter(node ast.CallExpr) { fn (var g Gen) gen_filter(node ast.CallExpr) {
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
s := g.out.after(g.stmt_start_pos) // the already generated part of current statement s := g.out.after(g.stmt_start_pos) // the already generated part of current statement
g.out.go_back(s.len) g.out.go_back(s.len)
// println('filter s="$s"') // println('filter s="$s"')
sym := g.table.get_type_symbol(node.return_type) sym := g.table.get_type_symbol(node.return_type)
@ -2398,7 +2355,7 @@ fn (var g Gen) gen_filter(node ast.CallExpr) {
g.expr(node.left) g.expr(node.left)
g.writeln('.data)[i];') g.writeln('.data)[i];')
g.write('if (') g.write('if (')
g.expr(node.args[0].expr) // the first arg is the filter condition g.expr(node.args[0].expr) // the first arg is the filter condition
g.writeln(') array_push(&$tmp, &it); \n }') g.writeln(') array_push(&$tmp, &it); \n }')
g.write(s) g.write(s)
g.write(' ') g.write(' ')
@ -2418,8 +2375,8 @@ fn (var g Gen) insert_before(s string) {
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }` // `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }`
fn (var g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) { fn (var g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
mr_styp := g.typ(return_type) mr_styp := g.typ(return_type)
mr_styp2 := mr_styp[7..] // remove Option_ mr_styp2 := mr_styp[7..] // remove Option_
g.writeln(';') // or') g.writeln(';') // or')
g.writeln('if (!${var_name}.ok) {') g.writeln('if (!${var_name}.ok) {')
g.writeln('\tstring err = ${var_name}.v_error;') g.writeln('\tstring err = ${var_name}.v_error;')
g.writeln('\tint errcode = ${var_name}.ecode;') g.writeln('\tint errcode = ${var_name}.ecode;')
@ -2469,12 +2426,8 @@ fn (var g Gen) type_of_last_statement(stmts []ast.Stmt) (string, string) {
fn (var g Gen) type_of_call_expr(node ast.Expr) string { fn (var g Gen) type_of_call_expr(node ast.Expr) string {
match node { match node {
ast.CallExpr { ast.CallExpr { return g.typ(it.return_type) }
return g.typ(it.return_type) else { return typeof(node) }
}
else {
return typeof(node)
}
} }
return '' return ''
} }
@ -2504,114 +2457,48 @@ fn (var g Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
fn op_to_fn_name(name string) string { fn op_to_fn_name(name string) string {
return match name { return match name {
'+' { '+' { '_op_plus' }
'_op_plus' '-' { '_op_minus' }
} '*' { '_op_mul' }
'-' { '/' { '_op_div' }
'_op_minus' '%' { '_op_mod' }
} else { 'bad op $name' }
'*' {
'_op_mul'
}
'/' {
'_op_div'
}
'%' {
'_op_mod'
}
else {
'bad op $name'
}
} }
} }
fn comp_if_to_ifdef(name string) string { fn comp_if_to_ifdef(name string) string {
match name { match name {
// platforms/os-es: // platforms/os-es:
'windows' { 'windows' { return '_WIN32' }
return '_WIN32' 'mac' { return '__APPLE__' }
} 'macos' { return '__APPLE__' }
'mac' { 'linux' { return '__linux__' }
return '__APPLE__' 'freebsd' { return '__FreeBSD__' }
} 'openbsd' { return '__OpenBSD__' }
'macos' { 'netbsd' { return '__NetBSD__' }
return '__APPLE__' 'dragonfly' { return '__DragonFly__' }
} 'msvc' { return '_MSC_VER' }
'linux' { 'android' { return '__ANDROID__' }
return '__linux__' 'solaris' { return '__sun' }
} 'haiku' { return '__haiku__' }
'freebsd' { 'linux_or_macos' { return '' }
return '__FreeBSD__'
}
'openbsd' {
return '__OpenBSD__'
}
'netbsd' {
return '__NetBSD__'
}
'dragonfly' {
return '__DragonFly__'
}
'msvc' {
return '_MSC_VER'
}
'android' {
return '__ANDROID__'
}
'solaris' {
return '__sun'
}
'haiku' {
return '__haiku__'
}
'linux_or_macos' {
return ''
}
// //
'js' { 'js' { return '_VJS' }
return '_VJS'
}
// compilers: // compilers:
'tinyc' { 'tinyc' { return '__TINYC__' }
return '__TINYC__' 'clang' { return '__clang__' }
} 'mingw' { return '__MINGW32__' }
'clang' { 'msvc' { return '_MSC_VER' }
return '__clang__'
}
'mingw' {
return '__MINGW32__'
}
'msvc' {
return '_MSC_VER'
}
// other: // other:
'debug' { 'debug' { return '_VDEBUG' }
return '_VDEBUG' 'glibc' { return '__GLIBC__' }
} 'prealloc' { return 'VPREALLOC' }
'glibc' { 'no_bounds_checking' { return 'NO_BOUNDS_CHECK' }
return '__GLIBC__' 'x64' { return 'TARGET_IS_64BIT' }
} 'x32' { return 'TARGET_IS_32BIT' }
'prealloc' { 'little_endian' { return 'TARGET_ORDER_IS_LITTLE' }
return 'VPREALLOC' 'big_endian' { return 'TARGET_ORDER_IS_BIG' }
} else { verror('bad os ifdef name "$name"') }
'no_bounds_checking' {
return 'NO_BOUNDS_CHECK'
}
'x64' {
return 'TARGET_IS_64BIT'
}
'x32' {
return 'TARGET_IS_32BIT'
}
'little_endian' {
return 'TARGET_ORDER_IS_LITTLE'
}
'big_endian' {
return 'TARGET_ORDER_IS_BIG'
}
else {
verror('bad os ifdef name "$name"')
}
} }
// verror('bad os ifdef name "$name"') // verror('bad os ifdef name "$name"')
return '' return ''
@ -2663,12 +2550,8 @@ fn (g Gen) type_default(typ table.Type) string {
} }
*/ */
match sym.name { match sym.name {
'string' { 'string' { return 'tos3("")' }
return 'tos3("")' 'rune' { return '0' }
}
'rune' {
return '0'
}
else {} else {}
} }
return '{0}' return '{0}'
@ -2899,21 +2782,11 @@ fn (var g Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
} }
g.str_types << styp g.str_types << styp
match sym.info { match sym.info {
table.Alias { table.Alias { g.gen_str_default(sym, styp) }
g.gen_str_default(sym, styp) table.Array { g.gen_str_for_array(it, styp) }
} table.Enum { g.gen_str_for_enum(it, styp) }
table.Array, table.ArrayFixed { table.Struct { g.gen_str_for_struct(it, styp) }
g.gen_str_for_array(it, styp) else { verror("could not generate string method for type \'${styp}\'") }
}
table.Enum {
g.gen_str_for_enum(it, styp)
}
table.Struct {
g.gen_str_for_struct(it, styp)
}
else {
verror("could not generate string method for type \'${styp}\'")
}
} }
} }
@ -3037,7 +2910,7 @@ fn (g Gen) type_to_fmt(typ table.Type) string {
} else if typ == table.bool_type { } else if typ == table.bool_type {
return '%.*s' return '%.*s'
} else if typ in [table.f32_type, table.f64_type] { } else if typ in [table.f32_type, table.f64_type] {
return '%g' // g removes trailing zeros unlike %f return '%g' // g removes trailing zeros unlike %f
} }
return '%d' return '%d'
} }