This commit is contained in:
Greg 2024-10-12 00:09:25 +03:00
parent 1fdd522c8f
commit 1117f2c104
4 changed files with 65 additions and 36 deletions

View file

@ -1,36 +1,44 @@
package main package main
type Callable struct { type Callable interface {
arity int arity() int
call func(*Interpreter, ...any) any call(i *Interpreter, args ...any) (ret any)
} }
func newCallable(f *FunStmt) *Callable { type Function struct {
return &Callable{ definition *FunStmt
arity: len(f.args), closure *Environment
call: func(i *Interpreter, args ...any) (ret any) { }
defer func() { func (f *Function) call(i *Interpreter, args ...any) (ret any) {
if err := recover(); err != nil {
re, ok := err.(Return)
if !ok { defer func() {
panic(err) if err := recover(); err != nil {
} re, ok := err.(Return)
ret = re.val if !ok {
} panic(err)
}()
env := newEnvironment(i.globals)
for idx, arg := range f.args {
env.define(arg.lexeme, args[idx])
} }
i.executeBlock(f.body, env) ret = re.val
}
}()
return nil env := newEnvironment(f.closure)
},
for idx, arg := range f.definition.args {
env.define(arg.lexeme, args[idx])
} }
i.executeBlock(f.definition.body, env)
return nil
}
func (f *Function) arity() int {
return len(f.definition.args)
}
func newFunction(fun *FunStmt, env *Environment) Callable {
return &Function{fun, env}
} }

View file

@ -2,12 +2,16 @@ package main
import "time" import "time"
func defineGlobals(env *Environment) { type ClockFun struct{}
env.define("clock", &Callable{ func (cf *ClockFun) call(i *Interpreter, args ...any) any {
arity: 0, return time.Now().Unix()
call: func(i *Interpreter, arg ...any) any { }
return time.Now().Unix()
}, func (cf *ClockFun) arity() int {
}) return 0
}
func defineGlobals(env *Environment) {
env.define("clock", &ClockFun{})
} }

View file

@ -171,18 +171,18 @@ func (i *Interpreter) visitCall(c *Call) any {
args = append(args, i.evaluate(arg)) args = append(args, i.evaluate(arg))
} }
callable, ok := callee.(*Callable) callable, ok := callee.(Callable)
if !ok { if !ok {
i.panic(&RuntimeError{c.paren, "Can only call function and classes."}) i.panic(&RuntimeError{c.paren, "Can only call function and classes."})
} }
if callable.arity != len(args) { if callable.arity() != len(args) {
i.panic(&RuntimeError{ i.panic(&RuntimeError{
c.paren, c.paren,
fmt.Sprintf( fmt.Sprintf(
"Expected %d arguments but got %d", "Expected %d arguments but got %d",
callable.arity, callable.arity(),
len(args), len(args),
), ),
}) })
@ -192,7 +192,7 @@ func (i *Interpreter) visitCall(c *Call) any {
} }
func (i *Interpreter) visitFunStmt(f *FunStmt) { func (i *Interpreter) visitFunStmt(f *FunStmt) {
i.env.define(f.name.lexeme, newCallable(f)) i.env.define(f.name.lexeme, newFunction(f, i.env))
} }
func (i *Interpreter) visitReturnStmt(r *ReturnStmt) { func (i *Interpreter) visitReturnStmt(r *ReturnStmt) {

View file

@ -41,4 +41,21 @@ fun fib(n) {
for (var i = 1; i <= 10; i = i + 1) { for (var i = 1; i <= 10; i = i + 1) {
print fib(i); print fib(i);
} }
fun makeCounter() {
var i = 0;
fun incr() {
i = i + 1;
print i;
}
return incr;
}
var counter = makeCounter();
counter();
counter();