diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-04-21 19:50:30 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-04-21 19:50:30 -0700 |
commit | f5a32312e548375f59784109c281863f8ce9a63f (patch) | |
tree | 7825669ef2a295a2a7df6e70a3773ab3d27b750a | |
parent | c08115d3b80705423034a72e4af1090120da9b21 (diff) | |
download | txr-f5a32312e548375f59784109c281863f8ce9a63f.tar.gz txr-f5a32312e548375f59784109c281863f8ce9a63f.tar.bz2 txr-f5a32312e548375f59784109c281863f8ce9a63f.zip |
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.
-rw-r--r-- | stdlib/infix.tl | 13 | ||||
-rw-r--r-- | 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) @@ -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 |