summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-05-02 12:46:06 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-05-02 12:46:06 -0700
commitf2f8a4d7738988533bca6687e94b561dd73f5e93 (patch)
treed012bb7d1991efa1dc3f98ed47a0c9fa8e22b2b3
parent60fd266c43615f60fb4ff9bb1ae2cada08cf1f07 (diff)
downloadtxr-f2f8a4d7738988533bca6687e94b561dd73f5e93.tar.gz
txr-f2f8a4d7738988533bca6687e94b561dd73f5e93.tar.bz2
txr-f2f8a4d7738988533bca6687e94b561dd73f5e93.zip
compiler: treat nested load-time forms.
load-time forms nested in load-time forms have no special semantics; it's wasteful to separately hoist them into load time and store their value in their own D register. We must be careful: this is not true if a nested form occurs in a lambda. * share/txr/stdlib/compiler.tl (*load-time*): New special variable. (compiler comp-lambda): Bind *load-time* to nil around the compilation of the lambda, so load-time forms in the lambda are hoisted to load time, even if the lambda itself is wrapped in a load-time form. (compiler comp-load-time-lit): Bind *load-time* true around the compilation of the form. If *load-time* is already true, then skip the special load-time logic and just compile the enclosed form; the surrounding load-time compilation is taking care of the load-time hoisting. * txr.1: Document that load-time forms nested in load-time forms don't do anything, except in the lambda case.
-rw-r--r--share/txr/stdlib/compiler.tl33
-rw-r--r--txr.146
2 files changed, 65 insertions, 14 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index ca86db11..f1c4ca09 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -199,6 +199,8 @@
(defvar *dedup*)
+(defvar *load-time*)
+
(defun dedup (obj)
(cond
((null obj) nil)
@@ -815,7 +817,8 @@
(defmeth compiler comp-lambda (me oreg env form)
(mac-param-bind form (op par-syntax . body) form
- (let* ((pars (new (fun-param-parser par-syntax form)))
+ (let* ((*load-time* nil)
+ (pars (new (fun-param-parser par-syntax form)))
(need-frame (or (plusp pars.nfix) pars.rest))
(nenv (if need-frame (new env up env co me) env))
lexsyms fvars specials need-dframe)
@@ -1239,19 +1242,21 @@
(defmeth compiler comp-load-time-lit (me oreg env form)
(mac-param-bind form (op loaded-p exp) form
- (if loaded-p
- me.(compile oreg env ^(quote ,exp))
- (compile-in-toplevel me
- (let* ((dreg me.(alloc-dreg))
- (exp me.(compile dreg (new env co me) exp))
- (lt-frag (new (frag dreg
- ^(,*exp.code
- ,*(maybe-mov dreg exp.oreg))
- exp.fvars
- exp.ffuns))))
- (misleading-ref-check exp env form)
- (push lt-frag me.lt-frags)
- (new (frag dreg nil)))))))
+ (cond
+ (loaded-p me.(compile oreg env ^(quote ,exp)))
+ (*load-time* me.(compile oreg env exp))
+ (t (compile-in-toplevel me
+ (let* ((*load-time* t)
+ (dreg me.(alloc-dreg))
+ (exp me.(compile dreg (new env co me) exp))
+ (lt-frag (new (frag dreg
+ ^(,*exp.code
+ ,*(maybe-mov dreg exp.oreg))
+ exp.fvars
+ exp.ffuns))))
+ (misleading-ref-check exp env form)
+ (push lt-frag me.lt-frags)
+ (new (frag dreg nil))))))))
(defun maybe-mov (to-reg from-reg)
(if (nequal to-reg from-reg)
diff --git a/txr.1 b/txr.1
index e6f39589..c8da18f7 100644
--- a/txr.1
+++ b/txr.1
@@ -71443,6 +71443,52 @@ the immediately enclosing form which surrounds the
.code load-time
form.
+A
+.code load-time
+form may be nested inside another
+.code load-time
+form. In this situation, two cases occur.
+
+If the two forms are not embedded in a
+.codn lambda ,
+or else are embedded in the same
+.codn lambda ,
+then the inner
+.code load-time
+form is superfluous due to the presence of the outer
+.codn load-time .
+That is to say, the inner
+.mono
+.meti (load-time << form )
+.onom
+expression is equivalent to
+.metn form ,
+because the outer form already establishes its evaluation to be in a load-time
+context.
+
+If the inner
+.code load-time
+form occurs in a
+.codn lambda ,
+but the outer form occurs outside of that
+.codn lambda ,
+then the semantics of the inner
+.code load-time
+form is relevant and necessary. This is because expressions occurring in a
+.code lambda
+are evaluated when the
+.code lambda
+is called, which may take place from a non-load-time context, even if the
+.code lambda
+itself was produced in a load-time context.
+
+An expression being embedded in a
+.code lambda
+means that it appears either in the
+.code lambda
+body, or else in the parameter list as the initializing
+expression for an optional parameter.
+
.TP* Notes:
When interpreted code containing