Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop the use of '(let )' #103

Merged
merged 1 commit into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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