parser/checker/gen: anon fn direct call with args
parent
f8a89e3f8f
commit
5fd5e558ae
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.write('$ret_styp $ident.name = ')
|
def_pos := g.definitions.len
|
||||||
g.expr(*val)
|
g.fn_args(val.decl.args, val.decl.is_variadic)
|
||||||
g.write('()')
|
g.definitions.go_back(g.definitions.len - def_pos)
|
||||||
} else {
|
g.write(') = ')
|
||||||
g.write('$ret_styp (*$ident.name) (')
|
g.expr(*val)
|
||||||
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(';')
|
g.writeln(';')
|
||||||
if blank_assign {
|
if blank_assign {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue