Skip to content

Commit c668182

Browse files
authored
Compiler support for dynamic vars (#156)
1 parent d503242 commit c668182

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

basilisp/compiler.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,14 @@ def _def_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
480480

481481
meta_nodes, meta = _nodes_and_exprl(_meta_kwargs_ast(ctx, form[1]))
482482

483+
# If the Var is marked as dynamic, we need to generate a keyword argument
484+
# for the generated Python code to set the Var as dynamic
485+
dynamic_kwarg = Maybe(form[1].meta) \
486+
.map(lambda m: m.get(_SYM_DYNAMIC_META_KEY, None) # type: ignore
487+
) \
488+
.map(lambda v: [ast.keyword(arg='dynamic', value=ast.NameConstant(v))]) \
489+
.or_else_get([])
490+
483491
yield from meta_nodes
484492
yield from def_nodes
485493

@@ -493,7 +501,7 @@ def _def_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
493501
yield _node(ast.Call(
494502
func=_INTERN_VAR_FN_NAME,
495503
args=[ns_name, def_name, ast.Name(id=safe_name, ctx=ast.Load())],
496-
keywords=_unwrap_nodes(meta)))
504+
keywords=list(chain(dynamic_kwarg, _unwrap_nodes(meta)))))
497505

498506

499507
def _do_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:

tests/compiler_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ def test_def(ns_var: Var):
167167
assert lcompile("beep") == "a sound a robot makes"
168168

169169

170+
def test_def_dynamic(ns_var: Var):
171+
v: Var = lcompile("(def ^:dynamic *a-dynamic-var* 1)")
172+
assert v.dynamic is True
173+
lcompile("(.push-bindings #'*a-dynamic-var* :hi)")
174+
assert kw.keyword("hi") == lcompile("*a-dynamic-var*")
175+
assert kw.keyword("hi") == lcompile("(.pop-bindings #'*a-dynamic-var*)")
176+
assert 1 == lcompile("*a-dynamic-var*")
177+
178+
v: Var = lcompile("(def a-regular-var 1)")
179+
assert v.dynamic is False
180+
lcompile("(.push-bindings #'a-regular-var :hi)")
181+
assert 1 == lcompile("a-regular-var")
182+
assert kw.keyword("hi") == lcompile("(.pop-bindings #'a-regular-var)")
183+
assert 1 == lcompile("a-regular-var")
184+
185+
170186
def test_do(ns_var: Var):
171187
code = """
172188
(do

0 commit comments

Comments
 (0)