func TestLambda(t *testing.T) { env := environment.New(nil) environment.Define(env, &types.Symbol{"+"}, &types.Builtin{add}) environment.Define(env, &types.Symbol{"begin"}, &types.Builtin{begin}) f, _ := parser.Parse(strings.NewReader("(lambda (n) n)")) if a, err := Eval(env, f); err != nil { t.Error("Evaluating lambda failed:", err, f) } else if !types.IsSFunction(a) { t.Error("Evaluating lambda didn't return an SFunction:", a) } f, _ = parser.Parse(strings.NewReader("(define add1 (lambda (n) (+ 1 n)))")) if _, err := Eval(env, f); err != nil { t.Error("Evaluating define lambda failed:", err) } if a, err := environment.Get(env, &types.Symbol{"add1"}); err != nil { t.Error("'Get'ting add1 caused an error: ", err) } else if !types.IsSFunction(a) { t.Error("add1 is not an SFunction:", a) } f, _ = parser.Parse(strings.NewReader("(add1 1)")) if a, err := Eval(env, f); err != nil { t.Error("Evaluating (add1 1) failed:", err) } else if !types.Eqv(a, &types.Number{2}) { t.Error("(add1 1) != 2", a) } }
func TestScoping(t *testing.T) { env := environment.New(nil) environment.Define(env, &types.Symbol{"begin"}, &types.Builtin{begin}) environment.Define(env, &types.Symbol{"+"}, &types.Builtin{add}) funcString := "(begin (define a 0) (define get-num ((lambda (a b) (define c 4) (lambda (b) (+ a b c))) 1 2)))" f, err := parser.Parse(strings.NewReader(funcString)) if err != nil { t.Error("Parsing funcString failed:", err) } if _, err := Eval(env, f); err != nil { t.Error("Evaluating funcString failed:", err) } f, _ = parser.Parse(strings.NewReader("a")) if a, err := Eval(env, f); err != nil { t.Error("Evaluating 'a' failed:", err) } else if !types.Eqv(a, &types.Number{0}) { t.Error("a != 0", a) } f, _ = parser.Parse(strings.NewReader("(get-num 8)")) if a, err := Eval(env, f); err != nil { t.Error("Evaluating (get-num) failed:", err) } else if !types.Eqv(a, &types.Number{13}) { t.Error("(get-num 8) != 13:", a) } }
func TestEval(t *testing.T) { env := environment.New(nil) environment.Define(env, &types.Symbol{"everything"}, &types.Number{42}) environment.Define(env, &types.Symbol{"cows"}, &types.String{"moo"}) environment.Define(env, &types.Symbol{"sheep"}, &types.String{"baa"}) environment.Define(env, &types.Symbol{"+"}, &types.Builtin{add}) if r, _ := Eval(env, &types.Symbol{"everything"}); !types.Eqv(r, &types.Number{42}) { t.Error("Var 'everything' != 42: ", r) } f, _ := parser.Parse(strings.NewReader("(+ 1 1)")) if r, err := Eval(env, f); err != nil { t.Error("Evaluating (+ 1 1) caused an error: ", err) } else if !types.Eqv(r, &types.Number{2}) { t.Error("(+ 1 1) != 2: ", r) } f, _ = parser.Parse(strings.NewReader("(+ 1 (+ 2 3))")) if r, err := Eval(env, f); err != nil { t.Error("Evaluating (+ 1 (+ 2 3)) caused an error: ", err) } else if !types.Eqv(r, &types.Number{6}) { t.Error("(+ 1 (+ 2 3)) != 6: ", r) } }
func TestBegin(t *testing.T) { env := environment.New(nil) environment.Define(env, &types.Symbol{"cows"}, &types.String{"moo"}) environment.Define(env, &types.Symbol{"sheep"}, &types.String{"baa"}) environment.Define(env, &types.Symbol{"begin"}, &types.Builtin{begin}) f, _ := parser.Parse(strings.NewReader("(begin cows sheep)")) if r, err := Eval(env, f); err != nil { t.Error("Evaluating (begin cows sheep) caused an error: ", err) } else if !types.Eqv(r, &types.String{"baa"}) { t.Error("(begin cows sheep) != baa", r) } }
func BuildEnvironment() (env *e.Environment) { var defFunc func(string, func(interface{}, t.Type) (t.Type, error)) defFunc = func(name string, fn func(interface{}, t.Type) (t.Type, error)) { e.Define(env, &t.Symbol{name}, &t.Builtin{fn}) } env = e.New(nil) defFunc("begin", begin) /* Pairs */ defFunc("cons", cons) defFunc("car", car) defFunc("cdr", cdr) /* Arithmetic */ defFunc("+", add) defFunc("-", sub) defFunc("=", equal_Number) /* General */ defFunc("eq?", eq) defFunc("eqv?", eqv) return }
func define(env *environment.Environment, args types.Type) error { name, err := types.Car(args) if err != nil { return err } value, err := types.Cadr(args) if err != nil { return err } evaldValue, err := Eval(env, value) if err != nil { return err } environment.Define(env, name.(*types.Symbol), evaldValue) return nil }