diff --git a/eval.go b/eval.go index f9fdcda..c11a9d6 100644 --- a/eval.go +++ b/eval.go @@ -2,10 +2,8 @@ package main import ( "bufio" - "errors" "fmt" "io" - "reflect" ) func eval(v interface{}, env *environment) (interface{}, error) { @@ -14,40 +12,10 @@ func eval(v interface{}, env *environment) (interface{}, error) { } switch t := v.(type) { - case symbol: - debugPrint("eval symbol") - s, err := env.get(t) - if err != nil { - return nil, err - } - return eval(s, env) - + return t.eval(env) case *sexp: - debugPrint("eval sexp") - if t.len() == 0 { - return nil, errors.New("illegal evaluation of empty sexp ()") - } - - if t.quotelvl > 0 { - return t, nil - } - - // eval the first item - v, err := eval(t.items[0], env) - if err != nil { - return nil, err - } - - c, ok := v.(callable) - if !ok { - return nil, fmt.Errorf(`expected special form or builtin procedure, received %v`, reflect.TypeOf(v)) - } - if len(t.items) > 1 { - return c.call(env, t.items[1:]) - } - return c.call(env, nil) - + return t.eval(env) default: debugPrint("default eval") return v, nil @@ -83,7 +51,6 @@ func (i interpreter) run(env *environment) { v, err := parse(i.tokens) switch err { case io.EOF: - fmt.Println("EOF lol") return case nil: i.eval(v, env) diff --git a/skeam.go b/skeam.go index aefdf88..cf4d8c9 100644 --- a/skeam.go +++ b/skeam.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "reflect" "strconv" "strings" ) @@ -17,6 +18,32 @@ type sexp struct { quotelvl int } +func (s *sexp) eval(env *environment) (interface{}, error) { + debugPrint("eval sexp") + if s.len() == 0 { + return nil, errors.New("illegal evaluation of empty sexp ()") + } + + if s.quotelvl > 0 { + return s, nil + } + + // eval the first item + v, err := eval(s.items[0], env) + if err != nil { + return nil, err + } + + c, ok := v.(callable) + if !ok { + return nil, fmt.Errorf(`expected special form or builtin procedure, received %v`, reflect.TypeOf(v)) + } + if len(s.items) > 1 { + return c.call(env, s.items[1:]) + } + return c.call(env, nil) +} + type callable interface { call(*environment, []interface{}) (interface{}, error) } @@ -46,6 +73,15 @@ func (s sexp) len() int { type symbol string +func (s symbol) eval(env *environment) (interface{}, error) { + debugPrint("eval symbol") + v, err := env.get(s) + if err != nil { + return nil, err + } + return eval(v, env) +} + var universe = &environment{map[symbol]interface{}{ // predefined values "#t": true,