cgen: autofree: first step
parent
efbf114a2f
commit
e5f6a0949f
|
@ -42,6 +42,7 @@ pub fn make(len int, cap int, elm_size int) array {
|
||||||
// Private function, used by V (`nums := [1, 2, 3]`)
|
// Private function, used by V (`nums := [1, 2, 3]`)
|
||||||
fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array {
|
fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array {
|
||||||
cap_ := if cap == 0 { 1 } else { cap }
|
cap_ := if cap == 0 { 1 } else { cap }
|
||||||
|
|
||||||
arr := array{
|
arr := array{
|
||||||
len: len
|
len: len
|
||||||
cap: cap
|
cap: cap
|
||||||
|
@ -377,7 +378,9 @@ pub fn (a []int) str() string {
|
||||||
mut sb := strings.new_builder(a.len * 13)
|
mut sb := strings.new_builder(a.len * 13)
|
||||||
sb.write('[')
|
sb.write('[')
|
||||||
for i in 0..a.len {
|
for i in 0..a.len {
|
||||||
sb.write(a[i].str())
|
val := a[i].str()
|
||||||
|
sb.write(val)
|
||||||
|
val.free()
|
||||||
if i < a.len - 1 {
|
if i < a.len - 1 {
|
||||||
sb.write(', ')
|
sb.write(', ')
|
||||||
}
|
}
|
||||||
|
|
|
@ -2809,6 +2809,13 @@ fn (p mut Parser) array_init() string {
|
||||||
p.gen_array_init(real, no_alloc, new_arr_ph, i)
|
p.gen_array_init(real, no_alloc, new_arr_ph, i)
|
||||||
typ = 'array_${stringify_pointer(typ)}'
|
typ = 'array_${stringify_pointer(typ)}'
|
||||||
p.register_array(typ)
|
p.register_array(typ)
|
||||||
|
if p.tok == .lcbr && i == 0 && p.peek() == .name {
|
||||||
|
// []string{len:10} (V2)
|
||||||
|
for p.tok != .rcbr {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
p.check(.rcbr)
|
||||||
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,11 @@ fn C.symlink(charptr, charptr) int
|
||||||
|
|
||||||
fn init_os_args(argc int, argv &byteptr) []string {
|
fn init_os_args(argc int, argv &byteptr) []string {
|
||||||
mut args := []string
|
mut args := []string
|
||||||
|
//mut args := []string(make(0, argc, sizeof(string)))
|
||||||
|
//mut args := []string{len:argc}
|
||||||
for i in 0 .. argc {
|
for i in 0 .. argc {
|
||||||
|
|
||||||
|
//args [i] = string(argv[i])
|
||||||
args << string(argv[i])
|
args << string(argv[i])
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
|
|
|
@ -153,6 +153,7 @@ pub:
|
||||||
rec_mut bool // is receiver mutable
|
rec_mut bool // is receiver mutable
|
||||||
is_c bool
|
is_c bool
|
||||||
no_body bool // just a definition `fn C.malloc()`
|
no_body bool // just a definition `fn C.malloc()`
|
||||||
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BranchStmt {
|
pub struct BranchStmt {
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct Gen {
|
||||||
inits strings.Builder // contents of `void _vinit(){}`
|
inits strings.Builder // contents of `void _vinit(){}`
|
||||||
table &table.Table
|
table &table.Table
|
||||||
mut:
|
mut:
|
||||||
|
file ast.File
|
||||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||||
tmp_count int
|
tmp_count int
|
||||||
varaidic_args map[string]int
|
varaidic_args map[string]int
|
||||||
|
@ -26,6 +27,7 @@ mut:
|
||||||
inside_ternary bool // ?: comma separated statements on a single line
|
inside_ternary bool // ?: comma separated statements on a single line
|
||||||
stmt_start_pos int
|
stmt_start_pos int
|
||||||
right_is_opt bool
|
right_is_opt bool
|
||||||
|
autofree bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||||
|
@ -37,9 +39,16 @@ pub fn cgen(files []ast.File, table &table.Table) string {
|
||||||
inits: strings.new_builder(100)
|
inits: strings.new_builder(100)
|
||||||
table: table
|
table: table
|
||||||
fn_decl: 0
|
fn_decl: 0
|
||||||
|
autofree: true
|
||||||
}
|
}
|
||||||
g.init()
|
g.init()
|
||||||
for file in files {
|
for file in files {
|
||||||
|
// println('cgen "$g.file.path" $file.stmts.len')
|
||||||
|
g.file = file
|
||||||
|
if g.file.path == '' || g.file.path.ends_with('.vv') {
|
||||||
|
// cgen test
|
||||||
|
g.autofree = false
|
||||||
|
}
|
||||||
g.stmts(file.stmts)
|
g.stmts(file.stmts)
|
||||||
}
|
}
|
||||||
g.write_variadic_types()
|
g.write_variadic_types()
|
||||||
|
@ -498,6 +507,9 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if name == 'exit' {
|
if name == 'exit' {
|
||||||
name = 'v_exit'
|
name = 'v_exit'
|
||||||
}
|
}
|
||||||
|
if name == 'free' {
|
||||||
|
name = 'v_free'
|
||||||
|
}
|
||||||
// type_name := g.table.type_to_str(it.return_type)
|
// type_name := g.table.type_to_str(it.return_type)
|
||||||
type_name := g.typ(it.return_type)
|
type_name := g.typ(it.return_type)
|
||||||
g.write('$type_name ${name}(')
|
g.write('$type_name ${name}(')
|
||||||
|
@ -528,13 +540,31 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
}
|
}
|
||||||
if is_main {
|
if is_main {
|
||||||
g.writeln('_vinit();')
|
g.writeln('_vinit();')
|
||||||
|
if g.autofree {
|
||||||
|
g.writeln('free(os__args.data); // empty, inited in _vinit()')
|
||||||
|
}
|
||||||
g.writeln('os__args = os__init_os_args(argc, (byteptr*)argv);')
|
g.writeln('os__args = os__init_os_args(argc, (byteptr*)argv);')
|
||||||
}
|
}
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
// g.write('\t')
|
// g.write('\t')
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
}
|
}
|
||||||
|
// ////////////
|
||||||
|
if g.autofree && false {
|
||||||
|
scope := g.file.scope.innermost(it.pos.pos - 1)
|
||||||
|
for i, var in scope.vars {
|
||||||
|
sym := g.table.get_type_symbol(var.typ)
|
||||||
|
if sym.kind == .array && !table.type_is_optional(var.typ) {
|
||||||
|
g.writeln('array_free($var.name); // autofree')
|
||||||
|
}
|
||||||
|
println(var.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// /////////
|
||||||
if is_main {
|
if is_main {
|
||||||
|
if g.autofree {
|
||||||
|
g.writeln('_vcleanup();')
|
||||||
|
}
|
||||||
g.writeln('return 0;')
|
g.writeln('return 0;')
|
||||||
}
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
@ -592,13 +622,18 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
if type_sym.kind != .array_fixed {
|
if type_sym.kind != .array_fixed {
|
||||||
elem_sym := g.table.get_type_symbol(it.elem_type)
|
elem_sym := g.table.get_type_symbol(it.elem_type)
|
||||||
elem_type_str := g.typ(it.elem_type)
|
elem_type_str := g.typ(it.elem_type)
|
||||||
g.write('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str), ')
|
if it.exprs.len == 0 {
|
||||||
g.writeln('($elem_type_str[]){\t')
|
g.write('new_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str))')
|
||||||
for expr in it.exprs {
|
}
|
||||||
g.expr(expr)
|
else {
|
||||||
g.write(', ')
|
g.write('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str), ')
|
||||||
|
g.writeln('($elem_type_str[]){\t')
|
||||||
|
for expr in it.exprs {
|
||||||
|
g.expr(expr)
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
g.write('\n})')
|
||||||
}
|
}
|
||||||
g.write('\n})')
|
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -661,29 +696,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(it.val.str())
|
g.write(it.val.str())
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
mut name := it.name.replace('.', '__')
|
g.call_expr(it)
|
||||||
if name == 'exit' {
|
|
||||||
name = 'v_exit'
|
|
||||||
}
|
|
||||||
if it.is_c {
|
|
||||||
// Skip "C__"
|
|
||||||
g.is_c_call = true
|
|
||||||
name = name[3..]
|
|
||||||
}
|
|
||||||
g.write('${name}(')
|
|
||||||
if name == 'println' && it.args[0].typ != table.string_type_idx {
|
|
||||||
// `println(int_str(10))`
|
|
||||||
// sym := g.table.get_type_symbol(it.args[0].typ)
|
|
||||||
styp := g.typ(it.args[0].typ)
|
|
||||||
g.write('${styp}_str(')
|
|
||||||
g.expr(it.args[0].expr)
|
|
||||||
g.write('))')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g.call_args(it.args)
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
g.is_c_call = false
|
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
// g.write('/*cast*/')
|
// g.write('/*cast*/')
|
||||||
|
@ -1561,6 +1574,13 @@ fn (g mut Gen) write_init_function() {
|
||||||
g.writeln('void _vinit() {')
|
g.writeln('void _vinit() {')
|
||||||
g.writeln(g.inits.str())
|
g.writeln(g.inits.str())
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
if g.autofree {
|
||||||
|
g.writeln('void _vcleanup() {')
|
||||||
|
g.writeln('puts("cleaning up...");')
|
||||||
|
g.writeln('free(os__args.data);')
|
||||||
|
g.writeln('free(strconv__ftoa__powers_of_10.data);')
|
||||||
|
g.writeln('}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) write_str_definitions() {
|
fn (g mut Gen) write_str_definitions() {
|
||||||
|
@ -1737,13 +1757,13 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
}
|
}
|
||||||
// TODO: fix match, sum type false positive
|
// TODO: fix match, sum type false positive
|
||||||
// match node.expr_types[i] {
|
// match node.expr_types[i] {
|
||||||
// table.string_type {
|
// table.string_type {
|
||||||
// g.write('%.*s')
|
// g.write('%.*s')
|
||||||
// }
|
// }
|
||||||
// table.int_type {
|
// table.int_type {
|
||||||
// g.write('%d')
|
// g.write('%d')
|
||||||
// }
|
// }
|
||||||
// else {}
|
// else {}
|
||||||
// }
|
// }
|
||||||
if node.expr_types[i] == table.string_type {
|
if node.expr_types[i] == table.string_type {
|
||||||
g.write('%.*s')
|
g.write('%.*s')
|
||||||
|
@ -1802,6 +1822,59 @@ fn (g mut Gen) gen_filter(node ast.MethodCallExpr) {
|
||||||
g.write(tmp)
|
g.write(tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) call_expr(it ast.CallExpr) {
|
||||||
|
mut name := it.name.replace('.', '__')
|
||||||
|
if name == 'exit' {
|
||||||
|
name = 'v_exit'
|
||||||
|
}
|
||||||
|
if name == 'free' {
|
||||||
|
name = 'v_free'
|
||||||
|
}
|
||||||
|
is_print := name == 'println'
|
||||||
|
if it.is_c {
|
||||||
|
// Skip "C__"
|
||||||
|
g.is_c_call = true
|
||||||
|
name = name[3..]
|
||||||
|
}
|
||||||
|
// Generate tmp vars for values that have to be freed.
|
||||||
|
mut tmps := []string
|
||||||
|
/*
|
||||||
|
for arg in it.args {
|
||||||
|
if arg.typ == table.string_type_idx || is_print {
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
tmps << tmp
|
||||||
|
g.write('string $tmp = ')
|
||||||
|
g.expr(arg.expr)
|
||||||
|
g.writeln('; //memory')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if is_print && it.args[0].typ != table.string_type_idx {
|
||||||
|
styp := g.typ(it.args[0].typ)
|
||||||
|
if g.autofree {
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
// tmps << tmp
|
||||||
|
g.write('string $tmp = ${styp}_str(')
|
||||||
|
g.expr(it.args[0].expr)
|
||||||
|
g.writeln('); println($tmp); string_free($tmp); //MEM2')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// `println(int_str(10))`
|
||||||
|
// sym := g.table.get_type_symbol(it.args[0].typ)
|
||||||
|
g.write('println(${styp}_str(')
|
||||||
|
g.expr(it.args[0].expr)
|
||||||
|
g.write('))')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.write('${name}(')
|
||||||
|
g.call_args(it.args)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
g.is_c_call = false
|
||||||
|
}
|
||||||
|
|
||||||
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
|
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
|
||||||
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
||||||
is_str := right.elem_type == table.string_type
|
is_str := right.elem_type == table.string_type
|
||||||
|
|
|
@ -189,6 +189,7 @@ byte g_str_buf[1024];
|
||||||
int load_so(byteptr);
|
int load_so(byteptr);
|
||||||
void reload_so();
|
void reload_so();
|
||||||
void _vinit();
|
void _vinit();
|
||||||
|
void _vcleanup();
|
||||||
|
|
||||||
// ============== wyhash ==============
|
// ============== wyhash ==============
|
||||||
// Author: Wang Yi
|
// Author: Wang Yi
|
||||||
|
|
|
@ -177,6 +177,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
rec_mut: rec_mut
|
rec_mut: rec_mut
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
no_body: no_body
|
no_body: no_body
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue