From a6f48a6a2ea89b78be79650c9c74f6b77e7df3d1 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 22 Apr 2025 06:58:53 -0700 Subject: infix: phony infix for prefix funtion call expressions too. * stdlib/infix.tl (infix-expand-hook): In addition to the phony infix rule which swaps a function from second to first place, and then transforms the arguments, if possible, we add a case which is essentially like the above, but with the leading argument before the function being absent: the expression begins with a function and has two or more arguments. If those arguments transform as infix, we take the result as one argument. Otherwise if no transformation takes place, we return the original expression. * txr.1: Documented. --- stdlib/infix.tl | 8 +++++++- txr.1 | 47 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/stdlib/infix.tl b/stdlib/infix.tl index ef27ca41..88c42e2d 100644 --- a/stdlib/infix.tl +++ b/stdlib/infix.tl @@ -278,7 +278,13 @@ (let ((rexp (infix-expand-hook rest env nil))) (if (eq rexp rest) ^(,y ,x ,*rest) - ^(,y ,x ,rexp)))))) + ^(,y ,x ,rexp)))) + (@(require (@x . @rest) + (and rest (cdr rest) (funp env x))) + (let ((rexp (infix-expand-hook rest env nil))) + (if (eq rexp rest) + exp + ^(,x ,rexp)))))) (exp))) (defmacro usr:ifx (. body) diff --git a/txr.1 b/txr.1 index 3f5c79a0..1060f558 100644 --- a/txr.1 +++ b/txr.1 @@ -54223,7 +54223,7 @@ Additionally, the symbols and .codn !f , indicate a prefix operator which, respectively, is and is not, -the name of a gobal or lexical functionl. +the name of a global or lexical function. The patterns which indicate a form for processing via .code parse-infix are: @@ -54409,23 +54409,36 @@ into .codn "(+ i 1)" . A form not falling into any of the above rules is recognized as "phony infix" -if: it consists of at least two elements, where the first element is not +if it conforms to one of two situations: +.RS +.IP 1. +It consists of at least two elements, where the first element is not a function, and the second element is a function. Both the lexical and global function namespaces are considered. -When a form is thus recognized, -it is transformed by exchanging the first and second positions. -Furthermore, if there are additional arguments after these two positions, they are -taken as an independent expression which is passed through the infix expansion -hook. If it is transformed by the hook, then the transformed expression -is taken as a single argument added to the two leading arguments -that have been exchanged. Otherwise, all the original untransformed -arguments are added. +When a form is thus recognized, it is transformed by exchanging the first and +second positions. Additionally, the remaining arguments may be transformed +as described below. +.IP 2. +It consists of at least two elements, where the first element is a function. +In this situation, the remaining arguments may be transformed as described +below. In this second situation, if no argument transformation takes place, +then the form is not recognized as "phony infix". +.RE +In either of the above two cases, additional elements after the function +symbol (the third and subsequent form elements in case 1, or second and +subsequent elements in case 2) are taken as an independent expression which is +passed through the infix expansion hook. If it is transformed by the hook, then +the transformed expression is taken as a single element which replaces +all of the original elements. Otherwise, all the original +untransformed arguments remain as-is, in which case, in situation 2 +it means that the expression remains untransformed, implying that it has +not been recognized as infix. This is a fallback strategy applied by the .code ifx macro's expander hook. If an expression isn't recognized as infix -by the above two rules, it is tried as a phony infix expression. -In spite of +by the auto-detection rules, it is tried as a phony infix expression via +one of the above two cases. Thus, in spite of .code cons not being registered as an infix operator, .code "(a cons b)" @@ -54448,6 +54461,16 @@ isn't recognized infix; so these elements remain as individual arguments, such that the expression transforms into .codn "(list a b c d)" . +According to the phony infix case 2 above, an expression like +.code "(list 2 + 2)" +transforms to +.codn "(list (+ 2 2))" ; +in other words, the arguments after the function are treated in the +same manner as for the expression +.codn "(1 list 2 + 2)" , +which is transformed to +.codn "(list 1 (+ 2 2))" . + Only compound expressions are recognized as infix. A sequence of atoms like .code "a * b" -- cgit v1.2.3