free arrays when they are out of scope

main.v: update help
pull/1257/head
Alexander Medvednikov 2019-07-21 12:43:47 +02:00
parent 385f1c856e
commit 40c31f701f
5 changed files with 53 additions and 35 deletions

View File

@ -46,23 +46,6 @@ fn (f mut Fn) open_scope() {
f.scope_level++
}
fn (f mut Fn) close_scope() {
// println('close_scope level=$f.scope_level var_idx=$f.var_idx')
// Move back `var_idx` (pointer to the end of the array) till we reach the previous scope level.
// This effectivly deletes (closes) current scope.
mut i := f.var_idx - 1
for; i >= 0; i-- {
v := f.local_vars[i]
if v.scope_level != f.scope_level {
// println('breaking. "$v.name" v.scope_level=$v.scope_level')
break
}
}
f.var_idx = i + 1
// println('close_scope new var_idx=$f.var_idx\n')
f.scope_level--
}
fn (f &Fn) mark_var_used(v Var) {
for i, vv in f.local_vars {
if vv.name == v.name {
@ -432,19 +415,11 @@ fn (p mut Parser) check_unused_variables() {
p.scanner.line_nr = var.line_nr - 1
p.error('`$var.name` declared and not used')
}
// Very basic automatic memory management at the end of the function.
// This is inserted right before the final `}`, so if the object is being returned,
// the free method will not be called.
if p.pref.is_test && var.typ.contains('array_') {
// p.genln('v_${var.typ}_free($var.name); // !!!! XAXA')
// p.genln('free(${var.name}.data); // !!!! XAXA')
}
}
}
// Important function with 5 args.
// user.say_hi() => "User_say_hi(user)"
// method_ph - where to insert "user_say_hi("
// user.register() => "User_register(user)"
// method_ph - where to insert "user_register("
// receiver_var - "user" (needed for pthreads)
// receiver_type - "User"
fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type string) {

View File

@ -977,7 +977,7 @@ fn new_v(args[]string) *V {
if os.dir_exists(vroot) && os.dir_exists(vroot + '/vlib/builtin') {
} else {
println('vlib not found. It should be next to V executable. ')
println('vlib not found. It should be next to the V executable. ')
println('Go to https://vlang.io to install V.')
exit(1)
}

View File

@ -27,6 +27,7 @@ mut:
is_global bool // __global (translated from C only)
is_used bool
scope_level int
is_alloc bool
}
struct Parser {
@ -69,6 +70,7 @@ mut:
attr string
v_script bool // "V bash", import all os functions into global space
var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization
building_v bool
}
const (
@ -96,6 +98,9 @@ fn (c mut V) new_parser(path string, run Pass) Parser {
os: c.os
run: run
vroot: c.vroot
building_v: !c.pref.is_repl && (path.contains('compiler/') ||
path.contains('v/vlib'))
}
p.next()
// p.scanner.debug_tokens()
@ -214,8 +219,9 @@ fn (p mut Parser) parse() {
// $if, $else
p.comp_time()
case Token.key_global:
if !p.pref.translated && !p.pref.is_live && !p.builtin_pkg && !p.building_v() {
//p.error('__global is only allowed in translated code')
if !p.pref.translated && !p.pref.is_live &&
!p.builtin_pkg && !p.building_v {
p.error('__global is only allowed in translated code')
}
p.next()
name := p.check_name()
@ -988,10 +994,35 @@ fn (p mut Parser) statements_no_curly_end() string {
}
//p.fmt_dec()
// println('close scope line=$p.scanner.line_nr')
p.cur_fn.close_scope()
p.close_scope()
return last_st_typ
}
fn (p mut Parser) close_scope() {
// println('close_scope level=$f.scope_level var_idx=$f.var_idx')
// Move back `var_idx` (pointer to the end of the array) till we reach the previous scope level.
// This effectivly deletes (closes) current scope.
mut i := p.cur_fn.var_idx - 1
for; i >= 0; i-- {
v := p.cur_fn.local_vars[i]
if v.scope_level != p.cur_fn.scope_level {
// println('breaking. "$v.name" v.scope_level=$v.scope_level')
break
}
if !p.building_v && !v.is_mut && v.is_alloc {
if v.typ.starts_with('array_') {
p.genln('v_array_free($v.name); // close_scope free')
}
else {
p.genln('free($v.name); // close_scope free')
}
}
}
p.cur_fn.var_idx = i + 1
// println('close_scope new var_idx=$f.var_idx\n')
p.cur_fn.scope_level--
}
fn (p mut Parser) genln(s string) {
p.cgen.genln(s)
}
@ -1221,6 +1252,7 @@ fn (p mut Parser) var_decl() {
name: name
typ: typ
is_mut: is_mut
is_alloc: typ.starts_with('array_')
})
mut cgen_typ := typ
if !or_else {
@ -3115,7 +3147,7 @@ fn (p mut Parser) for_st() {
p.check(.lcbr)
p.genln('')
p.statements()
p.cur_fn.close_scope()
p.close_scope()
p.for_expr_cnt--
}
@ -3228,7 +3260,7 @@ fn (p mut Parser) return_st() {
else {
ret := p.cgen.cur_line.right(ph)
p.cgen(p.cur_fn.defer_text)
if expr_type == 'void*' {
if p.cur_fn.defer_text == '' || expr_type == 'void*' {
p.cgen.resetln('return $ret')
} else {
tmp := p.get_tmp()
@ -3369,10 +3401,12 @@ fn is_compile_time_const(s string) bool {
return true
}
/*
fn (p &Parser) building_v() bool {
cur_dir := os.getwd()
return p.file_path.contains('v/compiler') || cur_dir.contains('v/compiler')
}
*/
fn (p mut Parser) attribute() {
p.check(.lsbr)

View File

@ -5,13 +5,15 @@
module builtin
struct array {
is_slice bool
pub:
// Using a void pointer allows to implement arrays without generics and without generating
// extra code for every type.
pub:
data voidptr
len int
cap int
element_size int
}
// Private function, used by V (`nums := []int`)
@ -144,6 +146,7 @@ pub fn (s array) slice(start, _end int) array {
data: s.data + start * s.element_size
len: l
cap: l
is_slice: true
}
return res
}
@ -215,7 +218,11 @@ pub fn (a []int) str() string {
return res
}
pub fn (a []int) free() {
//pub fn (a []int) free() {
pub fn (a array) free() {
if a.is_slice {
return
}
C.free(a.data)
}

View File

@ -716,12 +716,14 @@ pub fn (s string) free() {
C.free(s.str)
}
/*
fn (arr []string) free() {
for s in arr {
s.free()
}
C.free(arr.data)
}
*/
// all_before('23:34:45.234', '.') == '23:34:45'
pub fn (s string) all_before(dot string) string {