implemented set!

master
Jordan Orelli 12 years ago
parent ec5cbdcaab
commit ba1bab1e39

@ -24,3 +24,8 @@ func (e environment) get(key symbol) (interface{}, error) {
func (e environment) set(key symbol, val interface{}) { func (e environment) set(key symbol, val interface{}) {
e[key] = val e[key] = val
} }
func (e environment) defined(key symbol) bool {
_, ok := e[key]
return ok
}

@ -12,8 +12,8 @@
"jordan" "jordan"
; booleans. I don't like the look of #t and #f. They're dumb. ; booleans. I don't like the look of #t and #f. They're dumb.
true #t
false #f
; ------------------------------------------------------------------------------ ; ------------------------------------------------------------------------------
; basic math ; basic math
@ -30,9 +30,10 @@ false
(define x 5) (define x 5)
x x
(set! x "steve")
x
(quote 1 2 3) (quote 1 2 3)
(if 1 2 3) (if #f (quote "true-value") (quote "false-value"))
(if false 2 3) (if #t (quote "true-value") (quote "false-value"))
(if true 2 3)

@ -21,8 +21,8 @@ func (s sexp) String() string {
type symbol string type symbol string
var universe = &environment{ var universe = &environment{
"true": true, "#t": true,
"false": false, "#f": false,
"+": proc(addition), "+": proc(addition),
"-": proc(subtraction), "-": proc(subtraction),
"*": proc(multiplication), "*": proc(multiplication),
@ -30,6 +30,7 @@ var universe = &environment{
"define": special(define), "define": special(define),
"quote": special(quote), "quote": special(quote),
"if": special(_if), "if": special(_if),
"set!": special(set),
} }
// parses the string lexeme into a value that can be eval'd // parses the string lexeme into a value that can be eval'd
@ -183,7 +184,9 @@ func evalall(c chan token, env *environment) {
fmt.Println("error:", err) fmt.Println("error:", err)
return return
} else { } else {
fmt.Println(v) if v != nil {
fmt.Println(v)
}
} }
default: default:
fmt.Println("error in eval: %v", err) fmt.Println("error in eval: %v", err)

@ -15,7 +15,11 @@ func define(env *environment, args ...interface{}) (interface{}, error) {
if !ok { if !ok {
return nil, fmt.Errorf(`first argument to *define* must be symbol, received %v`, reflect.TypeOf(args[0])) return nil, fmt.Errorf(`first argument to *define* must be symbol, received %v`, reflect.TypeOf(args[0]))
} }
env.set(s, args[1]) v, err := eval(args[1], env)
if err != nil {
return nil, err
}
env.set(s, v)
return nil, nil return nil, nil
} }
@ -36,3 +40,22 @@ func _if(env *environment, args ...interface{}) (interface{}, error) {
} }
return eval(args[1], env) return eval(args[1], env)
} }
func set(env *environment, args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, fmt.Errorf(`received %d arguments in *set!*, expected exactly 2`, len(args))
}
s, ok := args[0].(symbol)
if !ok {
return nil, fmt.Errorf(`first argument to *set!* must be symbol, received %v`, reflect.TypeOf(args[0]))
}
if !env.defined(s) {
return nil, fmt.Errorf(`cannot *set!* undefined symbol %v`, s)
}
v, err := eval(args[1], env)
if err != nil {
return nil, err
}
env.set(s, v)
return nil, nil
}

Loading…
Cancel
Save