diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-05-02 12:46:06 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-05-02 12:46:06 -0700 |
commit | f2f8a4d7738988533bca6687e94b561dd73f5e93 (patch) | |
tree | d012bb7d1991efa1dc3f98ed47a0c9fa8e22b2b3 | |
parent | 60fd266c43615f60fb4ff9bb1ae2cada08cf1f07 (diff) | |
download | txr-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.tl | 33 | ||||
-rw-r--r-- | txr.1 | 46 |
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) @@ -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 |