Skip to content

Commit 70aa61c

Browse files
authored
Warn when emitting code which uses Var indirection (#306)
1 parent 9d26c26 commit 70aa61c

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

src/basilisp/cli.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,23 @@ def bootstrap_repl(which_ns: str) -> types.ModuleType:
6666
is_flag=True,
6767
envvar='BASILISP_WARN_ON_SHADOWED_VAR',
6868
help='if provided, emit warnings if a Var name is shadowed by a local name')
69-
def repl(default_ns, use_var_indirection, warn_on_shadowed_name, warn_on_shadowed_var):
69+
@click.option('--warn-on-var-indirection',
70+
default=True,
71+
is_flag=True,
72+
envvar='BASILISP_WARN_ON_VAR_INDIRECTION',
73+
help='if provided, emit warnings if a Var reference cannot be direct linked')
74+
def repl(default_ns,
75+
use_var_indirection,
76+
warn_on_shadowed_name,
77+
warn_on_shadowed_var,
78+
warn_on_var_indirection):
7079
basilisp.init()
7180
repl_module = bootstrap_repl(default_ns)
7281
ctx = compiler.CompilerContext(
7382
{compiler.USE_VAR_INDIRECTION: use_var_indirection,
7483
compiler.WARN_ON_SHADOWED_NAME: warn_on_shadowed_name,
75-
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var})
84+
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var,
85+
compiler.WARN_ON_VAR_INDIRECTION: warn_on_var_indirection})
7686
ns_var = runtime.set_current_ns(default_ns)
7787
eof = object()
7888
while True:
@@ -128,18 +138,25 @@ def repl(default_ns, use_var_indirection, warn_on_shadowed_name, warn_on_shadowe
128138
is_flag=True,
129139
envvar='BASILISP_WARN_ON_SHADOWED_VAR',
130140
help='if provided, emit warnings if a Var name is shadowed by a local name')
141+
@click.option('--warn-on-var-indirection',
142+
default=True,
143+
is_flag=True,
144+
envvar='BASILISP_WARN_ON_VAR_INDIRECTION',
145+
help='if provided, emit warnings if a Var reference cannot be direct linked')
131146
def run(file_or_code, # pylint: disable=too-many-arguments
132147
code,
133148
in_ns,
134149
use_var_indirection,
135150
warn_on_shadowed_name,
136-
warn_on_shadowed_var):
151+
warn_on_shadowed_var,
152+
warn_on_var_indirection):
137153
"""Run a Basilisp script or a line of code, if it is provided."""
138154
basilisp.init()
139155
ctx = compiler.CompilerContext(
140156
{compiler.USE_VAR_INDIRECTION: use_var_indirection,
141157
compiler.WARN_ON_SHADOWED_NAME: warn_on_shadowed_name,
142-
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var})
158+
compiler.WARN_ON_SHADOWED_VAR: warn_on_shadowed_var,
159+
compiler.WARN_ON_VAR_INDIRECTION: warn_on_var_indirection})
143160
eof = object()
144161

145162
with runtime.ns_bindings(in_ns) as ns:

src/basilisp/lang/compiler.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
USE_VAR_INDIRECTION = 'use_var_indirection'
4343
WARN_ON_SHADOWED_NAME = 'warn_on_shadowed_name'
4444
WARN_ON_SHADOWED_VAR = 'warn_on_shadowed_var'
45+
WARN_ON_VAR_INDIRECTION = 'warn_on_var_indirection'
4546

4647
_BUILTINS_NS = 'builtins'
4748
_CORE_NS = 'basilisp.core'
@@ -185,6 +186,12 @@ def warn_on_shadowed_var(self) -> bool:
185186
supersedes the value of this flag."""
186187
return self.warn_on_shadowed_name or self._opts.entry(WARN_ON_SHADOWED_VAR, True)
187188

189+
@property
190+
def warn_on_var_indirection(self) -> bool:
191+
"""If True, warn when a Var reference cannot be direct linked (iff
192+
use_var_indirection is False).."""
193+
return not self.use_var_indirection and self._opts.entry(WARN_ON_VAR_INDIRECTION, True)
194+
188195
@property
189196
def recur_point(self):
190197
return self._recur_points[-1]
@@ -1699,6 +1706,9 @@ def _sym_ast(ctx: CompilerContext, form: sym.Symbol) -> ASTStream:
16991706
return
17001707

17011708
# If we couldn't find the symbol anywhere else, generate a Var.find call
1709+
# and issue a warning if warn_on_var_indirection is active.
1710+
if ctx.warn_on_var_indirection:
1711+
logger.warning(f"could not resolve a direct link to Var '{form}'")
17021712
yield _node(ast.Attribute(
17031713
value=ast.Call(func=_FIND_VAR_FN_NAME, args=[base_sym], keywords=[]),
17041714
attr='value',

tests/basilisp/compiler_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,17 @@ def test_try_catch(capsys, ns: runtime.Namespace):
868868
assert "neither\n" == captured.out
869869

870870

871+
def test_warn_on_var_indirection(ns: runtime.Namespace):
872+
with mock.patch('basilisp.lang.compiler.logger') as logger:
873+
lcompile("(fn [] m)",
874+
ctx=compiler.CompilerContext({compiler.WARN_ON_VAR_INDIRECTION: False}))
875+
logger.warning.assert_not_called()
876+
877+
with mock.patch('basilisp.lang.compiler.logger') as logger:
878+
lcompile("(fn [] m)")
879+
logger.warning.assert_called_once_with("could not resolve a direct link to Var 'm'")
880+
881+
871882
def test_unquote(ns: runtime.Namespace):
872883
with pytest.raises(runtime.RuntimeException):
873884
lcompile("~s")

0 commit comments

Comments
 (0)