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

vweb fixes; ORM fixes; freeing strings

This commit is contained in:
Alexander Medvednikov 2019-11-25 08:38:00 +03:00
parent bac3c0a63e
commit 8d241cc164
6 changed files with 65 additions and 45 deletions

View File

@ -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

View File

@ -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)

View File

@ -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(',')
}

View File

@ -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(')
}

View File

@ -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 := ''

View File

@ -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)