summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-04-21 19:50:30 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-04-21 19:50:30 -0700
commitf5a32312e548375f59784109c281863f8ce9a63f (patch)
tree7825669ef2a295a2a7df6e70a3773ab3d27b750a
parentc08115d3b80705423034a72e4af1090120da9b21 (diff)
downloadtxr-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.tl13
-rw-r--r--txr.134
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