summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-22 23:33:22 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-22 23:33:22 -0700
commit24d4e4ba60119ad8d54998707e409728a425197e (patch)
tree0b1a20ca4f57c00fde85a281a562ce646ed87bd9
parentb154390bc08aca42e9a27b7def17368485adf8fb (diff)
downloadtxr-24d4e4ba60119ad8d54998707e409728a425197e.tar.gz
txr-24d4e4ba60119ad8d54998707e409728a425197e.tar.bz2
txr-24d4e4ba60119ad8d54998707e409728a425197e.zip
compiler: implement tree-case.
* share/txr/stdlib/compiler.tl (compiler compile): Add tree-case case, handled via comp-tree-case method. (compiler comp-tree-case): New method.
-rw-r--r--share/txr/stdlib/compiler.tl52
1 files changed, 52 insertions, 0 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 42d92780..c8125924 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -175,6 +175,7 @@
(sys:quasi me.(comp-quasi oreg env form))
(dohash me.(compile oreg env (expand-dohash form)))
(tree-bind me.(comp-tree-bind oreg env form))
+ (tree-case me.(comp-tree-case oreg env form))
(sys:upenv me.(compile oreg env.up (cadr form)))
(sys:dvbind me.(compile oreg env (caddr form)))
(sys:with-dyn-rebinds me.(comp-progn oreg env (cddr form)))
@@ -597,6 +598,57 @@
obj-var t nil body)))))
me.(compile oreg env expn)))))
+(defmeth compiler comp-tree-case (me oreg env form)
+ (mac-param-bind form (op obj . cases) form
+ (let* ((ncases (len cases))
+ (nenv (new env up env co me))
+ (obj-immut-var (cdar nenv.(extend-var (gensym))))
+ (obj-var (cdar nenv.(extend-var (gensym))))
+ (err-var (cdar nenv.(extend-var (gensym))))
+ (err-blk (cdar nenv.(extend-var (gensym))))
+ (lout (gensym "l"))
+ (objfrag me.(compile oreg env obj))
+ (cfrags (collect-each ((c cases)
+ (i (range 1)))
+ (mac-param-bind form (params . body) c
+ (let* ((src (expand ^(block ,err-blk.sym
+ (set ,obj-var.sym
+ ,obj-immut-var.sym)
+ ,(expand-bind-mac-params
+ form params
+ nil obj-var.sym
+ err-var.sym
+ err-blk.sym
+ body))))
+ (lerrtest (gensym "l"))
+ (lnext (gensym "l"))
+ (cfrag me.(compile oreg nenv src)))
+ (new (frag oreg
+ ^(,*cfrag.code
+ ,*(maybe-mov oreg cfrag.oreg)
+ (ifq ,oreg ,me.(get-dreg :) ,lerrtest)
+ ,*(cond
+ ((eql i ncases)
+ ^((mov ,oreg nil)
+ (jmp ,lout)))
+ (t
+ ^((jmp ,lnext))))
+ ,lerrtest
+ (if ,err-var.loc ,lout)
+ ,*(if (neql i ncases) ^(,lnext)))
+ cfrag.fvars
+ cfrag.ffuns))))))
+ (allfrags (cons objfrag cfrags)))
+ (new (frag oreg
+ ^(,*objfrag.code
+ (frame ,nenv.lev ,nenv.v-cntr)
+ ,*(maybe-mov obj-immut-var.loc objfrag.oreg)
+ ,*(mappend .code cfrags)
+ ,lout
+ (end ,oreg))
+ [reduce-left uni allfrags nil .fvars]
+ [reduce-left uni allfrags nil .ffuns])))))
+
(defun maybe-mov (to-reg from-reg)
(if (nequal to-reg from-reg)
^((mov ,to-reg ,from-reg))))