diff options
-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 |