Fixed seqability of cons cell, added quote read macro

This commit is contained in:
Simon Brooke 2019-08-15 09:47:48 +01:00
parent 6853c6c29c
commit b4091f28dc
2 changed files with 58 additions and 32 deletions

View file

@ -3,22 +3,35 @@
(def NIL (symbol "NIL"))
(def NIL (symbol "NIL"))
(deftype ConsCell [CAR CDR]
clojure.lang.ISeq
(cons [this x] (ConsCell. x this))
(count [this] (if
(= (.CDR this) NIL)
0
(inc (count (.CDR this)))))
(first [this] (.CAR this))
;; next and more must return ISeq:
;; https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java
(more [this] (if
(= (.CDR this) NIL)
clojure.lang.PersistentList/EMPTY
(.CDR this)))
(next [this] (.CDR this))
(seq [this] this) ;; doesn't work - `Method beowulf/cons_cell/ConsCell.seq()Lclojure/lang/ISeq; is abstract`
(next [this] (if
(= (.CDR this) NIL)
nil ;; next returns nil when empty
(.CDR this)))
clojure.lang.Seqable
(seq [this] this)
;; for some reason this marker protocol is needed otherwise compiler complains
;; that `nth not supported on ConsCell`
clojure.lang.Sequential
clojure.lang.IPersistentCollection
(count [this] (if
(= (.CDR this) NIL)
0
(inc (count (.CDR this)))))
(empty [this] false)
(equiv [this other] false))

View file

@ -4,12 +4,19 @@
;; (:import [beowulf.cons-cell ConsCell])
)
(declare generate)
(def parse
"Parse a string presented as argument into a parse tree which can then
be operated upon further."
(i/parser
"expr := mexpr | sexpr;
mexpr := fncall | defn | cond;
(str
;; top level: we accept mexprs as well as sexprs.
"expr := mexpr | sexpr;"
;; mexprs. I'm pretty clear that Lisp 1.5 could never read these,
;; but it's a convenience.
"mexpr := fncall | defn | cond;
fncall := fn-name lsqb args rsqb;
lsqb := '[';
rsqb := ']';
@ -20,20 +27,24 @@
args := (arg semi-colon opt-space)* arg;
arg := mexpr | sexpr;
fn-name := #'[a-z]*';
semi-colon := ';';
semi-colon := ';';"
list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
;; sexprs. Note it's not clear to me whether Lisp 1.5 had the quote macro,
;; but I've included it on the basis that it can do little harm.
"list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
dotted-pair := lpar dot-terminal ;
dot := '.';
lpar := '(';
rpar := ')';
sexpr := atom | number | dotted-pair | list;
sexpr := atom | number | dotted-pair | list | quoted-expr;
quoted-expr := quote sexpr;
quote := '\\'';
dot-terminal := sexpr space dot space sexpr rpar;
space := #'\\p{javaWhitespace}+';
opt-space := #'\\p{javaWhitespace}*';
sep := ',' | opt-space;
atom := #'[A-Z][A-Z0-9]*';
number := #'-?[0-9][0-9.]*';"))
number := #'-?[0-9][0-9.]*';")))
(defn simplify
"Simplify this parse tree `p`."
@ -45,9 +56,11 @@
(remove
#(if (coll? %) (empty? %))
(case (first p)
(:arrow :dot :lpar :lsqb :opt-space :rpar :rsqb :semi-colon :sep :space) nil
(:arrow :dot :lpar :lsqb :opt-space :quote :rpar :rsqb :semi-colon :sep :space) nil
(:arg :expr :mexpr :sexpr) (simplify (second p))
(:args :cond :cond-clause :dot-terminal :dotted-pair :fncall :list) (map simplify p)
;; the quote read macro (which probably didn't exist in Lisp 1.5, but...)
:quoted-expr [:fncall [:fn-name "quote"] [:args (simplify (nth p 2))]]
;;default
p)))
p))