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,36 +4,47 @@
;; (: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.
fncall := fn-name lsqb args rsqb; "expr := mexpr | sexpr;"
lsqb := '[';
rsqb := ']';
defn := mexpr opt-space '=' opt-space mexpr;
cond := lsqb (cond-clause semi-colon opt-space)* cond-clause rsqb;
cond-clause := expr opt-space arrow opt-space expr;
arrow := '->';
args := (arg semi-colon opt-space)* arg;
arg := mexpr | sexpr;
fn-name := #'[a-z]*';
semi-colon := ';';
list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal; ;; mexprs. I'm pretty clear that Lisp 1.5 could never read these,
dotted-pair := lpar dot-terminal ; ;; but it's a convenience.
dot := '.'; "mexpr := fncall | defn | cond;
lpar := '('; fncall := fn-name lsqb args rsqb;
rpar := ')'; lsqb := '[';
sexpr := atom | number | dotted-pair | list; rsqb := ']';
dot-terminal := sexpr space dot space sexpr rpar; defn := mexpr opt-space '=' opt-space mexpr;
space := #'\\p{javaWhitespace}+'; cond := lsqb (cond-clause semi-colon opt-space)* cond-clause rsqb;
opt-space := #'\\p{javaWhitespace}*'; cond-clause := expr opt-space arrow opt-space expr;
sep := ',' | opt-space; arrow := '->';
atom := #'[A-Z][A-Z0-9]*'; args := (arg semi-colon opt-space)* arg;
number := #'-?[0-9][0-9.]*';")) arg := mexpr | sexpr;
fn-name := #'[a-z]*';
semi-colon := ';';"
;; 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 | 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.]*';")))
(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))