summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-08-08 07:53:43 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-08-08 07:53:43 -0700
commit3c0c679b74016f0219c31d82578b99e53e531c78 (patch)
tree36790f5703b5100a890056b91f4216ce501ac123
parentca9ecd3ded67f06c9cebe5b3fd4d6fb940342f44 (diff)
downloadtxr-3c0c679b74016f0219c31d82578b99e53e531c78.tar.gz
txr-3c0c679b74016f0219c31d82578b99e53e531c78.tar.bz2
txr-3c0c679b74016f0219c31d82578b99e53e531c78.zip
new: left-inserting pipeline operators.
* stdlib/op.tl (opip-expand): Take arguments which specify the op and do operators to be inserted. Pass these through the recursive calls. (opip, oand): Pass op and do for the new arguments. (lopip, loand): New macros like opip and oand, but passing lop and ldo to the expander. (lflow): New macro. * autoload.c (op_set_entries): Add autoload entries for lopip, loand and lflow. * tests/012/op.tl: A few new tests. * txr.1: Documented. * stdlib/doc-syms.tl: Regenerated.
-rw-r--r--autoload.c3
-rw-r--r--stdlib/doc-syms.tl9
-rw-r--r--stdlib/op.tl28
-rw-r--r--tests/012/op.tl4
-rw-r--r--txr.159
5 files changed, 83 insertions, 20 deletions
diff --git a/autoload.c b/autoload.c
index b87d560a..417f6fb0 100644
--- a/autoload.c
+++ b/autoload.c
@@ -711,7 +711,8 @@ static val op_set_entries(val fun)
val name[] = {
lit("op"), lit("do"), lit("lop"), lit("ldo"), lit("ap"), lit("ip"),
lit("ado"), lit("ido"), lit("ret"), lit("aret"),
- lit("opip"), lit("oand"), lit("flow"),
+ lit("opip"), lit("oand"), lit("lopip"), lit("loand"),
+ lit("flow"), lit("lflow"),
nil
};
autoload_set(al_fun, name, fun);
diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl
index 79a52f39..be86e9d7 100644
--- a/stdlib/doc-syms.tl
+++ b/stdlib/doc-syms.tl
@@ -806,7 +806,7 @@
("floor" "D-0082")
("floor-rem" "N-02DE978F")
("floor1" "N-01ED20D1")
- ("flow" "N-02B2153E")
+ ("flow" "N-0178C76B")
("flush" "N-02390935")
("flush-stream" "N-03999913")
("flusho" "N-0072FF5E")
@@ -1157,6 +1157,7 @@
("lexical-macro-p" "N-021EC6D2")
("lexical-symacro-p" "N-021EC6D2")
("lexical-var-p" "N-021EC6D2")
+ ("lflow" "N-0178C76B")
("lgamma" "D-0086")
("lib-version" "N-032F57D4")
("line" "N-02D5D09D")
@@ -1176,6 +1177,7 @@
("load-args-recurse" "N-03067356")
("load-for" "N-0020A085")
("load-time" "D-0089")
+ ("loand" "N-02C35B52")
("loff-t" "N-01153D9E")
("log" "D-005A")
("log-alert" "N-035D75EC")
@@ -1212,6 +1214,7 @@
("long-suffix" "N-00A3183A")
("longlong" "N-02299408")
("lop" "N-017F3A22")
+ ("lopip" "N-02C35B52")
("lset" "N-008216EC")
("lstat" "N-006DE1CC")
("lutimes" "N-00E96FCF")
@@ -1410,7 +1413,7 @@
("o-sync" "N-034BF6C9")
("o-trunc" "N-034BF6C9")
("o-wronly" "N-034BF6C9")
- ("oand" "N-01937C5A")
+ ("oand" "N-02C35B52")
("obtain" "N-01556613")
("obtain*" "N-0102F0EB")
("obtain*-block" "N-0102F0EB")
@@ -1440,7 +1443,7 @@
("open-tail" "N-0348F89A")
("opendir" "N-024AA6F4")
("openlog" "N-037AA654")
- ("opip" "N-01937C5A")
+ ("opip" "N-02C35B52")
("opost" "N-03BD477F")
("opt" "N-0047F5AB")
("opt-desc" "N-03FC5092")
diff --git a/stdlib/op.tl b/stdlib/op.tl
index 2a41fc5a..4b5b0311 100644
--- a/stdlib/op.tl
+++ b/stdlib/op.tl
@@ -231,32 +231,42 @@
(listp rest)))
(t nil)))
-(defun sys:opip-expand (e clauses)
+(defun sys:opip-expand (e opsym dosym clauses)
(tree-case clauses
(nil nil)
((c . rest)
(if (atom c)
- (cons c (sys:opip-expand e rest))
+ (cons c (sys:opip-expand e opsym dosym rest))
(let ((sym (car c)))
(cond
((memq sym '(dwim uref qref op do lop ldo ap ip ado ido ret aret))
- (cons c (sys:opip-expand e rest)))
+ (cons c (sys:opip-expand e opsym dosym rest)))
((sys:opip-single-let-p c)
(tree-bind (t sym) c
- (sys:opip-expand e ^((let (,sym @1)) ,*rest))))
+ (sys:opip-expand e opsym dosym ^((let (,sym @1)) ,*rest))))
((sys:opip-let-p c)
(tree-bind (t . vars) c
^((do let* ,vars
- [(opip ,*(sys:opip-expand e rest)) @1]))))
+ [(opip ,*(sys:opip-expand e opsym dosym rest)) @1]))))
(t (let ((opdo (if (or (special-operator-p (car c))
- (macro-form-p c e)) 'do 'op)))
- (cons ^(,opdo ,*c) (sys:opip-expand e rest))))))))))
+ (macro-form-p c e)) dosym opsym)))
+ (cons ^(,opdo ,*c) (sys:opip-expand e opsym dosym
+ rest))))))))))
(defmacro opip (:env e . clauses)
- ^[chain ,*(sys:opip-expand e clauses)])
+ ^[chain ,*(sys:opip-expand e 'op 'do clauses)])
(defmacro oand (:env e . clauses)
- ^[chand ,*(sys:opip-expand e clauses)])
+ ^[chand ,*(sys:opip-expand e 'op 'do clauses)])
+
+(defmacro lopip (:env e . clauses)
+ ^[chain ,*(sys:opip-expand e 'lop 'ldo clauses)])
+
+(defmacro loand (:env e . clauses)
+ ^[chand ,*(sys:opip-expand e 'lop 'ldo clauses)])
(defmacro flow (val . opip-args)
^(call (opip ,*opip-args) ,val))
+
+(defmacro lflow (val . opip-args)
+ ^(call (lopip ,*opip-args) ,val))
diff --git a/tests/012/op.tl b/tests/012/op.tl
index 5501cec4..4e0a8d46 100644
--- a/tests/012/op.tl
+++ b/tests/012/op.tl
@@ -105,3 +105,7 @@
(flow 10 (+ 1) (let (x @1) (y (* x 2))) (+ x y)) 44
(flow 10 (+ 1) (let ((x @1) (y (* @1 2))) (+ x y))) 33
(flow 10 (+ 1) (let ((x @1) (y (* @1 2))))) nil)
+
+(mtest
+ (lflow 10 (- 1) (- 1)) 8
+ (lflow 10 (op - 100) (+ 1)) 91)
diff --git a/txr.1 b/txr.1
index 70a115a2..5a14573f 100644
--- a/txr.1
+++ b/txr.1
@@ -59006,10 +59006,12 @@ functions.
(mapcar (ap list @2 @1) '((1 2) (a b))) -> ((2 1) (b a))
.brev
-.coNP Macros @ opip and @ oand
+.coNP Macros @, opip @, oand @ lopip and @ loand
.synb
.mets (opip << clause *)
.mets (oand << clause *)
+.mets (lopip << clause *)
+.mets (loand << clause *)
.syne
.desc
The
@@ -59102,6 +59104,26 @@ or the respective dot notations, forms which invoke any of the
.code do
family of operators, as well as any atom forms.
+The
+.code lopip
+and
+.code loand
+operators are similar to, respectively,
+.code opip
+and
+.codn oand ,
+except that they insert the implicit argument as the leftmost
+argument. For these macros, the above specification of what transformations
+are applied to the arguments is modified as follows:
+
+.verb
+ ;; other compound forms are transformed like this:
+
+ (function ...) -> (lop function ...)
+ (operator ...) -> (ldo operator ...)
+ (macro ...) -> (ldo macro ...)
+.brev
+
When a
.code let
or
@@ -59263,9 +59285,10 @@ as well as, implicitly, the value
.code @1
coming from the previous element,
-.coNP Macro @ flow
+.coNP Macros @ flow and @ lflow
.synb
.mets (flow < form << opip-arg *)
+.mets (lflow < form << lopip-arg *)
.syne
.desc
The
@@ -59282,10 +59305,19 @@ arguments follow the semantics of the
.code opip
macro.
-The following equivalence holds:
+The same requirements apply to
+.codn lflow ,
+except that it is related to the
+.code lopip
+macro which inserts the implicit argument into the
+leftmost position.
+
+
+The following equivalences hold:
.verb
- (flow x ...) <--> [(opip ...) x]
+ (flow x ...) <--> [(opip ...) x]
+ (lflow x ...) <--> [(lopip ...) x]
.brev
That is to say,
@@ -59293,19 +59325,28 @@ That is to say,
is equivalent to the application of an
.codn opip -generated
function to the value of
-.metn form .
+.metn form ,
+and likewise
+.code lflow
+is equivalent to the application of a
+.codn lopip -generated
+function.
Note: if there are no
.meta opip-arg
+or
+.meta lopip-arg
arguments, then
.code flow
evaluates the
.code x
argument and returns
.codn nil ;
-which follows from the behavior of
+which follows from the behavior of the
.code opip
-when that operator is invoked with no arguments.
+and
+.code lopip
+macros, when those are invoked with no arguments.
.TP* Examples:
@@ -59313,6 +59354,10 @@ when that operator is invoked with no arguments.
(flow 1 (+ 2) (* 3) (cons 0)) -> (0 . 9)
(flow "abc" (upcase-str) (regsub #/B/ "ZTE")) -> "AZTEC"
+
+ (flow 1 (- 10)) -> 9
+
+ (lflow 10 (- 1)) -> 9
.brev
.coNP Macro @ ret