println: optimize and remove memory leaks
parent
5d4d3b838b
commit
1e32a4cec4
|
@ -670,7 +670,7 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
||||||
if i == f.args.len - 1 && arg.name == '..' {
|
if i == f.args.len - 1 && arg.name == '..' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
amp_ph := p.cgen.add_placeholder()
|
ph := p.cgen.add_placeholder()
|
||||||
// ) here means not enough args were supplied
|
// ) here means not enough args were supplied
|
||||||
if p.tok == RPAR {
|
if p.tok == RPAR {
|
||||||
str_args := f.str_args(p.table)// TODO this is C args
|
str_args := f.str_args(p.table)// TODO this is C args
|
||||||
|
@ -688,18 +688,21 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
||||||
p.check(MUT)
|
p.check(MUT)
|
||||||
}
|
}
|
||||||
typ := p.bool_expression()
|
typ := p.bool_expression()
|
||||||
// TODO temporary hack to allow println(777)
|
// Optimize `println`: replace it with `printf` to avoid extra allocations and
|
||||||
|
// function calls. `println(777)` => `printf("%d\n", 777)`
|
||||||
|
// (If we don't check for void, then V will compile `println(func())`)
|
||||||
if i == 0 && f.name == 'println' && typ != 'string' && typ != 'void' {
|
if i == 0 && f.name == 'println' && typ != 'string' && typ != 'void' {
|
||||||
// If we dont check for void, then V will compile "println(procedure())"
|
|
||||||
T := p.table.find_type(typ)
|
T := p.table.find_type(typ)
|
||||||
if typ == 'u8' {
|
fmt := p.typ_to_fmt(typ)
|
||||||
p.cgen.set_placeholder(amp_ph, 'u8_str(')
|
if fmt != '' {
|
||||||
}
|
p.cgen.cur_line = p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '", ')
|
||||||
else if T.parent == 'int' {
|
continue
|
||||||
p.cgen.set_placeholder(amp_ph, 'int_str(')
|
}
|
||||||
|
if T.parent == 'int' {
|
||||||
|
p.cgen.set_placeholder(ph, 'int_str(')
|
||||||
}
|
}
|
||||||
else if typ.ends_with('*') {
|
else if typ.ends_with('*') {
|
||||||
p.cgen.set_placeholder(amp_ph, 'ptr_str(')
|
p.cgen.set_placeholder(ph, 'ptr_str(')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Make sure this type has a `str()` method
|
// Make sure this type has a `str()` method
|
||||||
|
@ -719,7 +722,7 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
||||||
}
|
}
|
||||||
p.error('`$typ` needs to have method `str() string` to be printable')
|
p.error('`$typ` needs to have method `str() string` to be printable')
|
||||||
}
|
}
|
||||||
p.cgen.set_placeholder(amp_ph, '${typ}_str(')
|
p.cgen.set_placeholder(ph, '${typ}_str(')
|
||||||
}
|
}
|
||||||
p.gen(')')
|
p.gen(')')
|
||||||
continue
|
continue
|
||||||
|
@ -737,7 +740,7 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
||||||
if !is_interface {
|
if !is_interface {
|
||||||
// Dereference
|
// Dereference
|
||||||
if got.contains('*') && !expected.contains('*') {
|
if got.contains('*') && !expected.contains('*') {
|
||||||
p.cgen.set_placeholder(amp_ph, '*')
|
p.cgen.set_placeholder(ph, '*')
|
||||||
}
|
}
|
||||||
// Reference
|
// Reference
|
||||||
// TODO ptr hacks. DOOM hacks, fix please.
|
// TODO ptr hacks. DOOM hacks, fix please.
|
||||||
|
@ -746,14 +749,14 @@ fn (p mut Parser) fn_call_args(f *Fn) *Fn {
|
||||||
if ! (expected == 'void*' && got == 'int') &&
|
if ! (expected == 'void*' && got == 'int') &&
|
||||||
! (expected == 'byte*' && got.contains(']byte')) &&
|
! (expected == 'byte*' && got.contains(']byte')) &&
|
||||||
! (expected == 'byte*' && got == 'string') {
|
! (expected == 'byte*' && got == 'string') {
|
||||||
p.cgen.set_placeholder(amp_ph, '& /*11 EXP:"$expected" GOT:"$got" */')
|
p.cgen.set_placeholder(ph, '& /*11 EXP:"$expected" GOT:"$got" */')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// interface?
|
// interface?
|
||||||
if is_interface {
|
if is_interface {
|
||||||
if !got.contains('*') {
|
if !got.contains('*') {
|
||||||
p.cgen.set_placeholder(amp_ph, '&')
|
p.cgen.set_placeholder(ph, '&')
|
||||||
}
|
}
|
||||||
// Pass all interface methods
|
// Pass all interface methods
|
||||||
interface_type := p.table.find_type(arg.typ)
|
interface_type := p.table.find_type(arg.typ)
|
||||||
|
|
|
@ -2149,7 +2149,6 @@ fn (p mut Parser) typ_to_fmt(typ string) string {
|
||||||
if typ.ends_with('*') {
|
if typ.ends_with('*') {
|
||||||
return '%p'
|
return '%p'
|
||||||
}
|
}
|
||||||
p.error('unhandled sprintf format "$typ" ')
|
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -2214,17 +2213,22 @@ fn (p mut Parser) string_expr() {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
format += p.typ_to_fmt(typ)
|
f := p.typ_to_fmt(typ)
|
||||||
|
if f == '' {
|
||||||
|
p.error('unhandled sprintf format "$typ" ')
|
||||||
|
}
|
||||||
|
format += f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println("hello %d", num) optimization.
|
// println("hello %d", num) optimization.
|
||||||
if p.cgen.nogen {
|
if p.cgen.nogen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Don't allocate a new string, just print it. TODO HACK PRINT OPT
|
// println: don't allocate a new string, just print it.
|
||||||
cur_line := p.cgen.cur_line.trim_space()
|
cur_line := p.cgen.cur_line.trim_space()
|
||||||
if cur_line.contains('println(') && p.tok != PLUS && !p.pref.is_prod && !cur_line.contains('string_add') {
|
if cur_line.contains('println (') && p.tok != PLUS &&
|
||||||
p.cgen.cur_line = cur_line.replace('println(', 'printf(')
|
!cur_line.contains('string_add') && !cur_line.contains('eprintln') {
|
||||||
|
p.cgen.cur_line = cur_line.replace('println (', 'printf(')
|
||||||
p.gen('$format\\n$args')
|
p.gen('$format\\n$args')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ struct B{
|
||||||
mut:
|
mut:
|
||||||
a A
|
a A
|
||||||
}
|
}
|
||||||
|
|
||||||
struct C {
|
struct C {
|
||||||
mut:
|
mut:
|
||||||
b B
|
b B
|
||||||
|
@ -15,6 +16,11 @@ mut:
|
||||||
as []A
|
as []A
|
||||||
num int
|
num int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
fn test_struct_levels() {
|
fn test_struct_levels() {
|
||||||
mut c := C{}
|
mut c := C{}
|
||||||
|
@ -42,3 +48,9 @@ fn test_struct_levels() {
|
||||||
c.as[0].val = 10
|
c.as[0].val = 10
|
||||||
assert c.as[0].val == 10
|
assert c.as[0].val == 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_struct_str() {
|
||||||
|
u := User{'Bob', 30}
|
||||||
|
println(u) // make sure the struct is printable
|
||||||
|
// assert u.str() == '{name:"Bob", age:30}' // TODO
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue