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
type Callable struct {
arity int
call func(*Interpreter, ...any) any
type Callable interface {
arity() int
call(i *Interpreter, args ...any) (ret any)
}
func newCallable(f *FunStmt) *Callable {
return &Callable{
arity: len(f.args),
call: func(i *Interpreter, args ...any) (ret any) {
type Function struct {
definition *FunStmt
closure *Environment
}
defer func() {
if err := recover(); err != nil {
re, ok := err.(Return)
func (f *Function) call(i *Interpreter, args ...any) (ret any) {
if !ok {
panic(err)
}
defer func() {
if err := recover(); err != nil {
re, ok := err.(Return)
ret = re.val
}
}()
env := newEnvironment(i.globals)
for idx, arg := range f.args {
env.define(arg.lexeme, args[idx])
if !ok {
panic(err)
}
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"
func defineGlobals(env *Environment) {
type ClockFun struct{}
env.define("clock", &Callable{
arity: 0,
call: func(i *Interpreter, arg ...any) any {
return time.Now().Unix()
},
})
func (cf *ClockFun) call(i *Interpreter, args ...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))
}
callable, ok := callee.(*Callable)
callable, ok := callee.(Callable)
if !ok {
i.panic(&RuntimeError{c.paren, "Can only call function and classes."})
}
if callable.arity != len(args) {
if callable.arity() != len(args) {
i.panic(&RuntimeError{
c.paren,
fmt.Sprintf(
"Expected %d arguments but got %d",
callable.arity,
callable.arity(),
len(args),
),
})
@ -192,7 +192,7 @@ func (i *Interpreter) visitCall(c *Call) any {
}
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) {

View file

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