Skip to content

Commit 44e140a

Browse files
authored
Intern *compiler-options* so it can be reused on require (#507)
* Intern *compiler-options* so it can be reused on require * Slightly refactor stuff * Munge and de-munge compiler options into keywords * Use keywords rather than strings for compiler options * Debug log
1 parent 06d7861 commit 44e140a

File tree

14 files changed

+135
-71
lines changed

14 files changed

+135
-71
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
* Fixed a reader bug where no exception was being thrown splicing reader conditional forms appeared outside of valid splicing contexts (#470)
2929
* Fixed a bug where fully Namespace-qualified symbols would not resolve if the current Namespace did not alias the referenced Namespace (#479)
3030
* Fixed a bug where the `quote` special form allowed more than one argument and raised an unintended exception when no argument was provided (#497)
31+
* Fixed a bug where compiler options specified via command-line argument or environment variable were not honored by the importer (#???)
3132

3233
## [v0.1.dev12] - 2020-01-26
3334
### Added

src/basilisp/cli.py

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,51 +66,58 @@ def bootstrap_repl(ctx: compiler.CompilerContext, which_ns: str) -> types.Module
6666
default=runtime.REPL_DEFAULT_NS,
6767
help="default namespace to use for the REPL",
6868
)
69-
@click.option(
70-
"--use-var-indirection",
71-
default=False,
72-
is_flag=True,
73-
envvar="BASILISP_USE_VAR_INDIRECTION",
74-
help="if provided, all Var accesses will be performed via Var indirection",
75-
)
7669
@click.option(
7770
"--warn-on-shadowed-name",
78-
default=False,
71+
default=None,
7972
is_flag=True,
8073
envvar="BASILISP_WARN_ON_SHADOWED_NAME",
8174
help="if provided, emit warnings if a local name is shadowed by another local name",
8275
)
8376
@click.option(
8477
"--warn-on-shadowed-var",
85-
default=False,
78+
default=None,
8679
is_flag=True,
8780
envvar="BASILISP_WARN_ON_SHADOWED_VAR",
8881
help="if provided, emit warnings if a Var name is shadowed by a local name",
8982
)
83+
@click.option(
84+
"--warn-on-unused-names",
85+
default=None,
86+
is_flag=True,
87+
envvar="BASILISP_WARN_ON_UNUSED_NAMES",
88+
help="if provided, emit warnings if a local name is bound and unused",
89+
)
90+
@click.option(
91+
"--use-var-indirection",
92+
default=None,
93+
is_flag=True,
94+
envvar="BASILISP_USE_VAR_INDIRECTION",
95+
help="if provided, all Var accesses will be performed via Var indirection",
96+
)
9097
@click.option(
9198
"--warn-on-var-indirection",
92-
default=True,
99+
default=None,
93100
is_flag=True,
94101
envvar="BASILISP_WARN_ON_VAR_INDIRECTION",
95102
help="if provided, emit warnings if a Var reference cannot be direct linked",
96103
)
97-
def repl(
104+
def repl( # pylint: disable=too-many-arguments,too-many-locals
98105
default_ns,
99-
use_var_indirection,
100106
warn_on_shadowed_name,
101107
warn_on_shadowed_var,
108+
warn_on_unused_names,
109+
use_var_indirection,
102110
warn_on_var_indirection,
103111
):
104-
basilisp.init()
105-
ctx = compiler.CompilerContext(
106-
filename=REPL_INPUT_FILE_PATH,
107-
opts={
108-
compiler.WARN_ON_SHADOWED_NAME: warn_on_shadowed_name,
109-
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var,
110-
compiler.USE_VAR_INDIRECTION: use_var_indirection,
111-
compiler.WARN_ON_VAR_INDIRECTION: warn_on_var_indirection,
112-
},
112+
opts = compiler.compiler_opts(
113+
warn_on_shadowed_name=warn_on_shadowed_name,
114+
warn_on_shadowed_var=warn_on_shadowed_var,
115+
warn_on_unused_names=warn_on_unused_names,
116+
use_var_indirection=use_var_indirection,
117+
warn_on_var_indirection=warn_on_var_indirection,
113118
)
119+
basilisp.init(opts)
120+
ctx = compiler.CompilerContext(filename=REPL_INPUT_FILE_PATH, opts=opts)
114121
repl_module = bootstrap_repl(ctx, default_ns)
115122
ns_var = runtime.set_current_ns(default_ns)
116123
prompter = get_prompter()
@@ -156,30 +163,37 @@ def repl(
156163
@click.option(
157164
"--in-ns", default=runtime.REPL_DEFAULT_NS, help="namespace to use for the code"
158165
)
159-
@click.option(
160-
"--use-var-indirection",
161-
default=False,
162-
is_flag=True,
163-
envvar="BASILISP_USE_VAR_INDIRECTION",
164-
help="if provided, all Var accesses will be performed via Var indirection",
165-
)
166166
@click.option(
167167
"--warn-on-shadowed-name",
168-
default=False,
168+
default=None,
169169
is_flag=True,
170170
envvar="BASILISP_WARN_ON_SHADOWED_NAME",
171171
help="if provided, emit warnings if a local name is shadowed by another local name",
172172
)
173173
@click.option(
174174
"--warn-on-shadowed-var",
175-
default=False,
175+
default=None,
176176
is_flag=True,
177177
envvar="BASILISP_WARN_ON_SHADOWED_VAR",
178178
help="if provided, emit warnings if a Var name is shadowed by a local name",
179179
)
180+
@click.option(
181+
"--warn-on-unused-names",
182+
default=None,
183+
is_flag=True,
184+
envvar="BASILISP_WARN_ON_UNUSED_NAMES",
185+
help="if provided, emit warnings if a local name is bound and unused",
186+
)
187+
@click.option(
188+
"--use-var-indirection",
189+
default=None,
190+
is_flag=True,
191+
envvar="BASILISP_USE_VAR_INDIRECTION",
192+
help="if provided, all Var accesses will be performed via Var indirection",
193+
)
180194
@click.option(
181195
"--warn-on-var-indirection",
182-
default=True,
196+
default=None,
183197
is_flag=True,
184198
envvar="BASILISP_WARN_ON_VAR_INDIRECTION",
185199
help="if provided, emit warnings if a Var reference cannot be direct linked",
@@ -188,25 +202,28 @@ def run( # pylint: disable=too-many-arguments
188202
file_or_code,
189203
code,
190204
in_ns,
191-
use_var_indirection,
192205
warn_on_shadowed_name,
193206
warn_on_shadowed_var,
207+
warn_on_unused_names,
208+
use_var_indirection,
194209
warn_on_var_indirection,
195210
):
196211
"""Run a Basilisp script or a line of code, if it is provided."""
197-
basilisp.init()
212+
opts = compiler.compiler_opts(
213+
warn_on_shadowed_name=warn_on_shadowed_name,
214+
warn_on_shadowed_var=warn_on_shadowed_var,
215+
warn_on_unused_names=warn_on_unused_names,
216+
use_var_indirection=use_var_indirection,
217+
warn_on_var_indirection=warn_on_var_indirection,
218+
)
219+
basilisp.init(opts)
198220
ctx = compiler.CompilerContext(
199221
filename=CLI_INPUT_FILE_PATH
200222
if code
201223
else (
202224
STDIN_INPUT_FILE_PATH if file_or_code == STDIN_FILE_NAME else file_or_code
203225
),
204-
opts={
205-
compiler.WARN_ON_SHADOWED_NAME: warn_on_shadowed_name,
206-
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var,
207-
compiler.USE_VAR_INDIRECTION: use_var_indirection,
208-
compiler.WARN_ON_VAR_INDIRECTION: warn_on_var_indirection,
209-
},
226+
opts=opts,
210227
)
211228
eof = object()
212229

src/basilisp/importer.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ def _exec_cached_module(
252252
)
253253
compiler.compile_bytecode(
254254
cached_code,
255-
compiler.GeneratorContext(filename=filename),
255+
compiler.GeneratorContext(
256+
filename=filename, opts=runtime.get_compiler_opts()
257+
),
256258
compiler.PythonASTOptimizer(),
257259
ns,
258260
)
@@ -288,7 +290,9 @@ def _exec_module(
288290
)
289291
compiler.compile_module( # pylint: disable=unexpected-keyword-arg
290292
forms,
291-
compiler.CompilerContext(filename=filename),
293+
compiler.CompilerContext(
294+
filename=filename, opts=runtime.get_compiler_opts()
295+
),
292296
ns,
293297
collect_bytecode=all_bytecode.append,
294298
)

src/basilisp/lang/compiler/__init__.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import itertools
22
import os
33
import types
4-
from typing import Any, Callable, Iterable, List, Mapping, Optional
4+
from typing import Any, Callable, Iterable, List, Optional
55

66
from astor import code_gen as codegen
77

88
import basilisp._pyast as ast
9+
import basilisp.lang.map as lmap
910
import basilisp.lang.runtime as runtime
1011
from basilisp.lang.compiler.analyzer import ( # noqa
1112
WARN_ON_SHADOWED_NAME,
@@ -28,7 +29,7 @@
2829
statementize as _statementize,
2930
)
3031
from basilisp.lang.compiler.optimizer import PythonASTOptimizer
31-
from basilisp.lang.typing import ReaderForm
32+
from basilisp.lang.typing import CompilerOpts, ReaderForm
3233
from basilisp.lang.util import genname
3334

3435
_DEFAULT_FN = "__lisp_expr__"
@@ -40,13 +41,13 @@ def to_py_str(t: ast.AST) -> str:
4041
return codegen.to_source(t)
4142

4243

43-
BytecodeCollector = Optional[Callable[[types.CodeType], None]]
44+
BytecodeCollector = Callable[[types.CodeType], None]
4445

4546

4647
class CompilerContext:
4748
__slots__ = ("_filename", "_actx", "_gctx", "_optimizer")
4849

49-
def __init__(self, filename: str, opts: Optional[Mapping[str, bool]] = None):
50+
def __init__(self, filename: str, opts: Optional[CompilerOpts] = None):
5051
self._filename = filename
5152
self._actx = AnalyzerContext(filename=filename, opts=opts)
5253
self._gctx = GeneratorContext(filename=filename, opts=opts)
@@ -69,6 +70,27 @@ def py_ast_optimizer(self) -> PythonASTOptimizer:
6970
return self._optimizer
7071

7172

73+
def compiler_opts(
74+
warn_on_shadowed_name: Optional[bool] = None,
75+
warn_on_shadowed_var: Optional[bool] = None,
76+
warn_on_unused_names: Optional[bool] = None,
77+
use_var_indirection: Optional[bool] = None,
78+
warn_on_var_indirection: Optional[bool] = None,
79+
) -> CompilerOpts:
80+
"""Return a map of compiler options with defaults applied."""
81+
return lmap.map(
82+
{
83+
# Analyzer options
84+
WARN_ON_SHADOWED_NAME: warn_on_shadowed_name or False,
85+
WARN_ON_SHADOWED_VAR: warn_on_shadowed_var or False,
86+
WARN_ON_UNUSED_NAMES: warn_on_unused_names or True,
87+
# Generator options
88+
USE_VAR_INDIRECTION: use_var_indirection or False,
89+
WARN_ON_VAR_INDIRECTION: warn_on_var_indirection or True,
90+
}
91+
)
92+
93+
7294
def _emit_ast_string(
7395
ns: runtime.Namespace, module: ast.AST,
7496
) -> None: # pragma: no cover

src/basilisp/lang/compiler/analyzer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,17 @@
120120
)
121121
from basilisp.lang.interfaces import IMeta, IRecord, ISeq, IType, IWithMeta
122122
from basilisp.lang.runtime import Var
123-
from basilisp.lang.typing import LispForm, ReaderForm
123+
from basilisp.lang.typing import CompilerOpts, LispForm, ReaderForm
124124
from basilisp.lang.util import count, genname, munge
125125
from basilisp.util import Maybe, partition
126126

127127
# Analyzer logging
128128
logger = logging.getLogger(__name__)
129129

130130
# Analyzer options
131-
WARN_ON_SHADOWED_NAME = "warn_on_shadowed_name"
132-
WARN_ON_SHADOWED_VAR = "warn_on_shadowed_var"
133-
WARN_ON_UNUSED_NAMES = "warn_on_unused_names"
131+
WARN_ON_SHADOWED_NAME = kw.keyword("warn-on-shadowed-name")
132+
WARN_ON_SHADOWED_VAR = kw.keyword("warn-on-shadowed-var")
133+
WARN_ON_UNUSED_NAMES = kw.keyword("warn-on-unused-names")
134134

135135
# Lisp AST node keywords
136136
INIT = kw.keyword("init")
@@ -295,7 +295,7 @@ class AnalyzerContext:
295295
def __init__(
296296
self,
297297
filename: Optional[str] = None,
298-
opts: Optional[Mapping[str, bool]] = None,
298+
opts: Optional[CompilerOpts] = None,
299299
should_macroexpand: bool = True,
300300
allow_unresolved_symbols: bool = False,
301301
) -> None:

src/basilisp/lang/compiler/generator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@
9999
BasilispModule,
100100
Var,
101101
)
102-
from basilisp.lang.typing import LispForm
102+
from basilisp.lang.typing import CompilerOpts, LispForm
103103
from basilisp.lang.util import count, genname, munge
104104
from basilisp.util import Maybe
105105

106106
# Generator logging
107107
logger = logging.getLogger(__name__)
108108

109109
# Generator options
110-
USE_VAR_INDIRECTION = "use_var_indirection"
111-
WARN_ON_VAR_INDIRECTION = "warn_on_var_indirection"
110+
USE_VAR_INDIRECTION = kw.keyword("use-var-indirection")
111+
WARN_ON_VAR_INDIRECTION = kw.keyword("warn-on-var-indirection")
112112

113113
# String constants used in generating code
114114
_DEFAULT_FN = "__lisp_expr__"
@@ -203,7 +203,7 @@ class GeneratorContext:
203203
)
204204

205205
def __init__(
206-
self, filename: Optional[str] = None, opts: Optional[Mapping[str, bool]] = None
206+
self, filename: Optional[str] = None, opts: Optional[CompilerOpts] = None
207207
) -> None:
208208
self._filename = Maybe(filename).or_else_get(DEFAULT_COMPILER_FILE_PATH)
209209
self._opts = Maybe(opts).map(lmap.map).or_else_get(lmap.m()) # type: ignore
@@ -214,7 +214,7 @@ def __init__(
214214

215215
if logger.isEnabledFor(logging.DEBUG): # pragma: no cover
216216
for k, v in self._opts:
217-
logger.debug("Compiler option %s=%s", k, v)
217+
logger.debug("Compiler option %s = %s", k, v)
218218

219219
@property
220220
def current_ns(self) -> runtime.Namespace:

0 commit comments

Comments
 (0)