From 8d241cc1646414accab7627c7647656309ac980f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 25 Nov 2019 08:38:00 +0300 Subject: [PATCH] vweb fixes; ORM fixes; freeing strings --- vlib/builtin/builtin_nix.v | 4 +- vlib/compiler/comptime.v | 17 +++++--- vlib/compiler/expression.v | 1 + vlib/compiler/fn.v | 3 +- vlib/compiler/main.v | 3 +- vlib/compiler/parser.v | 82 ++++++++++++++++++++++---------------- 6 files changed, 65 insertions(+), 45 deletions(-) diff --git a/vlib/builtin/builtin_nix.v b/vlib/builtin/builtin_nix.v index 35950b50d0..dd09c9352c 100644 --- a/vlib/builtin/builtin_nix.v +++ b/vlib/builtin/builtin_nix.v @@ -47,10 +47,8 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool { println('TODO: print_backtrace_skipping_top_frames_linux $skipframes with tcc fails tests with "stack smashing detected" .') return false } - $if !android { + $if !android { // backtrace is not available on Android. $if glibc { - // backtrace is not available on Android. - //if C.backtrace_symbols_fd != 0 { buffer := [100]byteptr nr_ptrs := C.backtrace(*voidptr(buffer), 100) nr_actual_frames := nr_ptrs-skipframes diff --git a/vlib/compiler/comptime.v b/vlib/compiler/comptime.v index e3ca37a294..2ed22c5533 100644 --- a/vlib/compiler/comptime.v +++ b/vlib/compiler/comptime.v @@ -174,8 +174,8 @@ fn (p mut Parser) comp_time() { p.is_vweb = false p.genln('/////////////////// tmpl end') receiver := p.cur_fn.args[0] - dot := if receiver.is_mut { '->' } else { '.' } - p.genln('vweb__Context_html($receiver.name $dot vweb, tmpl_res)') + dot := if receiver.is_mut || receiver.ptr { '->' } else { '.' } + p.genln('vweb__Context_html($receiver.name /*!*/$dot vweb, tmpl_res)') } else { p.error('bad comptime expr') @@ -261,16 +261,23 @@ fn (p mut Parser) comptime_method_call(typ Type) { p.cgen.cur_line = '' p.check(.dollar) var := p.check_name() + mut j := 0 for i, method in typ.methods { if method.typ != 'void' { + continue } receiver := method.args[0] - amp := if receiver.is_mut { '&' } else { '' } - if i > 0 { + if !p.expr_var.ptr { + p.error('`$p.expr_var.name` needs to be a reference') + } + amp := if receiver.is_mut && !p.expr_var.ptr { '&' } else { '' } + if j > 0 { p.gen(' else ') } - p.gen('if ( string_eq($var, _STR("$method.name")) ) ${typ.name}_$method.name($amp $p.expr_var.name);') + p.genln('if ( string_eq($var, _STR("$method.name")) ) ' + + '${typ.name}_$method.name($amp $p.expr_var.name);') + j++ } p.check(.lpar) p.check(.rpar) diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index db4b29a88f..21b159e75a 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -445,6 +445,7 @@ fn (p mut Parser) expression() string { is_num := typ.contains('*') || is_number_type(typ) p.check_space(p.tok) if is_str && tok_op == .plus && !p.is_js { + p.is_alloc = true p.cgen.set_placeholder(ph, 'string_add(') p.gen(',') } diff --git a/vlib/compiler/fn.v b/vlib/compiler/fn.v index d87f3dca24..33fd18c377 100644 --- a/vlib/compiler/fn.v +++ b/vlib/compiler/fn.v @@ -1000,7 +1000,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) { } } p.expected_type = arg.typ - clone := p.pref.autofree && arg.typ == 'string' && arg.is_moved && p.mod != 'builtin' + clone := p.pref.autofree && p.mod != 'string' && arg.typ == 'string' && + !p.builtin_mod //&& arg.is_moved if clone { p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(') } diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 69fd26cd00..e29932fecb 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -502,6 +502,7 @@ pub fn (v mut V) generate_main() { else if v.table.main_exists() { v.gen_main_start(true) cgen.genln(' main__main();') + cgen.genln('free(g_str_buf);') v.gen_main_end('return 0') } } @@ -876,7 +877,7 @@ pub fn new_v(args[]string) &V { if args.len < 2 { dir = '' } - + // build mode mut build_mode := BuildMode.default_mode mut mod := '' diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 71d0d517f7..f530c9dd27 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -296,7 +296,7 @@ pub fn (p mut Parser) save_state() ParserState { } pub fn (p mut Parser) restore_state(state ParserState) { - p.scanner.line_nr = state.scanner_line_nr + p.scanner.line_nr = state.scanner_line_nr p.scanner.text = state.scanner_text p.scanner.pos = state.scanner_pos p.scanner.line_ends = state.scanner_line_ends @@ -1111,36 +1111,13 @@ fn (p mut Parser) close_scope() { mut i := p.var_idx - 1 for ; i >= 0; i-- { v := p.local_vars[i] - if v.scope_level != p.cur_fn.scope_level { - break + if p.pref.autofree && (v.is_alloc || (v.is_arg && v.typ == 'string')) { // && !p.pref.is_test { + p.free_var(v) } - // Clean up memory, only do this if -autofree was passed for now - if p.pref.autofree && v.is_alloc { // && !p.pref.is_test { - mut free_fn := 'free' - if v.typ.starts_with('array_') { - free_fn = 'v_array_free' - } else if v.typ == 'string' { - free_fn = 'v_string_free' - //if p.fileis('str.v') { - //println('freeing str $v.name') - //} - continue - } else if v.ptr || v.typ.ends_with('*') { - free_fn = 'v_ptr_free' - //continue - } else { - continue - } - if p.returns { - // Don't free a variable that's being returned - if !v.is_returned && v.typ != 'FILE*' { //!v.is_c { - prev_line := p.cgen.lines[p.cgen.lines.len-2] - p.cgen.lines[p.cgen.lines.len-2] = - '$free_fn($v.name); /* :) close_scope free $v.typ */' + prev_line - } - } else { - p.genln('$free_fn($v.name); // close_scope free') - } + //if p.fileis('mem.v') { + //println(v.name + ' $v.is_arg scope=$v.scope_level cur=$p.cur_fn.scope_level')} + if v.scope_level != p.cur_fn.scope_level {// && !v.is_arg { + break } } if p.cur_fn.defer_text.last() != '' { @@ -1153,6 +1130,37 @@ fn (p mut Parser) close_scope() { // println('close_scope new var_idx=$f.var_idx\n') } +fn (p mut Parser) free_var(v Var) { + // Clean up memory, only do this if -autofree was passed for now + //if p.fileis('mem.v') {println('free_var() $v.name')} + mut free_fn := 'free' + if v.typ.starts_with('array_') { + free_fn = 'v_array_free' + } else if v.typ == 'string' { + free_fn = 'v_string_free' + //if p.fileis('str.v') { + //println('freeing str $v.name') + //} + //continue + } else if v.ptr || v.typ.ends_with('*') { + free_fn = 'v_ptr_free' + //continue + } else { + return + } + if p.returns { + // Don't free a variable that's being returned + if !v.is_returned && v.typ != 'FILE*' { //!v.is_c { + prev_line := p.cgen.lines[p.cgen.lines.len-2] + p.cgen.lines[p.cgen.lines.len-2] = + '$free_fn($v.name); /* :) close_scope free $v.typ */' + prev_line + } + } else { + //if p.fileis('mem.v') {println(v.name)} + p.genln('$free_fn($v.name); // close_scope free') + } +} + fn (p mut Parser) genln(s string) { p.cgen.genln(s) } @@ -1567,11 +1575,13 @@ fn (p mut Parser) get_var_type(name string, is_ptr bool, deref_nr int) string { p.gen('*') } } + /* if p.pref.autofree && v.typ == 'string' && v.is_arg && p.assigned_type == 'string' { p.warn('setting moved ' + v.typ) p.mark_arg_moved(v) } + */ mut typ := p.var_expr(v) // *var if deref_nr > 0 { @@ -1691,12 +1701,14 @@ fn (p mut Parser) var_expr(v Var) string { p.next() return p.select_query(fn_ph) } - if typ == 'pg__DB' && !p.fileis('pg.v') && p.peek() == .name && - !p.tokens[p.token_idx].lit.contains('exec') + if typ == 'pg__DB' && !p.fileis('pg.v') && p.peek() == .name { - p.next() - p.insert_query(fn_ph) - return 'void' + name := p.tokens[p.token_idx].lit + if !name.contains('exec') && !name.starts_with('q_') { + p.next() + p.insert_query(fn_ph) + return 'void' + } } // println('dot #$dc') typ = p.dot(typ, fn_ph)