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 struct AnonFn {
pub: pub:
decl FnDecl decl FnDecl
is_called bool
pub mut: pub mut:
typ table.Type typ table.Type
} }
@ -896,6 +895,9 @@ pub fn (expr Expr) is_blank_ident() bool {
pub fn (expr Expr) position() token.Position { pub fn (expr Expr) position() token.Position {
// all uncommented have to be implemented // all uncommented have to be implemented
match mut expr { match mut expr {
AnonFn {
return expr.decl.pos
}
ArrayInit { ArrayInit {
return expr.pos 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 f := table.Fn{}
mut found := false mut found := false
mut found_in_args := 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 // try prefix with current module as it would have never gotten prefixed
if !fn_name.contains('.') && call_expr.mod !in ['builtin'] { if !fn_name.contains('.') && call_expr.mod !in ['builtin'] {
name_prefixed := '${call_expr.mod}.$fn_name' 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.cur_fn = &node.decl
c.stmts(node.decl.stmts) c.stmts(node.decl.stmts)
c.cur_fn = keep_fn c.cur_fn = keep_fn
return if node.is_called { return node.typ
node.decl.return_type
} else {
node.typ
}
} }
ast.ArrayInit { ast.ArrayInit {
return c.array_init(mut node) return c.array_init(mut node)

View File

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

View File

@ -1210,18 +1210,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.write('{') g.write('{')
} }
ret_styp := g.typ(val.decl.return_type) 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) (') g.write('$ret_styp (*$ident.name) (')
def_pos := g.definitions.len def_pos := g.definitions.len
g.fn_args(val.decl.args, val.decl.is_variadic) g.fn_args(val.decl.args, val.decl.is_variadic)
g.definitions.go_back(g.definitions.len - def_pos) g.definitions.go_back(g.definitions.len - def_pos)
g.write(') = ') g.write(') = ')
g.expr(*val) g.expr(*val)
}
g.writeln(';') g.writeln(';')
if blank_assign { if blank_assign {
g.write('}') 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) { 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 { if node.should_be_skipped {
return return
} }

View File

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

View File

@ -166,6 +166,22 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
.key_fn { .key_fn {
// Anonymous function // Anonymous function
node = p.anon_fn() 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 return node
} }
else { 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) // Test assigning functions (IdentFn)
// //