Skip to content

Commit 9d13f39

Browse files
authored
Return a useful error message if a Var isn't found (#201)
1 parent 3409831 commit 9d13f39

File tree

3 files changed

+19
-7
lines changed

3 files changed

+19
-7
lines changed

src/basilisp/compiler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ def _expressionize(body: MixedNodeStream,
400400
_NEW_UUID_FN_NAME = _load_attr(f'{_UTIL_ALIAS}.uuid_from_str')
401401
_NEW_VEC_FN_NAME = _load_attr(f'{_VEC_ALIAS}.vector')
402402
_INTERN_VAR_FN_NAME = _load_attr(f'{_VAR_ALIAS}.intern')
403-
_FIND_VAR_FN_NAME = _load_attr(f'{_VAR_ALIAS}.find')
403+
_FIND_VAR_FN_NAME = _load_attr(f'{_VAR_ALIAS}.find_safe')
404404
_COLLECT_ARGS_FN_NAME = _load_attr(f'{_RUNTIME_ALIAS}._collect_args')
405405
_COERCE_SEQ_FN_NAME = _load_attr(f'{_RUNTIME_ALIAS}.to_seq')
406406
_TRAMPOLINE_FN_NAME = _load_attr(f'{_RUNTIME_ALIAS}._trampoline')
@@ -570,7 +570,7 @@ def _is_sym_macro(ctx: CompilerContext, form: sym.Symbol) -> bool:
570570
ns_sym = sym.symbol(form.ns)
571571
if ns_sym in ctx.current_ns.aliases:
572572
aliased_ns = ctx.current_ns.aliases[ns_sym]
573-
v = Var.find(sym.symbol(form.name, ns=aliased_ns))
573+
v = Var.find(sym.symbol(form.name, ns=aliased_ns.name))
574574
if v is not None:
575575
return _is_macro(v)
576576

src/basilisp/lang/runtime.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ def find(ns_qualified_sym: sym.Symbol) -> "Optional[Var]":
189189
name_sym = sym.symbol(ns_qualified_sym.name)
190190
return Var.find_in_ns(ns_sym, name_sym)
191191

192+
@staticmethod
193+
def find_safe(ns_qualified_sym: sym.Symbol) -> "Var":
194+
"""Return the Var currently bound to the name in the namespace specified
195+
by `ns_qualified_sym`. If no Var is bound to that name, raise an exception.
196+
197+
This is a utility method to return useful debugging information when code
198+
refers to an invalid symbol at runtime."""
199+
v = Var.find(ns_qualified_sym)
200+
if v is None:
201+
raise RuntimeException(f"Unable to resolve symbol {ns_qualified_sym} in this context")
202+
return v
203+
192204

193205
class Namespace:
194206
"""Namespaces serve as organizational units in Basilisp code, just as

tests/basilisp/compiler_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ def test_interop_new(ns_var: Var):
371371
assert "1" == lcompile('(builtins.str. 1)')
372372
assert sym.symbol('hi') == lcompile('(basilisp.lang.symbol.Symbol. "hi")')
373373

374-
with pytest.raises(AttributeError):
374+
with pytest.raises(runtime.RuntimeException):
375375
lcompile('(builtins.str "hi")')
376376

377377

@@ -399,7 +399,7 @@ def test_let(ns_var: Var):
399399
assert lcompile("(let* [a 1 b :length c {b a} a 4] a)") == 4
400400
assert lcompile("(let* [a \"lower\"] (.upper a))") == "LOWER"
401401

402-
with pytest.raises(AttributeError):
402+
with pytest.raises(runtime.RuntimeException):
403403
lcompile("(let* [a 'sym] c)")
404404

405405
with pytest.raises(compiler.CompilerException):
@@ -672,17 +672,17 @@ def test_try_catch(capsys, ns_var):
672672

673673

674674
def test_unquote(ns_var: Var):
675-
with pytest.raises(AttributeError):
675+
with pytest.raises(runtime.RuntimeException):
676676
lcompile("~s")
677677

678678
assert llist.l(sym.symbol('s')) == lcompile('`(s)')
679679

680-
with pytest.raises(AttributeError):
680+
with pytest.raises(runtime.RuntimeException):
681681
lcompile("`(~s)")
682682

683683

684684
def test_unquote_splicing(ns_var: Var, resolver: reader.Resolver):
685-
with pytest.raises(AttributeError):
685+
with pytest.raises(runtime.RuntimeException):
686686
lcompile("~@[1 2 3]")
687687

688688
assert llist.l(1, 2, 3) == lcompile("`(~@[1 2 3])")

0 commit comments

Comments
 (0)