summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-05-16 21:03:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-05-16 21:03:00 -0700
commitb1ed6c8d93d70a531af99963a245fc44c5f7855c (patch)
treeaed7914652dc9fac09f117b2fc903b2306f0dbcb
parentb4fbc45099b678583dc4e8b84a725adb5428a354 (diff)
downloadtxr-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.tl26
-rw-r--r--txr.164
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)))))))
diff --git a/txr.1 b/txr.1
index e8cbfc60..b18b529f 100644
--- a/txr.1
+++ b/txr.1
@@ -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