From f5a32312e548375f59784109c281863f8ce9a63f Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 21 Apr 2025 19:50:30 -0700 Subject: infix: support function power operators. * infix.tl (ifx-oper): New slot, power. When we detect a prefix operator that is followed by a power symbol and operand, we clone the operator and store the operand here. (parse-infix): If the operator has the power slot, the add-local function, add an extra node for the exponentiation operation over the function result. When about to add a prefix operator to the operator stack, we check whether it is a function, and whether it is followed by ** and an operand. If so, we clone the operator and store the operand into the power slot then remoe those two arguments from the rest of the input; effectively, we recognize this as a phrase structure. (detect-infix): We need a couple of rules here to detect infix expressions which use function power operators. * txr.1: Document function power operators as well as the new auto-detection rules. --- stdlib/infix.tl | 13 +++++++++++-- txr.1 | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/stdlib/infix.tl b/stdlib/infix.tl index 4fd343a1..ef27ca41 100644 --- a/stdlib/infix.tl +++ b/stdlib/infix.tl @@ -35,6 +35,7 @@ (arity :infix) prec funp + power (:postinit (self) (set [(if (meql self.arity :infix :postfix) ifx-ops ifx-uops) self.sym] self @@ -164,7 +165,10 @@ (flet ((add-node (oper) (ecaseql oper.arity ((:prefix :postfix) - (push (list oper.lispsym (pop nodestack)) nodestack)) + (push (list oper.lispsym (pop nodestack)) nodestack) + (if oper.power + (push ^(expt ,(pop nodestack) ,oper.power) + nodestack))) ((:infix) (let ((y (pop nodestack)) (x (pop nodestack))) @@ -194,6 +198,10 @@ (add-node o1) (set ucheck nil)) (t + (when-match (** @arg . @rrest) rest + (set o1 (copy o1) + o1.power arg + rest rrest)) (push o1 opstack) (set ucheck t))) (set exp rest)) @@ -236,12 +244,13 @@ (or (and xa (or yo yb)) (and xu ya (neq xu.sym xu.lispsym)) + (and xu (eq y '**) (eq 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 (funp env z))))) (or - (and xu yu (or zu za)) + (and xu yu (or zu za (eq z '**))) (and xu ya zo)))))))) (defun infix-expand-hook (exp env type-sym) diff --git a/txr.1 b/txr.1 index f4180651..3f5c79a0 100644 --- a/txr.1 +++ b/txr.1 @@ -54218,10 +54218,12 @@ denotes an infix operator and the letter .code A denotes an argument which is not the name of a global function, lexical function in the current macro environment, or operator. -Additionally, the letter -.code u* -indicates a prefix operator which is not also the name of a global or -lexical function. +Additionally, the symbols +.code f +and +.codn !f , +indicate a prefix operator which, respectively, is and is not, +the name of a gobal or lexical functionl. The patterns which indicate a form for processing via .code parse-infix are: @@ -54249,6 +54251,14 @@ operator. .coIP "(!f A ...)" A prefix operator which is not also the name of a global or lexical function, followed by an argument. +.coIP "(f ** ...)" +A prefix operator which is also the name of a function +followed by the power symbol +.codn ** . +.coIP "(u f **)" +A prefix operator, followed by a prefix operator which is also a function, +followed by the power symbol +.codn ** . .RE For instance, the form @@ -54511,6 +54521,22 @@ or can be invoked with one argument: tofloat toint trunc floor ceil round lognot .brev +For each of these operators, not shown in the above table, a corresponding +function power operator exists, allowing powers of the function to be notated. +The operator corresponds of any one of the above operators, followed by the +.code ** +operator symbol, followed by an operand. For instance the function power +operator +.code "sin ** x" +denotes the +.code sin +function raised to the power of +.codn x . +This three element sequence is effectively a single prefix operator with the +same precedence as the parent +.code sin +on which it is based. + The .code = prefix operator found at precedence level 0 denotes the -- cgit v1.2.3