Skip to content

Commit

Permalink
mal impl: report more errors in step files
Browse files Browse the repository at this point in the history
  • Loading branch information
asarhaddon committed Jan 12, 2022
1 parent 4f4938e commit dcc2b37
Show file tree
Hide file tree
Showing 9 changed files with 356 additions and 188 deletions.
16 changes: 13 additions & 3 deletions impls/mal/env.mal
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@
;; Private helper for new-env.
(def! bind-env (fn* [env b e]
(if (empty? b)
env
(if (empty? e)
env
(throw "too many arguments in function call"))
(let* [b0 (first b)]
(if (= '& b0)
(assoc env (str (nth b 1)) e)
(bind-env (assoc env (str b0) (first e)) (rest b) (rest e)))))))
(if (= 2 (count b))
(if (symbol? (nth b 1))
(assoc env (str (nth b 1)) e)
(throw "formal parameters must be symbols"))
(throw "misplaced '&' construct"))
(if (empty? e)
(throw "too few arguments in function call")
(if (symbol? b0)
(bind-env (assoc env (str b0) (first e)) (rest b) (rest e))
(throw "formal parameters must be symbols"))))))))

(def! new-env (fn* [& args]
(if (<= (count args) 1)
Expand Down
10 changes: 7 additions & 3 deletions impls/mal/step2_eval.mal
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
;; (do (prn "EVAL" ast) )
(try*
(cond

(symbol? ast)
(let* [res (get env (str ast))]
(if res res (throw (str ast " not found"))))

(vector? ast)
(vec (eval-ast ast ast))
(vec (eval-ast ast env))

(map? ast)
(apply hash-map (apply concat (map (fn* [k] [k (EVAL (get ast k) env)])
Expand All @@ -33,8 +34,11 @@

"else"
;; apply list
(let* [el (eval-ast ast env)]
(apply (first el) (rest el))))
(let* [el (eval-ast ast env)
fn (first el)]
(if (fn? fn)
(apply fn (rest el))
(throw "can only apply functions"))))

(catch* exc
(do
Expand Down
41 changes: 24 additions & 17 deletions impls/mal/step3_env.mal
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
(def! LET (fn* [env binds form]
(if (empty? binds)
(EVAL form env)
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form)))))
(if (if (< 1 (count binds)) (symbol? (first binds)))
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form))
(throw "invalid binds")))))

(def! EVAL (fn* [ast env]
;; (do (prn "EVAL" ast "/" (keys @env)) )
(try*
(cond

(symbol? ast)
(env-get env ast)

Expand All @@ -43,21 +46,25 @@
;; apply list
(let* [a0 (first ast)]
(cond
(empty? ast)
ast

(= 'def! a0)
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(if (if (= 3 (count ast)) (symbol? (nth ast 1)))
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(throw "bad arguments"))

(= 'let* a0)
(LET (new-env env) (nth ast 1) (nth ast 2))
(if (if (= 3 (count ast)) (sequential? (nth ast 1)))
(LET (new-env env) (nth ast 1) (nth ast 2))
(throw "bad arguments"))

"else"
(let* [el (eval-ast ast env)]
(apply (first el) (rest el))))))
(let* [el (eval-ast ast env)
fn (first el)]
(if (fn? fn)
(apply fn (rest el))
(throw "can only apply functions"))))))

(catch* exc
(do
Expand All @@ -72,10 +79,10 @@
(def! rep (fn* [strng]
(PRINT (EVAL (READ strng) repl-env))))

(env-set repl-env "+" +)
(env-set repl-env "-" -)
(env-set repl-env "*" *)
(env-set repl-env "/" /)
(env-set repl-env '+ +)
(env-set repl-env '- -)
(env-set repl-env '* *)
(env-set repl-env '/ /)

;; repl loop
(def! repl-loop (fn* [line]
Expand Down
51 changes: 32 additions & 19 deletions impls/mal/step4_if_fn_do.mal
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
(def! LET (fn* [env binds form]
(if (empty? binds)
(EVAL form env)
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form)))))
(if (if (< 1 (count binds)) (symbol? (first binds)))
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form))
(throw "invalid binds")))))

(def! EVAL (fn* [ast env]
;; (do (prn "EVAL" ast "/" (keys @env)) )
(try*
(cond

(symbol? ast)
(env-get env ast)

Expand All @@ -44,33 +47,43 @@
;; apply list
(let* [a0 (first ast)]
(cond
(empty? ast)
ast

(= 'def! a0)
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(if (if (= 3 (count ast)) (symbol? (nth ast 1)))
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(throw "bad arguments"))

(= 'let* a0)
(LET (new-env env) (nth ast 1) (nth ast 2))
(if (if (= 3 (count ast)) (sequential? (nth ast 1)))
(LET (new-env env) (nth ast 1) (nth ast 2))
(throw "bad arguments"))

(= 'do a0)
(nth (eval-ast (rest ast) env) (- (count ast) 2))
(if (<= 2 (count ast))
(nth (eval-ast (rest ast) env) (- (count ast) 2))
(throw "bad argument count"))

(= 'if a0)
(if (EVAL (nth ast 1) env)
(EVAL (nth ast 2) env)
(if (> (count ast) 3)
(EVAL (nth ast 3) env)))
(if (if (<= 3 (count ast)) (<= (count ast) 4))
(if (EVAL (nth ast 1) env)
(EVAL (nth ast 2) env)
(if (= 4 (count ast))
(EVAL (nth ast 3) env)))
(throw "bad argument count"))

(= 'fn* a0)
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
(if (if (= 3 (count ast)) (sequential? (nth ast 1)))
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
(throw "bad arguments"))

"else"
(let* [el (eval-ast ast env)]
(apply (first el) (rest el))))))
(let* [el (eval-ast ast env)
fn (first el)]
(if (fn? fn)
(apply fn (rest el))
(throw "can only apply functions"))))))

(catch* exc
(do
Expand Down
51 changes: 32 additions & 19 deletions impls/mal/step6_file.mal
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
(def! LET (fn* [env binds form]
(if (empty? binds)
(EVAL form env)
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form)))))
(if (if (< 1 (count binds)) (symbol? (first binds)))
(do
(env-set env (first binds) (EVAL (nth binds 1) env))
(LET env (rest (rest binds)) form))
(throw "invalid binds")))))

(def! EVAL (fn* [ast env]
;; (do (prn "EVAL" ast "/" (keys @env)) )
(try*
(cond

(symbol? ast)
(env-get env ast)

Expand All @@ -44,33 +47,43 @@
;; apply list
(let* [a0 (first ast)]
(cond
(empty? ast)
ast

(= 'def! a0)
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(if (if (= 3 (count ast)) (symbol? (nth ast 1)))
(let* [val (EVAL (nth ast 2) env)]
(do
(env-set env (nth ast 1) val)
val))
(throw "bad arguments"))

(= 'let* a0)
(LET (new-env env) (nth ast 1) (nth ast 2))
(if (if (= 3 (count ast)) (sequential? (nth ast 1)))
(LET (new-env env) (nth ast 1) (nth ast 2))
(throw "bad arguments"))

(= 'do a0)
(nth (eval-ast (rest ast) env) (- (count ast) 2))
(if (<= 2 (count ast))
(nth (eval-ast (rest ast) env) (- (count ast) 2))
(throw "bad argument count"))

(= 'if a0)
(if (EVAL (nth ast 1) env)
(EVAL (nth ast 2) env)
(if (> (count ast) 3)
(EVAL (nth ast 3) env)))
(if (if (<= 3 (count ast)) (<= (count ast) 4))
(if (EVAL (nth ast 1) env)
(EVAL (nth ast 2) env)
(if (= 4 (count ast))
(EVAL (nth ast 3) env)))
(throw "bad argument count"))

(= 'fn* a0)
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
(if (if (= 3 (count ast)) (sequential? (nth ast 1)))
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
(throw "bad arguments"))

"else"
(let* [el (eval-ast ast env)]
(apply (first el) (rest el))))))
(let* [el (eval-ast ast env)
fn (first el)]
(if (fn? fn)
(apply fn (rest el))
(throw "can only apply functions"))))))

(catch* exc
(do
Expand Down
Loading

0 comments on commit dcc2b37

Please sign in to comment.