parser: anonymous functions (part 1)
parent
fe249ab0c3
commit
73073cd954
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
pub type TypeDecl = AliasTypeDecl | SumTypeDecl | FnTypeDecl
|
pub type TypeDecl = AliasTypeDecl | SumTypeDecl | FnTypeDecl
|
||||||
|
|
||||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr | IndexExpr | RangeExpr | MatchExpr | CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | ConcatExpr | Type | AsCast | TypeOf | StringInterLiteral
|
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr | IndexExpr | RangeExpr | MatchExpr | CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | ConcatExpr | Type | AsCast | TypeOf | StringInterLiteral | AnonFn
|
||||||
|
|
||||||
pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | Comment | AssertStmt | UnsafeStmt | GoStmt | Block | InterfaceDecl
|
pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | Comment | AssertStmt | UnsafeStmt | GoStmt | Block | InterfaceDecl
|
||||||
|
|
||||||
|
@ -184,6 +184,13 @@ pub:
|
||||||
alias string
|
alias string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AnonFn {
|
||||||
|
pub:
|
||||||
|
decl FnDecl
|
||||||
|
mut:
|
||||||
|
typ table.Type
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
@ -193,11 +200,12 @@ pub:
|
||||||
is_deprecated bool
|
is_deprecated bool
|
||||||
is_pub bool
|
is_pub bool
|
||||||
is_variadic bool
|
is_variadic bool
|
||||||
|
is_anon bool
|
||||||
receiver Field
|
receiver Field
|
||||||
is_method bool
|
is_method bool
|
||||||
rec_mut bool // is receiver mutable
|
rec_mut bool // is receiver mutable
|
||||||
is_c bool
|
is_c bool
|
||||||
is_js bool
|
is_js bool
|
||||||
no_body bool // just a definition `fn C.malloc()`
|
no_body bool // just a definition `fn C.malloc()`
|
||||||
is_builtin bool // this function is defined in builtin/strconv
|
is_builtin bool // this function is defined in builtin/strconv
|
||||||
pos token.Position
|
pos token.Position
|
||||||
|
|
|
@ -1198,6 +1198,9 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||||
it.expr_type = c.expr(it.expr)
|
it.expr_type = c.expr(it.expr)
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
|
ast.AnonFn {
|
||||||
|
return it.typ
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
tnode := typeof(node)
|
tnode := typeof(node)
|
||||||
if tnode != 'unknown v.ast.Expr' {
|
if tnode != 'unknown v.ast.Expr' {
|
||||||
|
|
|
@ -248,8 +248,14 @@ pub fn (var g Gen) write_typedef_types() {
|
||||||
.function {
|
.function {
|
||||||
info := typ.info as table.FnType
|
info := typ.info as table.FnType
|
||||||
func := info.func
|
func := info.func
|
||||||
if !info.has_decl && !info.is_anon {
|
if !info.has_decl {
|
||||||
fn_name := if func.is_c { func.name.replace('.', '__') } else { c_name(func.name) }
|
fn_name := if func.is_c {
|
||||||
|
func.name.replace('.', '__')
|
||||||
|
} else if info.is_anon {
|
||||||
|
typ.name
|
||||||
|
} else {
|
||||||
|
c_name(func.name)
|
||||||
|
}
|
||||||
g.definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
g.definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
||||||
for i, arg in func.args {
|
for i, arg in func.args {
|
||||||
g.definitions.write(g.typ(arg.typ))
|
g.definitions.write(g.typ(arg.typ))
|
||||||
|
@ -1085,6 +1091,33 @@ fn (var g Gen) expr(node ast.Expr) {
|
||||||
ast.TypeOf {
|
ast.TypeOf {
|
||||||
g.typeof_expr(it)
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
fn_body := g.out.after(pos)
|
||||||
|
g.definitions.write(fn_body)
|
||||||
|
g.out.go_back(fn_body.len)
|
||||||
|
|
||||||
|
g.out.write('&${sym.name}_impl')
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// #printf("node=%d\n", node.typ);
|
// #printf("node=%d\n", node.typ);
|
||||||
println(term.red('cgen.expr(): bad node ' + typeof(node)))
|
println(term.red('cgen.expr(): bad node ' + typeof(node)))
|
||||||
|
|
|
@ -234,6 +234,58 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (var p Parser) anon_fn() ast.AnonFn {
|
||||||
|
pos := p.tok.position()
|
||||||
|
p.open_scope()
|
||||||
|
p.check(.key_fn)
|
||||||
|
|
||||||
|
// TODO generics
|
||||||
|
|
||||||
|
args, is_variadic := p.fn_args()
|
||||||
|
for arg in args {
|
||||||
|
p.scope.register(arg.name, ast.Var{
|
||||||
|
name: arg.name
|
||||||
|
typ: arg.typ
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var return_type := table.void_type
|
||||||
|
if p.tok.kind.is_start_of_type() {
|
||||||
|
return_type = p.parse_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
var stmts := []ast.Stmt
|
||||||
|
no_body := p.tok.kind != .lcbr
|
||||||
|
if p.tok.kind == .lcbr {
|
||||||
|
stmts = p.parse_block()
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
typ := table.new_type(idx)
|
||||||
|
name := p.table.get_type_name(typ)
|
||||||
|
|
||||||
|
return ast.AnonFn{
|
||||||
|
decl: ast.FnDecl{
|
||||||
|
name: name
|
||||||
|
stmts: stmts
|
||||||
|
return_type: return_type
|
||||||
|
args: args
|
||||||
|
is_variadic: is_variadic
|
||||||
|
is_method: false
|
||||||
|
is_anon: true
|
||||||
|
no_body: no_body
|
||||||
|
pos: pos
|
||||||
|
}
|
||||||
|
typ: typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
var args := []table.Arg
|
var args := []table.Arg
|
||||||
|
|
Loading…
Reference in New Issue