diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-05-16 21:03:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-05-16 21:03:00 -0700 |
commit | b1ed6c8d93d70a531af99963a245fc44c5f7855c (patch) | |
tree | aed7914652dc9fac09f117b2fc903b2306f0dbcb | |
parent | b4fbc45099b678583dc4e8b84a725adb5428a354 (diff) | |
download | txr-b1ed6c8d93d70a531af99963a245fc44c5f7855c.tar.gz txr-b1ed6c8d93d70a531af99963a245fc44c5f7855c.tar.bz2 txr-b1ed6c8d93d70a531af99963a245fc44c5f7855c.zip |
with-compile-options: reimplement using compiler-let
The with-compile-opts macro is rewritten such that
it cad occur inside code that is being compiled, and
change compiler options for individual subexpressions.
It continues to work as before in scripted build steps
such as when calls to (compile-file ...) are wrapped
in it. However, for the time being, that now only works
in interpreted code, because with this change, when
a with-compile-opts form is compiled, it no longer
arranges for the binding of *compile-opts* to be visible
to the subforms; the binding affects the compiler's
own environment.
* stdlib/compiler.tl (with-compile-opts): Rewrite.
* txr.1: Documented.
-rw-r--r-- | stdlib/compiler.tl | 26 | ||||
-rw-r--r-- | txr.1 | 64 |
2 files changed, 64 insertions, 26 deletions
diff --git a/stdlib/compiler.tl b/stdlib/compiler.tl index 504d3ea8..c5d00612 100644 --- a/stdlib/compiler.tl +++ b/stdlib/compiler.tl @@ -2609,15 +2609,17 @@ (@else (error "~s: cannot compile ~s" 'compile else)))) (defmacro usr:with-compile-opts (:form form . clauses) - (with-gensyms (co) - ^(let* ((,co (copy *compile-opts*)) - (*compile-opts* ,co)) - ,*(collect-each ((cl clauses)) - (match-case cl - ((@(as op @(or nil t :warn :error)) . @syms) - (each ((s syms)) - (unless (member s %warning-syms%) - (compile-error form "~s isn't a recognized warning option" s))) - ^(set ,*(mappend (ret ^((qref ,co ,@1) ,op)) syms))) - (@(or @(atom) (@(not @(keywordp)) . @nil)) cl) - (@nil (compile-error form "unrecognized clause syntax: ~s" cl))))))) + (match-case clauses + (() ()) + (((@(as op @(or nil t :warn :error)) . @syms) . @rest) + (each ((s syms)) + (unless (member s %warning-syms%) + (compile-error form + "~s isn't a recognized warning option" s))) + ^(compiler-let ((*compile-opts* (let ((co (copy *compile-opts*))) + (set ,*(mappend (ret ^(co.,@1 ,op)) + syms)) + co))) + ,*(if rest ^((with-compile-opts ,*rest))))) + ((@first . @rest) + ^(progn ,first ,*(if rest ^((with-compile-opts ,*rest))))))) @@ -88166,27 +88166,52 @@ The macro takes zero or more arguments. Each argument is either a clause which affects compiler options or else an ordinary .meta form -which is evaluated in a context in which the +which is processed in a context in which the .code *compile-options* variable has been affected by all of the previous clauses. -The +It is unspecified whether the clauses operate destructively on +.code *compile-options* +or freshly bind it. However, the macro dynamically binds +.code *compile-options* +at least once, so that when it terminates, its previous value is restored. +This binding is performed using +.codn compiler-let . + +When .code with-compile-opts -macro arranges for +occurs in code processed by the compiler, all of the clause-driven compile +option manipulation is performed in the compiler's own context. The changes +to the .code *compile-options* -to be freshly bound, as if by the -.code let -operator. The variable is then given a value which is a copy of the -previous binding. -The option-affecting clauses then operate destructively on this copy. -When the macro terminates, the binding is undone and thus the -prior value of +variable are not visible to the code being compiled. Thus the macro may be +used to transparently change compiler options over individual subexpressions in +compiled code. + +When +.code with-compile-opts +occurs in interpreted code, the manipulations of .code *compile-options* -is restored. +are visible to the +.metn form s. +This allows interpreted build steps to configure compiler options +around functions such as +.codn compile-file . -The clauses which operate on options have the syntax of a value followed by one -or more symbols which must be the names of options which are compatible with -that value. The clause indicates that all those options take on that value. +The clauses which operate on options have list syntax consisting of a value +followed by one or more symbols which must be the names of options which are +compatible with that value. The clause indicates that all those options take on +that value. + +The possible values are: +.codn nil , +.codn t , +.code :warn +and +.codn :error . +These values are documented under the description of the +.code compile-opts +structure. .TP* Example: @@ -88198,12 +88223,23 @@ treated as error, but unused variable checking disabled. Then compile with unused variable checking enabled. .verb + ;; this form must be interpreted in order for + ;; the compile-file call to "see" the effect of the + ;; option manipulation. (with-compile-opts (:error shadow-var shadow-fun) (nil unused) (compile-file "foo.tl") (:warn unused) (compile-file "bar.tl")) + + ;; when the following form is compiled, the unused + ;; variable warning will be disabled just around + ;; the (let (y) x). + (lambda (x) + (with-compile-opts (nil unused) + (let (y) x))) + .brev .coNP Operator @ compiler-let |