1
0
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:
joe-conigliaro 2020-04-21 13:23:36 +10:00 committed by GitHub
parent ee2e83fef0
commit abf5942433
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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