summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stdlib/infix.tl32
-rw-r--r--tests/012/infix.tl12
-rw-r--r--txr.1101
3 files changed, 95 insertions, 50 deletions
diff --git a/stdlib/infix.tl b/stdlib/infix.tl
index 6a19f957..f455a755 100644
--- a/stdlib/infix.tl
+++ b/stdlib/infix.tl
@@ -220,18 +220,26 @@
(first nodestack)))
(defun-match detect-infix
- (((@(@o [ifx-uops]) . @rest))
- (or (neq o.sym o.lispsym)
- (find-if [orf ifx-uops ifx-ops] rest)))
- ((@(require (@nil [. @toks] . @nil)
- (or (atom toks)
- (null (cdr toks))
- (detect-infix toks))))
- t)
- (((@nil @y . @rest))
- (or [ifx-uops y] [ifx-ops y]
- (find-if [orf ifx-uops ifx-ops] rest)))
- ((@nil)))
+ (((@x @y . @rest))
+ (let* ((xu [ifx-uops x])
+ (yu [ifx-uops y])
+ (yo [ifx-ops y])
+ (yb (if-match [. @toks] y
+ (or (and (consp toks)
+ (null (cdr toks)))
+ (detect-infix toks))))
+ (ya (and (not yu) (not yo) (not (fboundp y))))
+ (xa (and (not xu) (not (fboundp x)))))
+ (or
+ (and xa (or yo yb))
+ (and xu ya (neq xu.sym xu.lispsym))
+ (if-match (@z . @nil) rest
+ (let* ((zu [ifx-uops z])
+ (zo [ifx-ops z])
+ (za (and (not zu) (not zo) (not (fboundp z)))))
+ (or
+ (and xu yu (or zu za))
+ (and xu ya zo))))))))
(defun infix-expand-hook (exp env type-sym)
(ignore env)
diff --git a/tests/012/infix.tl b/tests/012/infix.tl
index 0da0abeb..10b98930 100644
--- a/tests/012/infix.tl
+++ b/tests/012/infix.tl
@@ -126,9 +126,9 @@
data)))
(msstest
- (fft #(nil 0.0 0.0 0.0 0.0) 2 1)
- #(nil 0.0 0.0 0.0 0.0)
- (fft #(nil 1.0 1.0 1.0 1.0) 2 1)
- #(nil 2.0 2.0 0.0 0.0)
- (fft #(nil 0 1 0 2 0 3 0 4) 4 1)
- #(nil 0.0 10.0 2.0 -2.0 0.0 -2.0 -2.0 -2.0))
+ (fft #(nil 0.0 0.0 0.0 0.0) 2 1) #(nil 0.0 0.0 0.0 0.0)
+ (fft #(nil 1.0 1.0 1.0 1.0) 2 1) #(nil 2.0 2.0 0.0 0.0)
+ (fft #(nil 0 1 0 2 0 3 0 4) 4 1) #(nil 0.0 10.0 2.0 -2.0 0.0 -2.0 -2.0 -2.0))
+
+(msstest
+ (map (lop / 4) #(10 20 30)) #(2.5 5.0 7.5))
diff --git a/txr.1 b/txr.1
index 52c3c207..fc991584 100644
--- a/txr.1
+++ b/txr.1
@@ -54209,51 +54209,84 @@ Pass the form through; decline to perform a transformation.
A form is recognized as applicable for
.code parse-infix
-if any of these three conditions hold:
+by examining the first two or three elements of the form according
+to the following patterns. In these patterns, the letter
+.code u
+denotes a prefix (unary) operator; the letter
+.code o
+denotes an infix operator and the letter
+.code A
+denotes an argument which is not the name of a function or operator.
+Additionally, the letter
+.code u*
+indicates a prefix operator which is not also the name of a function.
+The patterns which indicate a form for processing via
+.code parse-infix
+are:
.RS
-.IP 1.
-The first element of the form is a prefix operator which is not the name of a
-built-in math function; or else the first element is a operator which is also
-the name of a built-in math function, and at least one of the remaining
-arguments is an operator.
-.IP 2
-The form form contains at least two elements, and at least one operator
-occurs among the second and subsequent arguments.
-.IP 3
-The form contains at least two elements, the second of which is a
-DWIM brackets form, which encloses either a single element or
-multiple elements which, if taken as an ordinary form, satisfy
-any of these three rules.
+.coIP "(A o ...)"
+A two-element pattern beginning with an argument followed by an infix operator.
+.coIP "(A [...] ...)
+A pattern beginning with an argument followed by a bracket expression
+is treated as infix, if the bracket expression encloses exactly one
+element or else if the content of the bracket expression recursively meets
+these rules, after conversion to ordinary expression. That is to say, for
+the purposes of applying these rules, the bracket expression is turned into the
+ordinary expression
+.code "(...)"
+with the same content. If this converted expression in indicated as infix,
+then the parent expression is indicates as infix, otherwise not.
+.coIP (u u u ...)
+Three consecutive leading prefix operators.
+.coIP (u u A ...)
+Two consecutive leading prefix operators followed by an argument.
+.coIP (u A o ...)
+A prefix operator followed by an argument, followed by an infix
+operator.
+.coIP (u* A ...)
+A prefix operator which is not also the name of a function,
+followed by an argument.
.RE
For instance, the form
.code "(++ x)"
-is recognized as an infix expression by rule 1 above, because
+is recognized as an infix expression by the last rule above, since
it begins with a prefix operator whose name isn't the name of
-a math function.
+a math function, followed by the argument
+.code x
+which is not the name of a function.
-In contrast
+The valid infix expression
.code "(sin x)"
-is not recognized as infix by rule 1, because since
+is not recognized as infix. Though
.code sin
-is a prefix operator which is also the name of a math library
-function, there is a requirement that there be additional arguments
-at least one of which is an operator. There are no such arguments.
-Note that, in fact, this expression does not require transformation;
-though it is a valid infix expression that could be parsed by
-.codn parse-infix ,
-it is also valid Lisp.
+is a prefix operator, it is one which is also a Lisp function,
+and thus this does not match the
+.code "(u* A ...)"
+pattern. It doesn't match the
+.code "(u A o ...)"
+pattern due to a missing third element that wold correspond to
+.codn o .
+Though not treated as infix, this expression does not require it,
+because
+.code parse-infix
+will return an identical expression.
The expression
.code "(a + a)"
-is recognized as infix by rule 2 above. The form contains at least
-two elements. The second element is an operator, which is sufficient.
+is recognized as infix by the
+.code "(A o ...)"
+pattern. The form contains at least two elements. The first is
+an argument and the second an infix operator.
The expression
.code "(a [i])"
-is recognized by rule 3, because the second element is a square
-bracket expression containing one element.
+is recognized by the
+.code "(A [...] ...)"
+pattern, and its additional constraints, because the first element is an
+argument and the second element is a square bracket expression containing
+exactly one element.
The
.code parse-infix
function will transform it to
@@ -54267,13 +54300,17 @@ form, turning it into
The expression
.code "(a [i + j])"
-is also recognized by rule 3, because the second element is a square
+is also recognized by the pattern
+.code "(A [...] ...)"
+and its additional constraints, because the second element is a square
bracket expression, whose elements, if they are isolated as the expression
.codn "(i + j)" ,
-satisfy one of the three rules, namely rule 2.
+satisfy the
+.code "(A o ...)"
+pattern.
The
.code parse-infix
-function will transform it to
+function will transform it this expression
.codn "[a (i + j)]" ,
in which recursive processing by the
.code ifx