summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-09-08 22:44:46 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-09-08 22:44:46 -0700
commit09d682f419016ad906f8448fd2c245e411b5358c (patch)
tree0fb577eaadd934bd0a230633ce978c208ef20862 /share
parent4296be5ab5aeb2f13b7c76f5e562b85b18d3beb9 (diff)
downloadtxr-09d682f419016ad906f8448fd2c245e411b5358c.tar.gz
txr-09d682f419016ad906f8448fd2c245e411b5358c.tar.bz2
txr-09d682f419016ad906f8448fd2c245e411b5358c.zip
awk macro: revise rng eval strategy.
awk ranges must evaluate out-of-band after the record is read, before the patterns and actions are evaluated. * share/txr/stdlib/awk.tl (sys:awk-compile-time): New slots, rng-expr-temps and rng-exprs. (sys:awk-let): Stash the code for evaluating a range into the compile-time info into the rng-exprs list, and associate it with a gensym in the parallel rng-expr-temps list. Then emit that gensym as the expansion for the rng form. (awk): Process the pattern code in two steps. First, expand it, to get it to drop the rng-exprs into the awk compile-time info structure. Then when generating the final lambda, wrap an let* around the generated code which binds the rng-temps with the rng-exprs. This resolves the gensym references that replaced the ranges. let* is is used and its bindings are reversed into discovery order because this supports nested rng syntax. Given (rng x (rng y z)), the (rng y z) is expanded first, and so its code and temp gensym are pushed onto their respective lists firsts. The outer rng's code will thus contain a temp referring to the code of the inner one.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/awk.tl67
1 files changed, 43 insertions, 24 deletions
diff --git a/share/txr/stdlib/awk.tl b/share/txr/stdlib/awk.tl
index d7aa6891..a2d03361 100644
--- a/share/txr/stdlib/awk.tl
+++ b/share/txr/stdlib/awk.tl
@@ -41,7 +41,9 @@
(set self.output (open-file self.output "w")))))
(defstruct sys:awk-compile-time ()
- (nranges 0))
+ (nranges 0)
+ rng-expr-temps
+ rng-exprs)
(defmeth sys:awk-state rec-to-f (self)
(cond
@@ -137,31 +139,48 @@
(macrolet ((next () '(return-from :awk-rec))
(next-file () '(return-from :awk-file))
(prn (. args) ^(qref ,',aws-sym (prn ,*args)))
- (rng (from-expr to-expr)
- (let ((ix (pinc (qref ,awc nranges))))
- ^(symacrolet ((flag (vecref (qref ,',aws-sym rng-vec) ,ix)))
- (cond
- (,from-expr (set flag t))
- (,to-expr (zap flag) t)
- (flag))))))
+ (rng (from-expr to-expr :env e)
+ (let ((ix (pinc (qref ,awc nranges)))
+ (rng-temp (gensym))
+ (from-expr-ex (sys:expand from-expr e))
+ (to-expr-ex (sys:expand to-expr e)))
+ (push rng-temp (qref ,awc rng-expr-temps))
+ (push ^(symacrolet ((flag (vecref (qref ,',aws-sym rng-vec) ,ix)))
+ (cond
+ (,from-expr-ex (set flag t))
+ (,to-expr-ex (zap flag) t)
+ (flag)))
+ (qref ,awc rng-exprs))
+ rng-temp)))
,*body)))
-(defmacro awk (. clauses)
+(defmacro awk (:env e . clauses)
(tree-bind (awc inputs output name lets b-actions e-actions p-actions)
(sys:awk-expander clauses)
(with-gensyms (aws-sym awk-fun awk-retval)
- ^(let* (,*lets ,awk-retval)
- (let ((,awk-fun (lambda (,aws-sym)
- (sys:awk-let ,awc ,aws-sym
- ,*(mapcar (aret ^(when ,@1 ,*@rest)) p-actions))))
- (,aws-sym (new sys:awk-state
- ,*(if inputs ^(inputs (list ,*inputs)))
- ,*(if output ^(output ,output))
- rng-n (macro-time (qref ,awc nranges)))))
- (sys:awk-let ,awc ,aws-sym
- ,*b-actions)
- (block ,name
- (unwind-protect
- (qref ,aws-sym (loop ,awk-fun))
- (set ,awk-retval (progn ,*e-actions)))
- ,awk-retval))))))
+ (let* ((p-actions-xform-unex (mapcar (aret ^(when ,@1 ,*@rest))
+ p-actions))
+ (p-actions-xform (sys:expand
+ ^(sys:awk-let ,awc ,aws-sym
+ ,*p-actions-xform-unex)
+ e)))
+ ^(let* (,*lets ,awk-retval)
+ (let* ((,aws-sym (new sys:awk-state
+ ,*(if inputs ^(inputs (list ,*inputs)))
+ ,*(if output ^(output ,output))
+ rng-n (macro-time (qref ,awc nranges))))
+ (,awk-fun (lambda (,aws-sym)
+ (sys:awk-let ,awc ,aws-sym
+ ,(if awc.rng-exprs
+ ^(let* ,(nreverse
+ (zip awc.rng-expr-temps
+ awc.rng-exprs))
+ ,p-actions-xform)
+ p-actions-xform)))))
+ (sys:awk-let ,awc ,aws-sym
+ ,*b-actions)
+ (block ,name
+ (unwind-protect
+ (qref ,aws-sym (loop ,awk-fun))
+ (set ,awk-retval (progn ,*e-actions)))
+ ,awk-retval)))))))