func Eval(sc *scheme.Scope, e scheme.Sexpr) (scheme.Sexpr, error) { //e = transform(sc, e) switch e := e.(type) { case *scheme.Cons: cons := e car, err := Eval(sc, cons.Car) if err != nil { return nil, err } if !isFunction(car) && !isPrim(car) { return nil, evalError("Attempted application on non-function") } cdr := cons.Cdr args, err := scheme.Flatten(cdr) if err != nil { return nil, err } if isPrim(car) { return car.(*scheme.Primitive).Procedure()(sc, args) } f := car.(*scheme.Function).Procedure() for i, a := range args { args[i], err = Eval(sc, a) if err != nil { return nil, err } } return f(sc, args) case *scheme.Symbol: return sc.Lookup(e) } return e, nil }
func let(s *scheme.Scope, ss []scheme.Sexpr) (scheme.Sexpr, error) { if len(ss) < 1 { return nil, scheme.ProcError("let requires at least one argument") } evalScope := scheme.NewScope(s) bindings, err := scheme.Flatten(ss[0]) if err != nil { return nil, err } for _, b := range bindings { bs, err := scheme.Flatten(b) if err != nil { return nil, err } if len(bs) != 2 { return nil, scheme.ProcError("invalid binding on let") } sym, ok := bs[0].(*scheme.Symbol) if !ok { return nil, scheme.ProcError("invalid binding on let") } val, err := eval.Eval(s, bs[1]) if err != nil { return nil, err } evalScope.Define(sym, val) } prog := ss[1:] var last scheme.Sexpr = scheme.Nil for _, l := range prog { last, err = eval.Eval(evalScope, l) if err != nil { return nil, err } } return last, nil }