summaryrefslogtreecommitdiffstats
path: root/txr.1
diff options
context:
space:
mode:
Diffstat (limited to 'txr.1')
-rw-r--r--txr.1260
1 files changed, 260 insertions, 0 deletions
diff --git a/txr.1 b/txr.1
index 34fac7dc..173c7e38 100644
--- a/txr.1
+++ b/txr.1
@@ -12463,6 +12463,8 @@ are both open-ended. Code can be written quite easily in \*(TL to introduce
new kinds of places, as well as new place-mutating operators.
New places can be introduced with the help of the
.code defplace
+or
+.code defset
macro, or possibly the
.code define-place-macro
macro in simple cases when a new syntactic place can be expressed as a
@@ -33470,6 +33472,8 @@ evaluations of the place form.
The programmer who implements a new place does not write expanders directly,
but rather defines them via the
.code defplace
+or
+.code defset
macro.
The programmer who implements a new place update macro likewise does not
@@ -34494,6 +34498,262 @@ cells:
,body)))
.cble
+.coNP Macro @ defset
+.synb
+.mets (defset < name < params < new-val-sym < get-form << set-form )
+.mets (defset < get-fun-sym << set-fun-sym )
+.syne
+.desc
+The
+.code defset
+macro provides a mechanism for introducing a new kind of syntactic place.
+It is simpler to use than
+.code defplace
+and more concise, but not as general.
+
+The
+.code defset
+macro is designed for situations in which a function or macro which evaluates
+all of its arguments is required to serve as a syntactic place.
+It provides two flavors of syntax: the long form, indicated by giving
+.code defset
+five arguments, and a short form, which uses two arguments.
+
+In the long form of
+.codn defset ,
+the syntactic place is described by
+.meta name
+and
+.metn params .
+The
+.code defset
+form expresses the request that call to the function or operator named
+.meta name
+is to be treated as a syntactic place, which has arguments described by
+the parameter list
+.metn params .
+
+The
+.meta new-val-sym
+parameter is the name of a symbol which will be bound to
+an expression which calculates the new value being stored into
+the syntactic place. This is intended to be referenced in the
+.meta set-form
+only, which should ensure that the expression that
+.meta new-val-sym
+holds is evaluated only once.
+
+The
+.meta get-form
+and
+.meta set-form
+arguments specify forms which generate the code for, respectively,
+accessing the value of the place, and storing a new value.
+
+The
+.code defset
+macro makes the necessary arrangements such that when an operator form
+named by
+.meta name
+is treated as a syntactic place, then at macro-expansion time, code is
+generated to evaluate all of its argument expressions into machine-generated
+variables. The names of those variables are automatically bound to the
+corresponding symbols given in the
+.meta params
+argument list of the
+.code defset
+syntax. Code is also generated to evaluate the expression which gives the
+new value to be stored, and that is bound to a generated variable whose
+name is bound to the
+.code new-val-sym
+symbol. Then arrangements are made to invoke the
+.code get-form
+and
+.code set-form
+in an environment in which these symbol bindings are visible. The task of
+these forms is to insert the values of the symbols from
+.meta params
+and
+.meta new-val-sym
+into suitable code templates that will perform the access and store actions.
+
+If
+.meta params
+list contains optional parameters, the default value expressions of those
+parameters shall be evaluated in the scope of the
+.code defset
+definition.
+
+The
+.meta params
+list may specify a rest parameter. In the expansion, this parameter will
+capture a list of temporary symbols, corresponding to the list of variadic
+argument expressions. For instance if the
+.code defset
+parameter list for a place
+.code g
+is
+.codn "(a b . c)" ,
+featuring the rest parameter
+.codn c ,
+and its
+.meta set-form
+is
+.code "^(s ,a ,b ,*c)"
+and the place is invoked as
+.code "(g (i) (j) (k) (l))"
+then parameter
+.code c
+will be bound to a list of gensyms such as
+.code "(#:g0123 #:g0124)"
+so that the evaluation of
+.meta set-form
+will yield syntax resembling
+.codn "(s #:g0121 #:g0122 #:g0123 #:g0124)" .
+Here, gensyms
+.code #:g0123
+and
+.code #:g0124
+are understood to be bound to the values of the expressions
+.code (k)
+and
+.codn (l) ,
+the two trailing parameters corresponding to the rest parameter
+.codn c .
+
+Syntactic places defined by
+.code defset
+may not use improper syntax such as
+.codn "(set (g 1 2 . 3) v)" .
+
+The short, two-argument form of
+.code defset
+simply specifies the names of two functions or operators:
+.code get-fun-sym
+names the operator which accesses the place, and
+.code set-fun-sym
+names the operator which stores a new value into the place.
+It is expected that all arguments of these operators are evaluated
+expressions, and that the store operator takes one argument more
+than the access operator. The operators are otherwise assumed to be
+variadic: each instance of a place based on
+.code get-fun-sym
+individually determines how many arguments are passed to that operator
+and to the one named by
+.codn set-fun-sym .
+
+The definition
+.code "(defset g s)"
+means that
+.code "(inc (g x y))"
+will generate code which ensures that
+.code x
+and
+.code y
+are evaluated exactly once, and then those two values are passed as
+arguments to
+.code g
+which returns the current value of the place. That value is then incremented
+by one, and stored into the place by calling the
+.code s
+function/operator with three arguments: the two values that were passed to
+.code g
+and the new value. The exact number of arguments is determined by each
+individual use of
+.code g
+as a place; the
+.code defset
+form doesn't specify the arity of
+.code g
+and
+.codn s ,
+only that
+.code s
+must accept one more argument relative to
+.codn g .
+
+The following equivalence holds between the short and long forms:
+
+.cblk
+ (defset g s) <--> (defset g (. r) n ^(g ,*r) ^(s ,*r ,n))
+.cble
+
+.TP* "Example:"
+
+Implementation of
+.code car
+as a syntactic place using a long form
+.codn defset :
+
+.cblk
+ (defset car (cell) new
+ ^(car ,cell)
+ (let ((n (gensym)))
+ ^(rlet ((,n ,new))
+ (progn (rplaca ,cell ,n) ,n))))
+.cble
+
+Given such a definition, the expression
+.code "(inc (car abc))"
+expands to code closely resembling:
+
+.cblk
+ (let ((#:g0014 (abc)))
+ (let ((#:g0028 (succ (car #:g0014))))
+ (rplaca #:g0014 #:g0028)
+ #:g0028))
+.cble
+
+The
+.code defset
+macro has arranged for the argument expression
+.code (abc)
+of
+.code car
+to be evaluated to a temporary variable
+.codn #:g0014 ,
+a
+.codn gensym .
+This, then, holds the
+.code cons
+cell being operated on.
+At macro-expansion time, the variable
+.code cell
+from the parameter list specified by the
+.code defset
+is bound to this symbol. The subexpression
+.code "(car #:0014)"
+is derived from the
+.meta get-form
+.code "^(car ,cell)"
+which inserted the value of
+.code cell
+into a backquote template, that value being the symbol
+.codn #:g0014 .
+The
+.code new
+variable was bound to the expression giving the new value, namely
+.codn "(succ (car #:g0014))" .
+The
+.meta set-form
+is careful to evaluate this only one time, storing its value into
+the temporary variable
+.codn #:g0028 ,
+referenced by the variable
+.codn n .
+The
+.metn set-form 's
+.code "(rplaca ,cell ,n)"
+fragment thus turned into
+.code "(rplaca #:g0014 #:g0028)"
+where
+.code #:g0014
+references the cons cell being operated on, and
+.code #:g0028
+the calculated new value to be stored into its
+.code car
+field.
+
.coNP Macro @ define-place-macro
.synb
.mets (define-place-macro < name < macro-style-params