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]`)
 | ||||
| fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array { | ||||
| 	cap_ := if cap == 0 { 1 } else { cap } | ||||
| 
 | ||||
| 	arr := array{ | ||||
| 		len: len | ||||
| 		cap: cap | ||||
|  | @ -377,7 +378,9 @@ pub fn (a []int) str() string { | |||
| 	mut sb := strings.new_builder(a.len * 13) | ||||
| 	sb.write('[') | ||||
| 	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 { | ||||
| 			sb.write(', ') | ||||
| 		} | ||||
|  |  | |||
|  | @ -2809,6 +2809,13 @@ fn (p mut Parser) array_init() string { | |||
| 	p.gen_array_init(real, no_alloc, new_arr_ph, i) | ||||
| 	typ = 'array_${stringify_pointer(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 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,11 @@ fn C.symlink(charptr, charptr) int | |||
| 
 | ||||
| fn init_os_args(argc int, argv &byteptr) []string { | ||||
| 	mut args := []string | ||||
| 	//mut args := []string(make(0, argc, sizeof(string)))
 | ||||
| 	//mut args := []string{len:argc}
 | ||||
| 	for i in 0 .. argc { | ||||
| 
 | ||||
| 		//args [i] = string(argv[i])
 | ||||
| 		args << string(argv[i]) | ||||
| 	} | ||||
| 	return args | ||||
|  |  | |||
|  | @ -153,6 +153,7 @@ pub: | |||
| 	rec_mut       bool // is receiver mutable
 | ||||
| 	is_c          bool | ||||
| 	no_body       bool // just a definition `fn C.malloc()`
 | ||||
| 	pos           token.Position | ||||
| } | ||||
| 
 | ||||
| pub struct BranchStmt { | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ struct Gen { | |||
| 	inits          strings.Builder // contents of `void _vinit(){}`
 | ||||
| 	table          &table.Table | ||||
| mut: | ||||
| 	file           ast.File | ||||
| 	fn_decl        &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
 | ||||
| 	tmp_count      int | ||||
| 	varaidic_args  map[string]int | ||||
|  | @ -26,6 +27,7 @@ mut: | |||
| 	inside_ternary bool // ?: comma separated statements on a single line
 | ||||
| 	stmt_start_pos int | ||||
| 	right_is_opt   bool | ||||
| 	autofree       bool | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 		table: table | ||||
| 		fn_decl: 0 | ||||
| 		autofree: true | ||||
| 	} | ||||
| 	g.init() | ||||
| 	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.write_variadic_types() | ||||
|  | @ -498,6 +507,9 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { | |||
| 		if name == 'exit' { | ||||
| 			name = 'v_exit' | ||||
| 		} | ||||
| 		if name == 'free' { | ||||
| 			name = 'v_free' | ||||
| 		} | ||||
| 		// type_name := g.table.type_to_str(it.return_type)
 | ||||
| 		type_name := g.typ(it.return_type) | ||||
| 		g.write('$type_name ${name}(') | ||||
|  | @ -528,13 +540,31 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { | |||
| 	} | ||||
| 	if is_main { | ||||
| 		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);') | ||||
| 	} | ||||
| 	for stmt in it.stmts { | ||||
| 		// g.write('\t')
 | ||||
| 		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 g.autofree { | ||||
| 			g.writeln('_vcleanup();') | ||||
| 		} | ||||
| 		g.writeln('return 0;') | ||||
| 	} | ||||
| 	g.writeln('}') | ||||
|  | @ -592,13 +622,18 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 			if type_sym.kind != .array_fixed { | ||||
| 				elem_sym := g.table.get_type_symbol(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), ') | ||||
| 				g.writeln('($elem_type_str[]){\t') | ||||
| 				for expr in it.exprs { | ||||
| 					g.expr(expr) | ||||
| 					g.write(', ') | ||||
| 				if it.exprs.len == 0 { | ||||
| 					g.write('new_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str))') | ||||
| 				} | ||||
| 				else { | ||||
| 					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 {} | ||||
| 		} | ||||
|  | @ -661,29 +696,7 @@ fn (g mut Gen) expr(node ast.Expr) { | |||
| 			g.write(it.val.str()) | ||||
| 		} | ||||
| 		ast.CallExpr { | ||||
| 			mut name := it.name.replace('.', '__') | ||||
| 			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 | ||||
| 			g.call_expr(it) | ||||
| 		} | ||||
| 		ast.CastExpr { | ||||
| 			// g.write('/*cast*/')
 | ||||
|  | @ -1561,6 +1574,13 @@ fn (g mut Gen) write_init_function() { | |||
| 	g.writeln('void _vinit() {') | ||||
| 	g.writeln(g.inits.str()) | ||||
| 	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() { | ||||
|  | @ -1737,13 +1757,13 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) { | |||
| 		} | ||||
| 		// TODO: fix match, sum type false positive
 | ||||
| 		// match node.expr_types[i] {
 | ||||
| 		// 	table.string_type {
 | ||||
| 		// 		g.write('%.*s')
 | ||||
| 		// 	}
 | ||||
| 		// 	table.int_type {
 | ||||
| 		// 		g.write('%d')
 | ||||
| 		// 	}
 | ||||
| 		// 	else {}
 | ||||
| 		// table.string_type {
 | ||||
| 		// g.write('%.*s')
 | ||||
| 		// }
 | ||||
| 		// table.int_type {
 | ||||
| 		// g.write('%d')
 | ||||
| 		// }
 | ||||
| 		// else {}
 | ||||
| 		// }
 | ||||
| 		if node.expr_types[i] == table.string_type { | ||||
| 			g.write('%.*s') | ||||
|  | @ -1802,6 +1822,59 @@ fn (g mut Gen) gen_filter(node ast.MethodCallExpr) { | |||
| 	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`
 | ||||
| fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) { | ||||
| 	is_str := right.elem_type == table.string_type | ||||
|  |  | |||
|  | @ -189,6 +189,7 @@ byte g_str_buf[1024]; | |||
| int load_so(byteptr); | ||||
| void reload_so(); | ||||
| void _vinit(); | ||||
| void _vcleanup(); | ||||
| 
 | ||||
| // ============== wyhash ==============
 | ||||
| //	Author: Wang Yi
 | ||||
|  |  | |||
|  | @ -177,6 +177,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | |||
| 		rec_mut: rec_mut | ||||
| 		is_c: is_c | ||||
| 		no_body: no_body | ||||
| 		pos: p.tok.position() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue