summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-17 08:34:02 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-17 08:34:02 -0700
commita0f18bf76682b4c49f7fb66bdbdcb4dad23483ec (patch)
treeee4bf1892f7665a1f73124a0340ab711d8e404d3
parentba498170706db2c1a53dc3427c584dd74230deef (diff)
downloadtxr-a0f18bf76682b4c49f7fb66bdbdcb4dad23483ec.tar.gz
txr-a0f18bf76682b4c49f7fb66bdbdcb4dad23483ec.tar.bz2
txr-a0f18bf76682b4c49f7fb66bdbdcb4dad23483ec.zip
compiler: compile string quasiliterals.
* share/txr/stdlib/compiler.tl (compiler compile): Add sys:quasi case, dispatching new comp-quasi method. (compiler comp-quasi): New method. (expand-quasi-mods, expand-quasi-args, expand-quasi): New functions.
-rw-r--r--share/txr/stdlib/compiler.tl84
1 files changed, 84 insertions, 0 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index f7ae0bc3..adf85e37 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -132,6 +132,7 @@
(sys:for-op me.(comp-for env (cdr form)))
(progn me.(comp-progn env (cadr form)))
(prog1 me.(comp-prog1 env form))
+ (sys:quasi me.(comp-quasi env form))
(sys:dvbind me.(compile env (caddr form)))
(sys:with-dyn-rebinds me.(comp-progn env (cddr form)))
((macrolet symacrolet macro-time)
@@ -353,6 +354,10 @@
((prog1 fi) me.(compile env fi))
((prog1) me.(compile env nil))))
+(defmeth compiler comp-quasi (me env form)
+ (let ((qexp (expand-quasi form)))
+ me.(compile env (expand qexp))))
+
(defmeth compiler comp-call (me env sym args)
(let ((oreg me.(alloc-treg))
(dreg me.(get-dreg sym))
@@ -396,6 +401,85 @@
[reduce-left uni frags nil .fvars]
[reduce-left uni frags nil .ffuns])))))
+(defun expand-quasi-mods (obj mods : form)
+ (let (plist num sep rng-ix scalar-ix-p flex gens)
+ (flet ((get-sym (exp)
+ (let ((gen (gensym)))
+ (push (list gen exp) gens)
+ gen)))
+ (for () (mods) ((pop mods))
+ (let ((mel (car mods)))
+ (cond
+ ((keywordp mel)
+ (set plist mods)
+ (return))
+ ((integerp mel)
+ (when num
+ (compile-error form "duplicate modifier (width/alignment): ~s"
+ num))
+ (set num mel))
+ ((stringp mel)
+ (when sep
+ (compile-error form "duplicate modifier (separator): ~s"
+ num))
+ (set sep mel))
+ ((atom mel)
+ (push (get-sym mel) flex))
+ (t
+ (caseq (car mel)
+ (dwim
+ (when rng-ix
+ (compile-error form "duplicate modifier (range/index): ~s"
+ mel))
+ (unless (consp (cdr mel))
+ (compile-error form "misisng argument in range/index: ~s"
+ mel))
+ (unless (null (cddr mel))
+ (compile-error form "excess args in range/index: ~s"
+ num))
+ (let ((arg (cadr mel)))
+ (cond
+ ((and (consp arg) (eq (car arg) 'range))
+ (set rng-ix (get-sym ^(rcons ,(cadr arg) ,(caddr arg)))))
+ (t
+ (set rng-ix (get-sym arg))
+ (set scalar-ix-p t)))))
+ (sys:expr (push (get-sym flex) (cadr mel)))
+ (t (push (get-sym mel) flex)))))))
+ (let ((mcount (+ (if num 1 0)
+ (if sep 1 0)
+ (if rng-ix 1 0)
+ (len flex))))
+ (when (> mcount 3)
+ (compile-error form "too many formatting modifiers"))
+ ^(alet ,(nreverse gens)
+ ,(if flex
+ ^(sys:fmt-flex ,obj ',plist
+ ,*(remq nil (list* num sep
+ (if scalar-ix-p
+ ^(rcons ,rng-ix nil)
+ rng-ix)
+ (nreverse flex))))
+ ^(sys:fmt-simple ,obj ,num ,sep, rng-ix ',plist)))))))
+
+(defun expand-quasi-args (form)
+ (append-each ((el (cdr form)))
+ (cond
+ ((consp el)
+ (caseq (car el)
+ (sys:var (mac-param-bind form (sym exp : mods) el
+ (list (expand-quasi-mods exp mods))))
+ (sys:quasi (expand-quasi-mods el))
+ (t el)))
+ ((bindable el)
+ (list ^(sys:fmt-simple ,el nil nil nil nil)))
+ (t
+ (list el)))))
+
+(defun expand-quasi (form)
+ (let ((qa (expand-quasi-args form)))
+ ^(append ,*qa)))
+
(defun usr:compile-toplevel (exp)
(let ((co (new compiler))
(as (new assembler)))