Ejemplo n.º 1
0
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)
	}
}
Ejemplo n.º 2
0
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)
	}
}
Ejemplo n.º 3
0
func TestEnv(t *testing.T) {
	e1 := New(nil)

	Define(e1, &types.Symbol{"cows"}, &types.String{"moo"})
	Define(e1, &types.Symbol{"sheep"}, &types.String{"baa"})

	e2 := New(e1)

	Define(e2, &types.Symbol{"chickens"}, &types.String{"bawk"})
	Define(e2, &types.Symbol{"sheep"}, &types.String{"meh"})

	if r, _ := Get(e2, &types.Symbol{"sheep"}); !types.Eqv(r, &types.String{"meh"}) {
		t.Error("Sheep in e2 do not say 'meh'")
	}

	if r, _ := Get(e1, &types.Symbol{"sheep"}); !types.Eqv(r, &types.String{"baa"}) {
		t.Error("Sheep in e1 do not say 'baa': ", r.(*types.String).Value)
	}

	Define(e2, &types.Symbol{"sheep"}, &types.String{"baa"})

	if r, _ := Get(e2, &types.Symbol{"sheep"}); !types.Eqv(r, &types.String{"baa"}) {
		t.Error("Sheep in e2 do not say 'baa': ", r.(*types.String).Value)
	}
}
Ejemplo n.º 4
0
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)
	}
}
Ejemplo n.º 5
0
func Get(env *Environment, sym *types.Symbol) (types.Type, error) {
	for e := env; e != nil; e = e.parent {
		for v := e.env; v != nil; {
			testSym, err := types.Caar(v)
			if err != nil {
				return nil, &envError{fmt.Sprintf("Checking for %s", sym.Value), err}
			}

			if types.Eqv(sym, testSym) {
				if r, err := types.Cdar(v); err != nil {
					return nil, &envError{fmt.Sprintf("Checking for %s", sym.Value), err}
				} else {
					return r, nil
				}
			}

			nextV, _ := types.Cdr(v)

			var ok bool
			v, ok = nextV.(*types.Pair)
			if !ok {
				return nil, &envError{m: "Corrupt environment!!!"}
			}
		}
	}

	return nil, &envError{m: fmt.Sprintf("Unknown variable: %s", sym.Value)}
}
Ejemplo n.º 6
0
func TestIf(t *testing.T) {
	env := environment.New(nil)

	f, _ := parser.Parse(strings.NewReader("(if #t 'yes 'no)"))
	if a, err := Eval(env, f); err != nil {
		t.Error("Evaluating (if #t 'yes 'no) failed:", err)
	} else if !types.Eqv(a, &types.Symbol{"yes"}) {
		t.Error("result != yes", a)
	}

	f, _ = parser.Parse(strings.NewReader("(if #f 'yes 'no)"))
	if a, err := Eval(env, f); err != nil {
		t.Error("Evaluating (if #f 'yes 'no) failed:", err)
	} else if !types.Eqv(a, &types.Symbol{"no"}) {
		t.Error("result != no", a)
	}
}
Ejemplo n.º 7
0
func TestQuote(t *testing.T) {
	env := environment.New(nil)

	f, _ := parser.Parse(strings.NewReader("(quote moo)"))
	if a, err := Eval(env, f); err != nil {
		t.Error("Evaluating (quote moo) failed:", err)
	} else if !types.Eqv(a, &types.Symbol{"moo"}) {
		t.Error("(quote moo) != moo", a)
	}
}
Ejemplo n.º 8
0
func eqv(env interface{}, args t.Type) (t.Type, error) {
	first, _ := t.Car(args)

	for args, _ := t.Cdr(args); args != nil; args, _ = t.Cdr(args) {
		arg, _ := t.Car(args)

		if !t.Eqv(first, arg) {
			return &t.Bool{false}, nil
		}
	}
	return &t.Bool{true}, nil
}
Ejemplo n.º 9
0
func TestDefine(t *testing.T) {
	env := environment.New(nil)

	f, _ := parser.Parse(strings.NewReader("(define answer 42)"))
	if _, err := Eval(env, f); err != nil {
		t.Error("Evaluating (define answer 42) failed:", err)
	}

	if a, err := environment.Get(env, &types.Symbol{"answer"}); err != nil {
		t.Error("'Get'ting 'answer' caused an error: ", err)
	} else if !types.Eqv(a, &types.Number{42}) {
		t.Error("answer != 42", a)
	}
}
Ejemplo n.º 10
0
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)
	}
}
Ejemplo n.º 11
0
func TestParser(t *testing.T) {
	r, err := Parse(strings.NewReader("sym"))
	if err != nil {
		t.Error(err)
	} else if !types.Eqv(r, &types.Symbol{"sym"}) {
		t.Error("Expecting symbol, got", r)
	}

	str := "(moo (said the many) cows)"

	r, err = Parse(strings.NewReader(str))
	if err != nil {
		t.Error(err)
	} else if r.String() != str {
		t.Error("expected", str, "got", r)
	}

	str = "(moo (cows"

	r, err = Parse(strings.NewReader(str))
	if err == nil {
		t.Error("Expected parser error, got", r)
	}

	str = "(\"moo\" said the cows)"
	r, err = Parse(strings.NewReader(str))
	if err != nil {
		t.Error(err)
	} else if r.String() != str {
		t.Error("expected", str, "got", r)
	}

	str = "'(moo ())"
	expected := "(quote (moo #nil))"
	r, err = Parse(strings.NewReader(str))
	if err != nil {
		t.Error(err)
	} else if r.String() != expected {
		t.Error("expected", expected, "got", r)
	}

	str = "(+ 1 1)"
	expected = "(+ 1 1)"
	r, err = Parse(strings.NewReader(str))
	if err != nil {
		t.Error(err)
	} else if r.String() != expected {
		t.Error("expected", expected, "got", r)
	}
}
Ejemplo n.º 12
0
func equal_Number(env interface{}, args t.Type) (t.Type, error) {
	arg, _ := t.Car(args)
	first, ok := arg.(*t.Number)
	if !ok {
		return nil, fmt.Errorf("=: Not a number: %s", arg)
	}

	for args, _ := t.Cdr(args); args != nil; args, _ = t.Cdr(args) {
		arg, _ := t.Car(args)

		if !t.Eqv(first, arg) {
			return &t.Bool{false}, nil
		}
	}
	return &t.Bool{true}, nil
}
Ejemplo n.º 13
0
func TestFibonacci(t *testing.T) {
	env := BuildEnvironment()

	const funcString = "(define fib (lambda (a b max) (if (= 0 max) b (fib b (+ a b) (- max 1)))))"

	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)
	}

	const funcString2 = "(fib 0 1 10)"

	f, _ = parser.Parse(strings.NewReader(funcString2))
	if a, err := Eval(env, f); err != nil {
		t.Error("Evaluating", funcString2, "failed:", err)
	} else if !types.Eqv(a, &types.Number{89}) {
		t.Error(funcString2, "!= 89", a)
	}
}