parser/checker/gen: anon fn direct call with args

pull/5733/head
joe-conigliaro 2020-07-08 01:10:39 +10:00
parent f8a89e3f8f
commit 5fd5e558ae
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
8 changed files with 52 additions and 28 deletions

View File

@ -213,7 +213,6 @@ pub:
pub struct AnonFn {
pub:
decl FnDecl
is_called bool
pub mut:
typ table.Type
}
@ -896,6 +895,9 @@ pub fn (expr Expr) is_blank_ident() bool {
pub fn (expr Expr) position() token.Position {
// all uncommented have to be implemented
match mut expr {
AnonFn {
return expr.decl.pos
}
ArrayInit {
return expr.pos
}

View File

@ -1014,6 +1014,16 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
mut f := table.Fn{}
mut found := false
mut found_in_args := false
// anon fn direct call
if call_expr.left is ast.AnonFn {
// it was set to anon for checker errors, clear for gen
call_expr.name = ''
c.expr(call_expr.left)
anon_fn := call_expr.left as ast.AnonFn
anon_fn_sym := c.table.get_type_symbol(anon_fn.typ)
f = (anon_fn_sym.info as table.FnType).func
found = true
}
// try prefix with current module as it would have never gotten prefixed
if !fn_name.contains('.') && call_expr.mod !in ['builtin'] {
name_prefixed := '${call_expr.mod}.$fn_name'
@ -2072,11 +2082,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
c.cur_fn = &node.decl
c.stmts(node.decl.stmts)
c.cur_fn = keep_fn
return if node.is_called {
node.decl.return_type
} else {
node.typ
}
return node.typ
}
ast.ArrayInit {
return c.array_init(mut node)

View File

@ -701,9 +701,6 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
match node {
ast.AnonFn {
f.fn_decl(node.decl)
if node.is_called {
f.write('()')
}
}
ast.ArrayInit {
f.array_init(node)

View File

@ -1210,18 +1210,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.write('{')
}
ret_styp := g.typ(val.decl.return_type)
if val.is_called {
g.write('$ret_styp $ident.name = ')
g.expr(*val)
g.write('()')
} else {
g.write('$ret_styp (*$ident.name) (')
def_pos := g.definitions.len
g.fn_args(val.decl.args, val.decl.is_variadic)
g.definitions.go_back(g.definitions.len - def_pos)
g.write(') = ')
g.expr(*val)
}
g.write('$ret_styp (*$ident.name) (')
def_pos := g.definitions.len
g.fn_args(val.decl.args, val.decl.is_variadic)
g.definitions.go_back(g.definitions.len - def_pos)
g.write(') = ')
g.expr(*val)
g.writeln(';')
if blank_assign {
g.write('}')

View File

@ -241,6 +241,11 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) ([]string, []string)
}
fn (mut g Gen) call_expr(node ast.CallExpr) {
// NOTE: everything could be done this way
// see my comment in parser near anon_fn
if node.left is ast.AnonFn {
g.expr(node.left)
}
if node.should_be_skipped {
return
}

View File

@ -355,12 +355,6 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
return_type: return_type
}
name := 'anon_${p.tok.pos}_$func.signature()'
mut is_called := false
if p.tok.kind == .lpar {
is_called = true
p.check(.lpar)
p.check(.rpar)
}
func.name = name
idx := p.table.find_or_register_fn_type(p.mod, func, true, false)
typ := table.new_type(idx)
@ -379,7 +373,6 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
pos: pos
file: p.file_name
}
is_called: is_called
typ: typ
}
}

View File

@ -166,6 +166,22 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
.key_fn {
// Anonymous function
node = p.anon_fn()
// its a call
// NOTE: this could be moved to just before the pratt loop
// then anything can be a call, eg. `index[2]()` or `stuct.field()`
// but this would take a bit of modification
if p.tok.kind == .lpar {
p.next()
pos := p.tok.position()
args := p.call_args()
p.check(.rpar)
node = ast.CallExpr{
name: 'anon'
left: node
args: args
pos: pos
}
}
return node
}
else {

View File

@ -101,6 +101,17 @@ fn test_anon_fn() {
})
}
fn test_anon_fn_direct_call() {
fn(name string) {
println('hello $name')
}('from anon')
b := fn(n int) int {
return 11+n
}(100)
assert b == 111
}
//
// Test assigning functions (IdentFn)
//