1
0
Fork 0
Little S-Expression Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sxpf/eval_test.go

97 lines
2.4 KiB

//-----------------------------------------------------------------------------
// Copyright (c) 2022 Detlef Stern
//
// This file is part of sxpf.
//
// sxpf is licensed under the latest version of the EUPL // (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package sxpf_test
import (
"bytes"
"testing"
"codeberg.org/t73fde/sxpf"
)
func TestEvaluate(t *testing.T) {
testcases := []struct {
src string
exp string
}{
{"a", "A"},
{`"a"`, `"a"`},
{"(CAT a b)", `"AB"`},
{"(QUOTE ((A b) c))", "((A B) C)"},
{"(CAT a b)", `"AB"`},
}
env := newTestEnv()
for i, tc := range testcases {
expr, err := sxpf.ParseString(env, tc.src)
if err != nil {
t.Error(err)
continue
}
val, err := sxpf.Eval(env, expr)
if err != nil {
t.Error(err)
continue
}
got, err := sxpf.Repr(val)
if err != nil {
t.Error(err)
continue
}
if got != tc.exp {
t.Errorf("%d: %v should evaluate to %v, but got: %v", i, tc.src, tc.exp, got)
}
}
}
type testEnv struct {
smk sxpf.SymbolMaker
symMap *sxpf.SymbolMap
}
func newTestEnv() *testEnv {
smk := sxpf.NewTrivialSymbolMaker()
env := testEnv{smk: smk}
symMap := sxpf.NewSymbolMap(smk, nil)
for _, form := range testForms {
symMap.Set(env.MakeSymbol(form.Name()), form)
}
env.symMap = symMap
return &env
}
var testForms = []*sxpf.Builtin{
sxpf.NewBuiltin(
"CAT",
false, 0, -1,
func(_ sxpf.Environment, args *sxpf.Pair, _ int) (sxpf.Value, error) {
var buf bytes.Buffer
for arg := args; !sxpf.IsNil(arg); arg = arg.GetTail() {
arg.GetFirst().Print(&buf)
}
return sxpf.NewString(buf.String()), nil
},
),
sxpf.NewBuiltin(
"QUOTE",
true, 1, 1,
func(_ sxpf.Environment, args *sxpf.Pair, _ int) (sxpf.Value, error) {
return args.GetFirst(), nil
},
),
}
func (te *testEnv) MakeSymbol(s string) *sxpf.Symbol { return te.smk.MakeSymbol(s) }
func (te *testEnv) LookupForm(sym *sxpf.Symbol) (sxpf.Form, error) { return te.symMap.LookupForm(sym) }
func (*testEnv) EvalSymbol(sym *sxpf.Symbol) (sxpf.Value, error) { return sym, nil }
func (*testEnv) EvalOther(val sxpf.Value) (sxpf.Value, error) { return val, nil }
func (te *testEnv) EvalPair(p *sxpf.Pair) (sxpf.Value, error) {
return sxpf.EvalCallOrSeq(te, p)
}