mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser/cgen: anon fn var & calling (#4534)
This commit is contained in:
parent
ee2e83fef0
commit
abf5942433
@ -1341,6 +1341,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||
return table.string_type
|
||||
}
|
||||
ast.AnonFn {
|
||||
c.stmts(it.decl.stmts)
|
||||
return it.typ
|
||||
}
|
||||
else {
|
||||
@ -1441,7 +1442,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
||||
}
|
||||
// Function object (not a call), e.g. `onclick(my_click)`
|
||||
if func := c.table.find_fn(name) {
|
||||
fn_type := table.new_type(c.table.find_or_register_fn_type(func, true))
|
||||
fn_type := table.new_type(c.table.find_or_register_fn_type(func, false, true))
|
||||
ident.name = name
|
||||
ident.kind = .function
|
||||
ident.info = ast.IdentFn{
|
||||
|
@ -269,7 +269,7 @@ pub fn (mut g Gen) write_typedef_types() {
|
||||
.function {
|
||||
info := typ.info as table.FnType
|
||||
func := info.func
|
||||
if !info.has_decl {
|
||||
if !info.has_decl && !info.is_anon {
|
||||
fn_name := if func.is_c {
|
||||
func.name.replace('.', '__')
|
||||
} else if info.is_anon {
|
||||
@ -762,6 +762,18 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
or_stmts = it.or_block.stmts
|
||||
return_type = it.return_type
|
||||
}
|
||||
ast.AnonFn {
|
||||
g.expr(*it)
|
||||
// TODO: no buffer fiddling
|
||||
fsym := g.table.get_type_symbol(it.typ)
|
||||
ret_styp := g.typ(it.decl.return_type)
|
||||
g.write('$ret_styp (*$ident.name) (')
|
||||
def_pos := g.definitions.len
|
||||
g.fn_args(it.decl.args, it.decl.is_variadic)
|
||||
g.definitions.go_back(g.definitions.len - def_pos)
|
||||
g.writeln(') = &${fsym.name};')
|
||||
continue
|
||||
}
|
||||
else {}
|
||||
}
|
||||
gen_or := is_call && table.type_is(return_type, .optional)
|
||||
@ -1104,28 +1116,14 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.typeof_expr(it)
|
||||
}
|
||||
ast.AnonFn {
|
||||
sym := g.table.get_type_symbol(it.typ)
|
||||
func := it.decl
|
||||
// TODO: Fix hack and write function implementation directly to definitions
|
||||
// TODO: dont fiddle with buffers
|
||||
pos := g.out.len
|
||||
type_name := g.typ(func.return_type)
|
||||
g.write('$type_name ${sym.name}_impl(')
|
||||
g.fn_args(func.args, func.is_variadic)
|
||||
g.writeln(') {')
|
||||
g.stmts(func.stmts)
|
||||
if g.autofree {
|
||||
g.free_scope_vars(func.pos.pos - 1)
|
||||
}
|
||||
if g.defer_stmts.len > 0 {
|
||||
g.write_defer_stmts()
|
||||
}
|
||||
g.out.writeln('}')
|
||||
g.defer_stmts = []
|
||||
g.fn_decl = 0
|
||||
def_pos := g.definitions.len
|
||||
g.stmt(it.decl)
|
||||
fn_body := g.out.after(pos)
|
||||
g.definitions.go_back(g.definitions.len - def_pos)
|
||||
g.definitions.write(fn_body)
|
||||
g.out.go_back(fn_body.len)
|
||||
g.out.write('&${sym.name}_impl')
|
||||
}
|
||||
else {
|
||||
// #printf("node=%d\n", node.typ);
|
||||
|
@ -238,7 +238,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
|
||||
fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||
pos := p.tok.position()
|
||||
p.open_scope()
|
||||
// p.open_scope()
|
||||
p.check(.key_fn)
|
||||
// TODO generics
|
||||
args, is_variadic := p.fn_args()
|
||||
@ -257,15 +257,17 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||
if p.tok.kind == .lcbr {
|
||||
stmts = p.parse_block()
|
||||
}
|
||||
p.close_scope()
|
||||
// p.close_scope()
|
||||
func := table.Fn{
|
||||
args: args
|
||||
is_variadic: is_variadic
|
||||
return_type: return_type
|
||||
}
|
||||
idx := p.table.find_or_register_fn_type(func, false)
|
||||
name := 'anon_${p.tok.pos}_$func.signature()'
|
||||
func.name = name
|
||||
idx := p.table.find_or_register_fn_type(func, true, false)
|
||||
typ := table.new_type(idx)
|
||||
name := p.table.get_type_name(typ)
|
||||
//name := p.table.get_type_name(typ)
|
||||
return ast.AnonFn{
|
||||
decl: ast.FnDecl{
|
||||
name: name
|
||||
|
@ -80,7 +80,7 @@ pub fn (p mut Parser) parse_fn_type(name string) table.Type {
|
||||
is_variadic: is_variadic
|
||||
return_type: return_type
|
||||
}
|
||||
idx := p.table.find_or_register_fn_type(func, false)
|
||||
idx := p.table.find_or_register_fn_type(func, false, false)
|
||||
return table.new_type(idx)
|
||||
}
|
||||
|
||||
|
@ -390,14 +390,13 @@ pub fn (var t Table) find_or_register_multi_return(mr_typs []Type) int {
|
||||
return t.register_type_symbol(mr_type)
|
||||
}
|
||||
|
||||
pub fn (var t Table) find_or_register_fn_type(f Fn, has_decl bool) int {
|
||||
is_anon := f.name.len == 0
|
||||
name := if is_anon { 'anon_fn_$f.signature()' } else { f.name }
|
||||
pub fn (var t Table) find_or_register_fn_type(f Fn, is_anon bool, has_decl bool) int {
|
||||
name := if f.name.len == 0 { 'anon_fn_$f.signature()' } else { f.name }
|
||||
return t.register_type_symbol(TypeSymbol{
|
||||
kind: .function
|
||||
name: name
|
||||
info: FnType{
|
||||
is_anon: is_anon
|
||||
is_anon: f.name.len == 0 || is_anon
|
||||
has_decl: has_decl
|
||||
func: f
|
||||
}
|
||||
|
@ -125,6 +125,16 @@ fn test_fns() {
|
||||
}
|
||||
|
||||
fn test_anon_fn() {
|
||||
f1 := fn(a int){
|
||||
println('hello from f1')
|
||||
}
|
||||
|
||||
f1(1)
|
||||
f2 := fn(a int){
|
||||
println('hello from f2')
|
||||
}
|
||||
|
||||
f2(1)
|
||||
/*
|
||||
high_fn(fn (x int) int {
|
||||
println('hello')
|
||||
@ -165,3 +175,4 @@ fn test_fn_type_call() {
|
||||
st1 := &MySt{f:test}
|
||||
assert st1.f(10) == 1010
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user