Skip to content

Commit

Permalink
Drop the use of '(let )'
Browse files Browse the repository at this point in the history
This was something we removed examples of in #12, but we didn't
actually remove the code.  Do that here, and close #100.
  • Loading branch information
skx committed Nov 21, 2022
1 parent 32b9052 commit 005a953
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 76 deletions.
21 changes: 4 additions & 17 deletions eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,6 @@ func TestEvaluate(t *testing.T) {
// gensym - just test that there's an 11 character return
{"(length (split (str (gensym)) \"\"))", "11"},

// Let
{"(let ((a 5)) (nil? a))", "#f"},
{"(let ((a 5)) a)", "5"},
{"(let ((a 5) (b 6)) a (* a b))", "30"},
{"(let ((a 5)) (set! a 44) a)", "44"},
{"(let ((a 5)) c)", "nil"},
{"(let ((a 3) (b (+ a 3))) b))", "6"},

// let*
{"(let* (z 9) z)", "9"},
{"(let* (x 9) x)", "9"},
Expand All @@ -192,7 +184,7 @@ func TestEvaluate(t *testing.T) {
// (set!) inside (let) will only modify the local scope
{`
(set! a 3)
(let ((b 33))
(let* (b 33)
(set! a 4321))
a
`,
Expand All @@ -201,7 +193,7 @@ a
// (set! a b TRUE) inside (let) will modify the parent scope
{`
(define a 3)
(let ((b 33))
(let* (b 33)
(set! a 4321 true))
a
`,
Expand All @@ -222,7 +214,7 @@ a

// eval
{"(eval \"(+ 1 2)\")", "3"},
{"(let ((a \"(+ 1 23)\")) (eval a))", "24"},
{"(let* (a \"(+ 1 23)\") (eval a))", "24"},
{"(eval c)", "nil"},
{"(read \"(+ 3 4)\")", "(+ 3 4)"},
{"(eval (read \"(+ 3 4)\"))", "7"},
Expand Down Expand Up @@ -324,11 +316,6 @@ a
{"(set! 3 4)", "ERROR{tried to set a non-symbol 3}"},
{"(eval 'foo 'bar)", primitive.ArityError().ToString()},
{"(eval 3)", "ERROR{unexpected type for eval %!V(primitive.Number=3).}"},
{"(let 3)", "ERROR{argument is not a list, got 3}"},
{"(let ((0 0)) )", "ERROR{binding name is not a symbol, got 0}"},
{"(let ((0 )) )", primitive.ArityError().ToString()},
{"(let (3 3) )", "ERROR{binding value is not a list, got 3}"},

{"(let*)", primitive.ArityError().ToString()},
{"(let* 32)", "ERROR{argument is not a list, got 32}"},
{"(let* (a 3 b))", "ERROR{list for (len*) must have even length, got [a 3 b]}"},
Expand Down Expand Up @@ -357,7 +344,7 @@ a
{"(print (/ 3 0))", "ERROR{error expanding argument [/ 3 0] for call to (print ..): ERROR{attempted division by zero}}"},
{"(lambda (x 3) (nil))}", "ERROR{expected a symbol for an argument, got 3}"},
{"(set! )", primitive.ArityError().ToString()},
{"(let )", primitive.ArityError().ToString()},
{"(let* )", primitive.ArityError().ToString()},
{`
(define fizz (lambda (n:number)
(cond
Expand Down
60 changes: 1 addition & 59 deletions eval/specials.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.Environment, expandMacro bool) (primitive.Primitive, bool) {

switch name {

case "alias":
// We need at least one pair.
if len(args) < 2 {
Expand All @@ -46,7 +47,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return primitive.Nil{}, true

// (define
case "define", "def!":
if len(args) < 2 {
return primitive.ArityError(), true
Expand All @@ -59,7 +59,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return primitive.Error(fmt.Sprintf("Expected a symbol, got %v", args[0])), true

// (defmacro!
case "defmacro!":
if len(args) < 2 {
return primitive.ArityError(), true
Expand Down Expand Up @@ -91,7 +90,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return ret, true

// (env
case "env":

// create a new list
Expand Down Expand Up @@ -162,7 +160,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
return primitive.Error(fmt.Sprintf("unexpected type for eval %V.", args[0])), true
}

// (if
case "if":
if len(args) < 2 {
return primitive.ArityError(), true
Expand All @@ -188,7 +185,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
// otherwise we handle the true-section.
return ev.eval(args[1], e, expandMacro), true

// (lambda
case "lambda", "fn*":
// ensure we have arguments
if len(args) != 2 && len(args) != 3 {
Expand Down Expand Up @@ -234,54 +230,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
Macro: false,
}, true

// let
case "let":
if len(args) < 1 {
return primitive.ArityError(), true
}

newEnv := env.NewEnvironment(e)
bindingsList, ok := args[0].(primitive.List)
if !ok {
return primitive.Error(fmt.Sprintf("argument is not a list, got %v", args[0])), true
}

for _, binding := range bindingsList {

// ensure we got a list
bl, ok := binding.(primitive.List)
if !ok {
return primitive.Error(fmt.Sprintf("binding value is not a list, got %v", binding)), true
}

if len(bl) < 2 {
return primitive.ArityError(), true
}

// get the value
bindingVal := ev.eval(bl[1], newEnv, expandMacro)

// The thing to set
set, ok2 := bl[0].(primitive.Symbol)
if !ok2 {
return primitive.Error(fmt.Sprintf("binding name is not a symbol, got %v", bl[0])), true
}

// Finally set the parameter
newEnv.Set(string(set), bindingVal)
}

// Now we've populated the new
// environment with the pairs we received
// in the setup phase we can execute
// the body.
var ret primitive.Primitive
for _, x := range args[1:] {
ret = ev.eval(x, newEnv, expandMacro)
}
return ret, true

// (let*
case "let*":
// We need to have at least one argument.
//
Expand Down Expand Up @@ -330,21 +278,18 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return ret, true

// (macroexpand ..)
case "macroexpand":
if len(args) != 1 {
return primitive.ArityError(), true
}
return ev.macroExpand(args[0], e), true

// (quasiquote ..)
case "quasiquote":
if len(args) != 1 {
return primitive.ArityError(), true
}
return ev.eval(ev.quasiquote(args[0]), e, expandMacro), true

// (quote ..)
case "quote":
if len(args) != 1 {
return primitive.ArityError(), true
Expand Down Expand Up @@ -376,7 +321,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
// Return it.
return out, true

// (set!
case "set!":
if len(args) < 2 {
return primitive.ArityError(), true
Expand All @@ -399,7 +343,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return primitive.Nil{}, true

// (struct
case "struct":
if len(args) <= 1 {
return primitive.ArityError(), true
Expand Down Expand Up @@ -430,7 +373,6 @@ func (ev *Eval) evalSpecialForm(name string, args []primitive.Primitive, e *env.
}
return ev.atom(args[0].ToString()), true

// (try
case "try":
if len(args) < 2 {
return primitive.ArityError(), true
Expand Down

0 comments on commit 005a953

Please sign in to comment.