Considerably improved REPL, with better parse error handling
This commit is contained in:
parent
609e2c3a6e
commit
526b71bce7
17
README.md
17
README.md
|
@ -4,15 +4,22 @@ LISP 1.5 is to all Lisp dialects as Beowulf is to Emglish literature.
|
|||
|
||||
## What this is
|
||||
|
||||
A work-in-progress towards an implementation of Lisp 1.5 in Clojure.
|
||||
A work-in-progress towards an implementation of Lisp 1.5 in Clojure. The
|
||||
objective is to build a complete and accurate implementation of Lisp 1.5
|
||||
as described in the manual, with, in so far as is possible, exactly the
|
||||
same bahaviour; the only intended deviation is that the parser reads
|
||||
'mexprs' (meta language expressions) as well as sexprs.
|
||||
|
||||
## BUT WHY?!!?!
|
||||
|
||||
Because.
|
||||
|
||||
Because Lisp is the only computer language worth learning, and if a thing is worth learning, it's worth learning properly; which means going back to the beginning and trying to understand that.
|
||||
Because Lisp is the only computer language worth learning, and if a thing
|
||||
is worth learning, it's worth learning properly; which means going back to
|
||||
the beginning and trying to understand that.
|
||||
|
||||
Because there is, so far as I know, no working implementation of Lisp 1.5 for modern machines.
|
||||
Because there is, so far as I know, no working implementation of Lisp 1.5
|
||||
for modern machines.
|
||||
|
||||
Because I'm barking mad, and this is therapy.
|
||||
|
||||
|
@ -24,6 +31,10 @@ Download from http://example.com/FIXME.
|
|||
|
||||
`java -jar beowulf-0.1.0-standalone.jar`
|
||||
|
||||
This will start a Lisp 1.5 read/eval/print loop (REPL).
|
||||
|
||||
To end a session, type `quit` at the command prompt.
|
||||
|
||||
## Learning Lisp 1.5
|
||||
|
||||
The `Lisp 1.5 Programmer's Manual` is still
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||
[org.clojure/math.numeric-tower "0.0.4"]
|
||||
[org.clojure/tools.trace "0.7.10"]
|
||||
[environ "1.1.0"]
|
||||
[instaparse "1.4.10"]]
|
||||
:main ^:skip-aot beowulf.core
|
||||
:plugins [[lein-environ "1.1.0"]]
|
||||
:target-path "target/%s"
|
||||
:profiles {:uberjar {:aot :all}})
|
||||
|
|
|
@ -1,15 +1,53 @@
|
|||
(ns beowulf.core
|
||||
(:require [beowulf.eval :refer [EVAL oblist]]
|
||||
[beowulf.read :refer [READ]])
|
||||
[beowulf.read :refer [READ]]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[environ.core :refer [env]])
|
||||
(:gen-class))
|
||||
|
||||
(defn -main
|
||||
(defn repl
|
||||
"Read/eval/print loop."
|
||||
[& args]
|
||||
(println "Béowulf is mín nama")
|
||||
[]
|
||||
(loop []
|
||||
(print ":: ")
|
||||
(flush)
|
||||
(let [input (READ)]
|
||||
(println (str "> " (EVAL input @oblist)))
|
||||
(recur))))
|
||||
(try
|
||||
(let [input (read-line)]
|
||||
(cond
|
||||
(= input "quit") (throw (ex-info "Færwell!" {:cause :quit}))
|
||||
input (println (str "> " (EVAL (READ input) @oblist)))
|
||||
:else (println)))
|
||||
(catch
|
||||
Exception
|
||||
e
|
||||
(let [data (ex-data e)]
|
||||
(if
|
||||
data
|
||||
(case (:cause data)
|
||||
:parse-failure (println (:failure data))
|
||||
:quit (throw e)
|
||||
;; default
|
||||
(pprint data))
|
||||
(println (.getMessage e))))))
|
||||
(recur)))
|
||||
|
||||
(defn -main
|
||||
[& args]
|
||||
(println
|
||||
(str
|
||||
"Hider wilcuman. Béowulf is mín nama\nSíðe "
|
||||
(System/getProperty "beowulf.version")
|
||||
"\n\n"))
|
||||
(try
|
||||
(repl)
|
||||
(catch
|
||||
Exception
|
||||
e
|
||||
(let [data (ex-data e)]
|
||||
(if
|
||||
data
|
||||
(case (:cause data)
|
||||
:quit (println (.getMessage e))
|
||||
;; default
|
||||
(pprint data))
|
||||
(println e))))))
|
||||
|
|
|
@ -64,9 +64,13 @@
|
|||
scale-factor := #'[0-9]*'")))
|
||||
|
||||
(defn simplify
|
||||
"Simplify this parse tree `p`."
|
||||
"Simplify this parse tree `p`. If `p` is an instaparse failure object, throw
|
||||
an `ex-info`, with `p` as the value of its `:failure` key."
|
||||
([p]
|
||||
(simplify p :sexpr))
|
||||
(if
|
||||
(instance? instaparse.gll.Failure p)
|
||||
(throw (ex-info "Parse error" {:cause :parse-failure :failure p}))
|
||||
(simplify p :sexpr)))
|
||||
([p context]
|
||||
(if
|
||||
(coll? p)
|
||||
|
@ -274,5 +278,5 @@
|
|||
`(generate (simplify (parse ~s))))
|
||||
|
||||
(defn READ
|
||||
[]
|
||||
(gsp (read-line)))
|
||||
[input]
|
||||
(gsp (or input (read-line))))
|
||||
|
|
Loading…
Reference in a new issue