parser,fmt: implement `[manualfree] module abc` for opting out *all* fns in a given .v from autofree
parent
083dc23db8
commit
46a5c487c1
|
@ -7,7 +7,7 @@
|
||||||
- `byte.str()` has been fixed and works like with all other numbers. `byte.ascii_str()` has been added.
|
- `byte.str()` has been fixed and works like with all other numbers. `byte.ascii_str()` has been added.
|
||||||
- Smart cast in for loops: `for mut x is string {}`.
|
- Smart cast in for loops: `for mut x is string {}`.
|
||||||
- `[noinit]` struct attribute to disallow direct struct initialization with `Foo{}`.
|
- `[noinit]` struct attribute to disallow direct struct initialization with `Foo{}`.
|
||||||
- `[manualfree]` attribute for functions, that want to do their own memory management.
|
- support `[manualfree] fn f1(){}` and `[manualfree] module m1`, for functions doing their own memory management.
|
||||||
|
|
||||||
## V 0.2.1
|
## V 0.2.1
|
||||||
*30 Dec 2020*
|
*30 Dec 2020*
|
||||||
|
|
|
@ -131,6 +131,7 @@ pub fn (e &SelectorExpr) root_ident() Ident {
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
attrs []table.Attr
|
||||||
pos token.Position
|
pos token.Position
|
||||||
is_skipped bool // module main can be skipped in single file programs
|
is_skipped bool // module main can be skipped in single file programs
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,7 @@ pub fn (mut f Fmt) mod(mod ast.Module) {
|
||||||
if mod.is_skipped {
|
if mod.is_skipped {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
f.attrs(mod.attrs)
|
||||||
f.writeln('module $mod.name\n')
|
f.writeln('module $mod.name\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[manualfree]
|
||||||
|
module main
|
||||||
|
|
||||||
|
fn abc() {
|
||||||
|
x := 'abc should be autofreed'
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
[manualfree]
|
||||||
|
fn xyz() {
|
||||||
|
x := 'xyz should do its own memory management'
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
abc()
|
||||||
|
xyz()
|
||||||
|
}
|
|
@ -156,7 +156,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
|
||||||
fn (mut p Parser) fn_decl() ast.FnDecl {
|
fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
p.top_level_statement_start()
|
p.top_level_statement_start()
|
||||||
start_pos := p.tok.position()
|
start_pos := p.tok.position()
|
||||||
is_manualfree := p.attrs.contains('manualfree')
|
is_manualfree := p.is_manualfree || p.attrs.contains('manualfree')
|
||||||
is_deprecated := p.attrs.contains('deprecated')
|
is_deprecated := p.attrs.contains('deprecated')
|
||||||
is_direct_arr := p.attrs.contains('direct_array_access')
|
is_direct_arr := p.attrs.contains('direct_array_access')
|
||||||
mut is_unsafe := p.attrs.contains('unsafe')
|
mut is_unsafe := p.attrs.contains('unsafe')
|
||||||
|
|
|
@ -45,6 +45,7 @@ mut:
|
||||||
or_is_handled bool // ignore `or` in this expression
|
or_is_handled bool // ignore `or` in this expression
|
||||||
builtin_mod bool // are we in the `builtin` module?
|
builtin_mod bool // are we in the `builtin` module?
|
||||||
mod string // current module name
|
mod string // current module name
|
||||||
|
is_manualfree bool // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree
|
||||||
attrs []table.Attr // attributes before next decl stmt
|
attrs []table.Attr // attributes before next decl stmt
|
||||||
expr_mod string // for constructing full type names in parse_type()
|
expr_mod string // for constructing full type names in parse_type()
|
||||||
scope &ast.Scope
|
scope &ast.Scope
|
||||||
|
@ -817,10 +818,12 @@ fn (mut p Parser) attributes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) parse_attr() table.Attr {
|
fn (mut p Parser) parse_attr() table.Attr {
|
||||||
|
apos := p.prev_tok.position()
|
||||||
if p.tok.kind == .key_unsafe {
|
if p.tok.kind == .key_unsafe {
|
||||||
p.next()
|
p.next()
|
||||||
return table.Attr{
|
return table.Attr{
|
||||||
name: 'unsafe'
|
name: 'unsafe'
|
||||||
|
pos: apos.extend(p.tok.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut is_ctdefine := false
|
mut is_ctdefine := false
|
||||||
|
@ -862,6 +865,7 @@ fn (mut p Parser) parse_attr() table.Attr {
|
||||||
is_ctdefine: is_ctdefine
|
is_ctdefine: is_ctdefine
|
||||||
arg: arg
|
arg: arg
|
||||||
is_string_arg: is_string_arg
|
is_string_arg: is_string_arg
|
||||||
|
pos: apos.extend(p.tok.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1670,10 +1674,16 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) module_decl() ast.Module {
|
fn (mut p Parser) module_decl() ast.Module {
|
||||||
|
mut module_attrs := []table.Attr{}
|
||||||
|
if p.tok.kind == .lsbr {
|
||||||
|
p.attributes()
|
||||||
|
module_attrs = p.attrs
|
||||||
|
}
|
||||||
mut name := 'main'
|
mut name := 'main'
|
||||||
is_skipped := p.tok.kind != .key_module
|
is_skipped := p.tok.kind != .key_module
|
||||||
mut module_pos := token.Position{}
|
mut module_pos := token.Position{}
|
||||||
if !is_skipped {
|
if !is_skipped {
|
||||||
|
p.attrs = []
|
||||||
module_pos = p.tok.position()
|
module_pos = p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
mut pos := p.tok.position()
|
mut pos := p.tok.position()
|
||||||
|
@ -1710,8 +1720,22 @@ fn (mut p Parser) module_decl() ast.Module {
|
||||||
}
|
}
|
||||||
p.mod = full_mod
|
p.mod = full_mod
|
||||||
p.builtin_mod = p.mod == 'builtin'
|
p.builtin_mod = p.mod == 'builtin'
|
||||||
|
if !is_skipped {
|
||||||
|
for ma in module_attrs {
|
||||||
|
match ma.name {
|
||||||
|
'manualfree' {
|
||||||
|
p.is_manualfree = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.error_with_pos('unknown module attribute `[$ma.name]`', ma.pos)
|
||||||
|
return ast.Module{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return ast.Module{
|
return ast.Module{
|
||||||
name: full_mod
|
name: full_mod
|
||||||
|
attrs: module_attrs
|
||||||
is_skipped: is_skipped
|
is_skipped: is_skipped
|
||||||
pos: module_pos
|
pos: module_pos
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module table
|
module table
|
||||||
|
|
||||||
|
import v.token
|
||||||
|
|
||||||
// e.g. `[unsafe]`
|
// e.g. `[unsafe]`
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
pub:
|
pub:
|
||||||
|
@ -11,6 +13,7 @@ pub:
|
||||||
is_ctdefine bool // [if name]
|
is_ctdefine bool // [if name]
|
||||||
arg string // [name: arg]
|
arg string // [name: arg]
|
||||||
is_string_arg bool // [name: 'arg']
|
is_string_arg bool // [name: 'arg']
|
||||||
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
// no square brackets
|
// no square brackets
|
||||||
|
|
Loading…
Reference in New Issue