Skip to content

Commit 7009020

Browse files
authored
Correctly set node syntax position for deftype members (#523)
* Correctly set node syntax position for deftype members * Change the log
1 parent bc1ed65 commit 7009020

File tree

3 files changed

+80
-5
lines changed

3 files changed

+80
-5
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Added
99
* Added support for `future`s (#441)
1010

11+
### Fixed
12+
* Fixed a bug where the Basilisp AST nodes for return values of `deftype` members could be marked as _statements_ rather than _expressions_, resulting in an incorrect `nil` return (#523)
13+
1114
## [v0.1.dev13] - 2020-03-16
1215
### Added
1316
* Added support for Shebang-style line comments (#469)

src/basilisp/lang/compiler/analyzer.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,8 @@ def __deftype_classmethod(
933933

934934
params = args[1:]
935935
has_vargs, param_nodes = __deftype_method_param_bindings(ctx, params)
936-
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
936+
with ctx.expr_pos():
937+
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
937938
method = ClassMethod(
938939
form=form,
939940
name=method_name,
@@ -987,7 +988,8 @@ def __deftype_method(
987988

988989
loop_id = genname(method_name)
989990
with ctx.new_recur_point(loop_id, param_nodes):
990-
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
991+
with ctx.expr_pos():
992+
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
991993
method = Method(
992994
form=form,
993995
name=method_name,
@@ -1047,7 +1049,8 @@ def __deftype_property(
10471049

10481050
assert not has_vargs, "deftype* properties may not have arguments"
10491051

1050-
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
1052+
with ctx.expr_pos():
1053+
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
10511054
prop = PropertyMethod(
10521055
form=form,
10531056
name=method_name,
@@ -1077,7 +1080,8 @@ def __deftype_staticmethod(
10771080
"""Emit a node for a :staticmethod member of a deftype* form."""
10781081
with ctx.hide_parent_symbol_table(), ctx.new_symbol_table(method_name):
10791082
has_vargs, param_nodes = __deftype_method_param_bindings(ctx, args)
1080-
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
1083+
with ctx.expr_pos():
1084+
stmts, ret = _body_ast(ctx, runtime.nthrest(form, 2))
10811085
method = StaticMethod(
10821086
form=form,
10831087
name=method_name,
@@ -1432,7 +1436,8 @@ def __fn_method_ast( # pylint: disable=too-many-branches,too-many-locals
14321436

14331437
fn_loop_id = genname("fn_arity" if fnname is None else fnname.name)
14341438
with ctx.new_recur_point(fn_loop_id, param_nodes):
1435-
stmts, ret = _body_ast(ctx, form.rest)
1439+
with ctx.expr_pos():
1440+
stmts, ret = _body_ast(ctx, form.rest)
14361441
method = FnMethod(
14371442
form=form,
14381443
loop_id=fn_loop_id,

tests/basilisp/compiler_test.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,21 @@ def test_deftype_empty_classmethod_body(
868868
)
869869
assert None is Point.create()
870870

871+
def test_deftype_classmethod_returns_value(
872+
self, lcompile: CompileFn, class_interface: Var
873+
):
874+
Point = lcompile(
875+
"""
876+
(do
877+
(def ^:dynamic a nil)
878+
(deftype* Point [x]
879+
:implements [WithCls]
880+
(^:classmethod create [cls x]
881+
(set! a x)))
882+
Point)"""
883+
)
884+
assert kw.keyword("a") is Point.create(kw.keyword("a"))
885+
871886
class TestDefTypeMethod:
872887
def test_deftype_fields_and_methods(self, lcompile: CompileFn):
873888
Point = lcompile(
@@ -1009,6 +1024,24 @@ def test_deftype_method_args_are_syms(self, lcompile: CompileFn, code: str):
10091024
with pytest.raises(compiler.CompilerException):
10101025
lcompile(code)
10111026

1027+
def test_deftype_method_returns_value(
1028+
self, lcompile: CompileFn,
1029+
):
1030+
Point = lcompile(
1031+
"""
1032+
(import* collections.abc)
1033+
(do
1034+
(deftype* Point [^:mutable x]
1035+
:implements [collections.abc/Callable]
1036+
(--call-- [this new-val]
1037+
(set! x new-val)))
1038+
Point)"""
1039+
)
1040+
pt = Point(1)
1041+
assert pt.x == 1
1042+
assert 5 == pt(5)
1043+
assert pt.x == 5
1044+
10121045
class TestDefTypeProperty:
10131046
@pytest.fixture
10141047
def property_interface(self, lcompile: CompileFn):
@@ -1111,6 +1144,25 @@ def test_deftype_empty_property_body(
11111144
)
11121145
assert None is Point(1, 2, 3).prop
11131146

1147+
def test_deftype_property_returns_value(
1148+
self, lcompile: CompileFn, property_interface: Var
1149+
):
1150+
Point = lcompile(
1151+
"""
1152+
(do
1153+
(deftype* Point [^:mutable x]
1154+
:implements [WithProp]
1155+
(^:property prop [this]
1156+
(set! x (inc x))))
1157+
Point)"""
1158+
)
1159+
pt = Point(1)
1160+
assert pt.x == 1
1161+
assert pt.prop == 2
1162+
assert pt.x == 2
1163+
assert pt.prop == 3
1164+
assert pt.x == 3
1165+
11141166
class TestDefTypeStaticMethod:
11151167
@pytest.fixture
11161168
def static_interface(self, lcompile: CompileFn):
@@ -1236,6 +1288,21 @@ def test_deftype_empty_staticmethod_body(
12361288
)
12371289
assert None is Point.dostatic("x", "y")
12381290

1291+
def test_deftype_staticmethod_returns_value(
1292+
self, lcompile: CompileFn, static_interface: Var
1293+
):
1294+
Point = lcompile(
1295+
"""
1296+
(do
1297+
(def ^:dynamic a nil)
1298+
(deftype* Point [x]
1299+
:implements [WithStatic]
1300+
(^:staticmethod dostatic [x]
1301+
(set! a x)))
1302+
Point)"""
1303+
)
1304+
assert kw.keyword("a") is Point.dostatic(kw.keyword("a"))
1305+
12391306
class TestDefTypeReaderForm:
12401307
def test_ns_does_not_exist(self, lcompile: CompileFn, test_ns: str):
12411308
with pytest.raises(reader.SyntaxError):

0 commit comments

Comments
 (0)