diff --git a/env.go b/env.go index 3c715e6..12a6ae5 100644 --- a/env.go +++ b/env.go @@ -20,3 +20,7 @@ func (e environment) get(key symbol) (interface{}, error) { } return nil, UnknownSymbolError{key} } + +func (e environment) set(key symbol, val interface{}) { + e[key] = val +} diff --git a/skeam.go b/skeam.go index 4600ff1..dfcb65d 100644 --- a/skeam.go +++ b/skeam.go @@ -16,14 +16,12 @@ type sexp []interface{} type symbol string -var universe = environment{ - "int": int64(5), - "float": float64(3.14), - "string": "Jordan", +var universe = &environment{ "+": proc(addition), "-": proc(subtraction), "*": proc(multiplication), "/": proc(division), + "define": special(define), } // parses the string lexeme into a value that can be eval'd @@ -95,7 +93,7 @@ func parse(c chan token) (interface{}, error) { return nil, io.EOF } -func eval(v interface{}, env environment) (interface{}, error) { +func eval(v interface{}, env *environment) (interface{}, error) { switch t := v.(type) { case symbol: @@ -112,16 +110,26 @@ func eval(v interface{}, env environment) (interface{}, error) { return nil, errors.New("illegal evaluation of empty sexp ()") } + // get first element as symbol s, ok := t[0].(symbol) if !ok { return nil, errors.New("expected a symbol") } + // resolve symbol v, err := env.get(s) if err != nil { return nil, err } + if spec, ok := v.(special); ok { + if len(t) > 1 { + return spec(env, t[1:]...) + } else { + return spec(env) + } + } + p, ok := v.(proc) if !ok { return nil, fmt.Errorf("expected proc, found %v", reflect.TypeOf(v)) @@ -156,7 +164,7 @@ func eval(v interface{}, env environment) (interface{}, error) { return nil, nil } -func evalall(c chan token, env environment) { +func evalall(c chan token, env *environment) { for { v, err := parse(c) switch err {