can now add numbers

master
Jordan Orelli 12 years ago
parent 7eedbb4e92
commit 39286ce998

@ -15,6 +15,7 @@ type environment map[symbol]interface{}
func (e environment) get(key symbol) (interface{}, error) { func (e environment) get(key symbol) (interface{}, error) {
v, ok := e[key] v, ok := e[key]
if ok { if ok {
debugPrint(fmt.Sprintf(`found key "%v": %v`, key, v))
return v, nil return v, nil
} }
return nil, UnknownSymbolError{key} return nil, UnknownSymbolError{key}

@ -78,7 +78,7 @@ func isDigit(r rune) bool {
func debugPrint(s string) { func debugPrint(s string) {
if DEBUG { if DEBUG {
fmt.Println(s) fmt.Println("#", s)
} }
} }

@ -0,0 +1,40 @@
package main
import (
"fmt"
"reflect"
)
type proc func(...interface{}) (interface{}, error)
func addition(vals ...interface{}) (interface{}, error) {
addFloats := false
var accf float64
var acc int64
for _, raw := range vals {
switch v := raw.(type) {
case int64:
if addFloats {
accf += float64(v)
} else {
acc += v
}
case float64:
if !addFloats {
addFloats = true
accf += float64(acc)
}
accf += v
default:
return nil, fmt.Errorf("addition is not defined for %v", reflect.TypeOf(v))
}
}
if addFloats {
return accf, nil
} else {
return acc, nil
}
panic("not reached")
}

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"reflect"
"strconv" "strconv"
) )
@ -19,6 +20,7 @@ var universe = environment{
"int": 5, "int": 5,
"float": 3.14, "float": 3.14,
"string": "Jordan", "string": "Jordan",
"+": proc(addition),
} }
// parses the string lexeme into a value that can be eval'd // parses the string lexeme into a value that can be eval'd
@ -90,18 +92,65 @@ func parse(c chan token) (interface{}, error) {
return nil, io.EOF return nil, io.EOF
} }
func eval(v interface{}, env environment) error { func eval(v interface{}, env environment) (interface{}, error) {
switch t := v.(type) { switch t := v.(type) {
case symbol: case symbol:
debugPrint("eval symbol")
s, err := env.get(t) s, err := env.get(t)
if err != nil { if err != nil {
return err return nil, err
} }
return eval(s, env) return eval(s, env)
case sexp:
debugPrint("eval sexp")
if len(t) == 0 {
return nil, errors.New("illegal evaluation of empty sexp ()")
}
s, ok := t[0].(symbol)
if !ok {
return nil, errors.New("expected a symbol")
}
v, err := env.get(s)
if err != nil {
return nil, err
}
p, ok := v.(proc)
if !ok {
return nil, fmt.Errorf("expected proc, found %v", reflect.TypeOf(v))
}
if len(t) > 1 {
args := make([]interface{}, 0, len(t)-1)
for _, raw := range t[1:] {
v, err := eval(raw, env)
if err != nil {
return nil, err
}
args = append(args, v)
}
inner, err := p(args...)
if err != nil {
return nil, err
}
return eval(inner, env)
}
inner, err := p()
if err != nil {
return nil, err
}
return eval(inner, env)
default: default:
fmt.Println(v) return v, nil
} }
return nil return nil, nil
} }
func evalall(c chan token, env environment) { func evalall(c chan token, env environment) {
@ -111,8 +160,10 @@ func evalall(c chan token, env environment) {
case io.EOF: case io.EOF:
return return
case nil: case nil:
if err := eval(v, env); err != nil { if v, err := eval(v, env); err != nil {
fmt.Println("error:", err) fmt.Println("error:", err)
} else {
fmt.Println(v)
} }
default: default:
fmt.Println("error in eval: %v", err) fmt.Println("error in eval: %v", err)
@ -135,6 +186,9 @@ func args() {
} }
func main() { func main() {
if DEBUG {
fmt.Println(universe)
}
if len(os.Args) > 1 { if len(os.Args) > 1 {
args() args()
return return

Loading…
Cancel
Save