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"))
(def NIL (symbol "NIL"))
(deftype ConsCell [CAR CDR] (deftype ConsCell [CAR CDR]
clojure.lang.ISeq clojure.lang.ISeq
(cons [this x] (ConsCell. x this)) (cons [this x] (ConsCell. x this))
(count [this] (if
(= (.CDR this) NIL)
0
(inc (count (.CDR this)))))
(first [this] (.CAR 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 (more [this] (if
(= (.CDR this) NIL) (= (.CDR this) NIL)
clojure.lang.PersistentList/EMPTY clojure.lang.PersistentList/EMPTY
(.CDR this))) (.CDR this)))
(next [this] (.CDR this)) (next [this] (if
(seq [this] this) ;; doesn't work - `Method beowulf/cons_cell/ConsCell.seq()Lclojure/lang/ISeq; is abstract` (= (.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 clojure.lang.IPersistentCollection
(count [this] (if
(= (.CDR this) NIL)
0
(inc (count (.CDR this)))))
(empty [this] false) (empty [this] false)
(equiv [this other] false)) (equiv [this other] false))

View file

@ -4,12 +4,19 @@
;; (:import [beowulf.cons-cell ConsCell]) ;; (:import [beowulf.cons-cell ConsCell])
) )
(declare generate)
(def parse (def parse
"Parse a string presented as argument into a parse tree which can then "Parse a string presented as argument into a parse tree which can then
be operated upon further." be operated upon further."
(i/parser (i/parser
"expr := mexpr | sexpr; (str
mexpr := fncall | defn | cond; ;; 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; fncall := fn-name lsqb args rsqb;
lsqb := '['; lsqb := '[';
rsqb := ']'; rsqb := ']';
@ -20,20 +27,24 @@
args := (arg semi-colon opt-space)* arg; args := (arg semi-colon opt-space)* arg;
arg := mexpr | sexpr; arg := mexpr | sexpr;
fn-name := #'[a-z]*'; 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 ; dotted-pair := lpar dot-terminal ;
dot := '.'; dot := '.';
lpar := '('; lpar := '(';
rpar := ')'; 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; dot-terminal := sexpr space dot space sexpr rpar;
space := #'\\p{javaWhitespace}+'; space := #'\\p{javaWhitespace}+';
opt-space := #'\\p{javaWhitespace}*'; opt-space := #'\\p{javaWhitespace}*';
sep := ',' | opt-space; sep := ',' | opt-space;
atom := #'[A-Z][A-Z0-9]*'; atom := #'[A-Z][A-Z0-9]*';
number := #'-?[0-9][0-9.]*';")) number := #'-?[0-9][0-9.]*';")))
(defn simplify (defn simplify
"Simplify this parse tree `p`." "Simplify this parse tree `p`."
@ -45,9 +56,11 @@
(remove (remove
#(if (coll? %) (empty? %)) #(if (coll? %) (empty? %))
(case (first p) (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)) (:arg :expr :mexpr :sexpr) (simplify (second p))
(:args :cond :cond-clause :dot-terminal :dotted-pair :fncall :list) (map simplify 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 ;;default
p))) p)))
p)) p))