Fixed seqability of cons cell, added quote read macro
This commit is contained in:
parent
6853c6c29c
commit
b4091f28dc
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in a new issue