Skip to content

Commit 66c0009

Browse files
authored
Add support for auto-resolved namespaces for keywords (#576)
* Add support for auto-resolved namespaces for keywords * Changelog * Lint
1 parent e76e5a1 commit 66c0009

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
* Added support for auto-resolving namespaces for keyword from the current namespace using the `::kw` syntax (#576)
810

911
## [v0.1.dev14] - 2020-06-18
1012
### Added

src/basilisp/lang/reader.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
IWithMeta,
5050
)
5151
from basilisp.lang.obj import seq_lrepr as _seq_lrepr
52-
from basilisp.lang.runtime import Namespace, Var, lrepr
52+
from basilisp.lang.runtime import Namespace, Var, get_current_ns, lrepr
5353
from basilisp.lang.typing import IterableLispForm, LispForm, ReaderForm
5454
from basilisp.lang.util import munge
5555
from basilisp.util import Maybe, partition
@@ -835,9 +835,28 @@ def _read_kw(ctx: ReaderContext) -> keyword.Keyword:
835835
"""Return a keyword from the input stream."""
836836
start = ctx.reader.advance()
837837
assert start == ":"
838+
token = ctx.reader.peek()
839+
if token == ":":
840+
ctx.reader.advance()
841+
should_autoresolve = True
842+
else:
843+
should_autoresolve = False
844+
838845
ns, name = _read_namespaced(ctx)
839846
if "." in name:
840847
raise ctx.syntax_error("Found '.' in keyword name")
848+
849+
if should_autoresolve:
850+
current_ns = get_current_ns()
851+
if ns is not None:
852+
aliased_ns = current_ns.aliases.get(symbol.symbol(ns))
853+
if aliased_ns is None:
854+
raise ctx.syntax_error(f"Cannot resolve namespace alias '{ns}'")
855+
ns = aliased_ns.name
856+
else:
857+
ns = current_ns.name
858+
return keyword.keyword(name, ns=ns)
859+
841860
return keyword.keyword(name, ns=ns)
842861

843862

@@ -848,7 +867,7 @@ def _read_meta(ctx: ReaderContext) -> IMeta:
848867
assert start == "^"
849868
meta = _read_next_consuming_comment(ctx)
850869

851-
meta_map: Optional[lmap.Map[LispForm, LispForm]] = None
870+
meta_map: Optional[lmap.Map[LispForm, LispForm]]
852871
if isinstance(meta, symbol.Symbol):
853872
meta_map = lmap.map({keyword.keyword("tag"): meta})
854873
elif isinstance(meta, keyword.Keyword):

tests/basilisp/reader_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,17 @@ def test_kw():
245245
read_str_first(":dotted.kw")
246246

247247

248+
def test_autoresolved_kw(test_ns: str, ns: runtime.Namespace):
249+
assert kw.keyword("kw", ns=test_ns) == read_str_first("::kw")
250+
251+
new_ns = runtime.Namespace(sym.symbol("other.ns"))
252+
ns.add_alias(new_ns, sym.symbol("other"))
253+
assert kw.keyword("kw", ns="other.ns") == read_str_first("::other/kw")
254+
255+
with pytest.raises(reader.SyntaxError):
256+
read_str_first("::third/kw")
257+
258+
248259
def test_literals():
249260
assert read_str_first("nil") is None
250261
assert read_str_first("true") is True

0 commit comments

Comments
 (0)