diff options
-rw-r--r-- | stdlib/infix.tl | 32 | ||||
-rw-r--r-- | tests/012/infix.tl | 12 | ||||
-rw-r--r-- | txr.1 | 101 |
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)) @@ -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 |