summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c25
-rw-r--r--stdlib/doc-syms.tl2
-rw-r--r--txr.1254
3 files changed, 135 insertions, 146 deletions
diff --git a/eval.c b/eval.c
index 5b1f4818..fa78f52e 100644
--- a/eval.c
+++ b/eval.c
@@ -3132,6 +3132,20 @@ static val op_load_time_lit(val form, val env)
}
}
+static val me_macro_time(val form, val menv)
+{
+ val args = rest(form);
+ val result = nil;
+
+ for (; args; args = cdr(args)) {
+ val arg = car(args);
+ val arg_ex = expand(arg, menv);
+ result = eval(arg_ex, nil, args);
+ }
+
+ return maybe_quote(result);
+}
+
static val me_def_variable(val form, val menv)
{
val args = rest(form);
@@ -5146,15 +5160,6 @@ again:
cons(handle_syms,
if3(body == body_ex,
body, body_ex)))), form);
- } else if (sym == macro_time_s) {
- val args = rest(form);
- val result = nil;
- for (; args; args = cdr(args)) {
- val arg = car(args);
- val arg_ex = expand(arg, menv);
- result = eval(arg_ex, nil, args);
- }
- return maybe_quote(result);
} else if (sym == macrolet_s) {
return expand_macrolet(form, menv);
} else if (sym == symacrolet_s) {
@@ -6756,7 +6761,6 @@ void eval_init(void)
reg_op(macrolet_s, op_error);
reg_op(symacrolet_s, op_error);
- reg_op(macro_time_s, op_error);
reg_op(var_s, op_meta_error);
reg_op(expr_s, op_meta_error);
reg_op(quote_s, op_quote);
@@ -6812,6 +6816,7 @@ void eval_init(void)
reg_op(eval_only_s, op_progn);
reg_op(load_time_lit_s, op_load_time_lit);
+ reg_mac(macro_time_s, func_n2(me_macro_time));
reg_mac(defvar_s, me_def_variable_f);
reg_mac(defparm_s, me_def_variable_f);
reg_mac(defparml_s, me_def_variable_f);
diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl
index 6db5eecc..9f999aab 100644
--- a/stdlib/doc-syms.tl
+++ b/stdlib/doc-syms.tl
@@ -1183,7 +1183,7 @@
("mac-param-bind" "N-021A9008")
("macro-ancestor" "N-00519E96")
("macro-form-p" "N-02AC86DE")
- ("macro-time" "N-0264A0BD")
+ ("macro-time" "N-0131B069")
("macroexpand" "N-02ED5471")
("macroexpand-1" "N-02ED5471")
("macroexpand-1-lisp1" "N-01E62179")
diff --git a/txr.1 b/txr.1
index 13e7f38f..4be1b6ef 100644
--- a/txr.1
+++ b/txr.1
@@ -38618,137 +38618,6 @@ and binds to the entire
.code tree-bind
form.
-.coNP Operator @ macro-time
-.synb
-.mets (macro-time << form *)
-.syne
-.desc
-The
-.code macro-time
-operator has a syntax similar to the
-.code progn
-operator. Each
-.meta form
-is evaluated from left to right, and the resulting value is that of the last
-form.
-
-The special behavior of
-.code macro-time
-is that the evaluation takes place during
-the expansion phase, rather than during the evaluation phase.
-
-Also,
-.code macro-time
-macro-expands each
-.meta form
-and evaluates it before processing the next
-.meta form
-in the same way. Thus, for instance, if a
-.meta form
-introduces a global definition, that definition will be visible not
-only during the evaluation of a subsequent
-.metn form ,
-but also during its macro-expansion time.
-
-During the expansion phase, all
-.code macro-time
-expressions which occur in a context
-that calls for evaluation are evaluated, and replaced by their quoted values.
-For instance
-.code "(macro-time (list 1 2 3))"
-evaluates
-.code "(list 1 2 3)"
-to the object
-.code "(1 2 3)"
-and the entire
-.code macro-time
-form is replaced by that value, quoted:
-.codn "'(1 2 3)" .
-If the form is evaluated again at evaluation-time, the resulting value will be
-that of the quote, in this case
-.codn "(1 2 3)" .
-
-.code macro-time
-forms do not see the surrounding lexical environment; they see only
-global function and variable bindings and macros.
-
-Note:
-.code macro-time
-supports techniques that require a calculation to be performed in the
-environment where the program is being compiled, and inserting the result of
-that calculation as a literal into the program source. Possibly, the
-calculation can have some useful effect in that environment, or use
-as an input information that is available in that environment.
-The
-.code load-time
-operator also inserts a calculated value as a de facto
-literal into the program, but it performs that calculation in the
-environment where the compiled file is being loaded.
-The two operators may be considered complementary in this sense.
-
-Consider the source file:
-
-.verb
- (defun host-name-c () (macro-time (uname).nodename))
-
- (defun host-name-l () (load-time (uname).nodename))
-.brev
-
-If this is compiled via
-.codn compile-file ,
-the
-.code uname
-call in
-.code host-name-c
-takes place when it is macro-expanded. Thereafter, the compiled version
-of the function returns the name of the machine where the
-compilation took place, no matter in what environment it is subsequently
-loaded and called.
-
-In contrast, the compilation of
-.code host-name-l
-arranges for that function's
-.code uname
-call to take place just one time, whenever the compiled file is loaded.
-Each time the function is subsequently called, it will
-return the name of the machine where it was loaded, without making
-any additional calls to
-.codn uname .
-
-The
-.code macro-time
-operator can occasionally be required in order for some constructs to evaluate
-or compile. One way that occurs is when a construct that is being fully
-expanded itself defines a macro which is later required in that same construct.
-For example:
-
-.verb
- (progn (defmacro mac () 42) (mac))
-.brev
-
-This specific example actually works under
-.code eval
-or file compilation, because in that situation it isn't fully expanded
-all at once. When
-.code eval
-and
-.code compile-file
-process a top-level form that is a
-.codn progn ,
-they treat its argument forms as individual, separate top-level forms. In
-general, \*(TL is designed in such a way as to not to require, in most ordinary
-programs, extra verbiage to tell the compiler or evaluator that certain
-definitions are required by macros. However, somewhat unusual situations can
-arise which are not handled in this way.
-
-Also,
-.codn macro-time ,
-or the related
-.code @(mdo)
-directive, can be occasionally necessary in \*(TX
-queries, which are parsed and subject to macro-expansion in their entirety
-before being executed.
-
.coNP Operator @ defmacro
.synb
.mets (defmacro < name
@@ -39856,6 +39725,121 @@ emanating from the
.code delta
form.
+.coNP Macro @ macro-time
+.synb
+.mets (macro-time << form *)
+.syne
+.desc
+The
+.code macro-time
+macro evaluates its arguments immediately during macro expansion.
+
+The
+.meta form
+arguments are processed from left to right. Each
+.meta form
+is fully expanded and evaluated in the top-level environment
+before the next form is considered.
+
+The value of the last
+.metn form ,
+or else
+.code nil
+if there aren't any arguments, is converted into a literal expression
+which denotes that value, and the resulting literal is produced
+as the expansion of
+.metn macro-time .
+
+Note:
+.code macro-time
+supports techniques that require a calculation to be performed in the
+environment where the program is being compiled, and inserting the result of
+that calculation as a literal into the program source. Possibly, the
+calculation can have some useful effect in that environment, or use
+as an input information that is available in that environment.
+The
+.code load-time
+operator also inserts a calculated value as a de facto
+literal into the program, but it performs that calculation in the
+environment where the compiled file is being loaded.
+The two operators may be considered complementary in this sense.
+
+Consider the source file:
+
+.verb
+ (defun host-name-c () (macro-time (uname).nodename))
+
+ (defun host-name-l () (load-time (uname).nodename))
+.brev
+
+If this is compiled via
+.codn compile-file ,
+the
+.code uname
+call in
+.code host-name-c
+takes place when it is macro-expanded. Thereafter, the compiled version
+of the function returns the name of the machine where the
+compilation took place, no matter in what environment it is subsequently
+loaded and called.
+
+In contrast, the compilation of
+.code host-name-l
+arranges for that function's
+.code uname
+call to take place just one time, whenever the compiled file is loaded.
+Each time the function is subsequently called, it will
+return the name of the machine where it was loaded, without making
+any additional calls to
+.codn uname .
+
+Note:
+.code macro-time
+can be understood in terms of the following implementation. Note that
+this implementation always produces a
+.code quote
+expression, which
+.code macro-time
+is not required to do if
+.meta val
+is self-evaluating:
+
+.verb
+ (defmacro macro-time (. forms)
+ (let (val)
+ (each ((f forms))
+ (set val (eval f)))
+ ^(quote ,val)))
+.brev
+
+Because
+.code eval
+treats a top-level
+.code progn
+specially, this implementation is also possible:
+
+.verb
+ (defmacro macro-time (. forms)
+ ^(quote ,(eval ^(progn ,*forms))))
+.brev
+
+.TP* Examples:
+
+.verb
+ ;; The (1 2 3) object is produced at macro-expansion time, becoming
+ ;; a quoted literal which evaluates to (1 2 3).
+ (macro-time (list 1 2 3)) -> (1 2 3)
+
+ ;; The above fact is revealed by macroexpand: the list form was
+ ;; evaluated, and then quote was inserted to produce (quote (1 2 3))
+ ;; which is notated '(1 2 3):
+ (macroexpand '(macro-time (list 1 2 3))) -> '(1 2 3)
+
+ ;; Quote isn't required on a self-evaluating object; it serves
+ ;; as a literal expression denoting itself:
+ (macroexpand '(macro-time (join-with "-" "a" "b"))) -> "a-b"
+.brev
+
.coNP Macro @ equot
.synb
.mets (equot << form )
@@ -84832,14 +84816,14 @@ From time to time, certain situations benefit from the program being
able to perform an evaluation, and then have the result of that evaluation
treated as a literal.
-There is already an operator named
+The
.code macro-time
-which makes this possible in its particular manner: that operator
+macro makes this possible in its particular manner: that macro
allows one or more expressions to be evaluated during macro expansion.
The result of the
.code macro-time
is then quoted and substituted in place of the expression. That result
-then appears as a true quoted literal to the executing code.
+then appears as a true literal to the executing code.
The
.code load-time
@@ -85241,7 +85225,7 @@ a suffix that adds no value. Lastly,
.code load-time
is shorter, and harmonizes with
.codn macro-time ,
-which preceded it by four years.
+which existed earlier.
.coNP Function @ disassemble
.synb