@@ -497,6 +497,21 @@ def _clean_meta(meta: Optional[lmap.Map]) -> Optional[lmap.Map]:
497
497
return None if len (new_meta ) == 0 else new_meta
498
498
499
499
500
+ def _body_ast (
501
+ ctx : ParserContext , form : Union [llist .List , ISeq ]
502
+ ) -> Tuple [Iterable [Node ], Node ]:
503
+ """Parse the form into a body of statement nodes and a single return
504
+ expression node.
505
+
506
+ If the body is empty, return a constant node containing nil."""
507
+ body = list (map (partial (_parse_ast , ctx ), form ))
508
+ if body :
509
+ * stmts , ret = body
510
+ else :
511
+ stmts , ret = [], _const_node (ctx , None )
512
+ return stmts , ret
513
+
514
+
500
515
def _with_meta (gen_node ):
501
516
"""Wraps the node generated by gen_node in a :with-meta AST node if the
502
517
original form has meta.
@@ -764,13 +779,7 @@ def __deftype_classmethod(
764
779
765
780
params = args [1 :]
766
781
has_vargs , param_nodes = __deftype_method_param_bindings (ctx , params )
767
-
768
- body = list (map (partial (_parse_ast , ctx ), runtime .nthrest (form , 2 )))
769
- if body :
770
- * stmts , ret = body
771
- else :
772
- stmts , ret = [], _const_node (ctx , None )
773
-
782
+ stmts , ret = _body_ast (ctx , runtime .nthrest (form , 2 ))
774
783
method = ClassMethod (
775
784
form = form ,
776
785
name = method_name ,
@@ -824,12 +833,7 @@ def __deftype_method(
824
833
825
834
loop_id = genname (method_name )
826
835
with ctx .new_recur_point (loop_id , param_nodes ):
827
- body = list (map (partial (_parse_ast , ctx ), runtime .nthrest (form , 2 )))
828
- if body :
829
- * stmts , ret = body
830
- else :
831
- stmts , ret = [], _const_node (ctx , None )
832
-
836
+ stmts , ret = _body_ast (ctx , runtime .nthrest (form , 2 ))
833
837
method = Method (
834
838
form = form ,
835
839
name = method_name ,
@@ -889,12 +893,7 @@ def __deftype_property(
889
893
890
894
assert not has_vargs , "deftype* properties may not have arguments"
891
895
892
- body = list (map (partial (_parse_ast , ctx ), runtime .nthrest (form , 2 )))
893
- if body :
894
- * stmts , ret = body
895
- else :
896
- stmts , ret = [], _const_node (ctx , None )
897
-
896
+ stmts , ret = _body_ast (ctx , runtime .nthrest (form , 2 ))
898
897
prop = PropertyMethod (
899
898
form = form ,
900
899
name = method_name ,
@@ -924,13 +923,7 @@ def __deftype_staticmethod(
924
923
"""Emit a node for a :staticmethod member of a deftype* form."""
925
924
with ctx .hide_parent_symbol_table (), ctx .new_symbol_table (method_name ):
926
925
has_vargs , param_nodes = __deftype_method_param_bindings (ctx , args )
927
-
928
- body = list (map (partial (_parse_ast , ctx ), runtime .nthrest (form , 2 )))
929
- if body :
930
- * stmts , ret = body
931
- else :
932
- stmts , ret = [], _const_node (ctx , None )
933
-
926
+ stmts , ret = _body_ast (ctx , runtime .nthrest (form , 2 ))
934
927
method = StaticMethod (
935
928
form = form ,
936
929
name = method_name ,
@@ -1287,12 +1280,7 @@ def __fn_method_ast( # pylint: disable=too-many-branches,too-many-locals
1287
1280
1288
1281
fn_loop_id = genname ("fn_arity" if fnname is None else fnname .name )
1289
1282
with ctx .new_recur_point (fn_loop_id , param_nodes ):
1290
- body = list (map (partial (_parse_ast , ctx ), form .rest ))
1291
- if body :
1292
- * stmts , ret = body
1293
- else :
1294
- stmts , ret = [], _const_node (ctx , None )
1295
-
1283
+ stmts , ret = _body_ast (ctx , form .rest )
1296
1284
method = FnMethod (
1297
1285
form = form ,
1298
1286
loop_id = fn_loop_id ,
@@ -1654,18 +1642,14 @@ def _let_ast(ctx: ParserContext, form: ISeq) -> Let:
1654
1642
assert form .first == SpecialForm .LET
1655
1643
nelems = count (form )
1656
1644
1657
- if nelems < 3 :
1645
+ if nelems < 2 :
1658
1646
raise ParserException (
1659
- "let forms must have bindings and at least one body form " , form = form
1647
+ "let forms must have bindings vector and 0 or more body forms " , form = form
1660
1648
)
1661
1649
1662
1650
bindings = runtime .nth (form , 1 )
1663
1651
if not isinstance (bindings , vec .Vector ):
1664
1652
raise ParserException ("let bindings must be a vector" , form = bindings )
1665
- elif len (bindings ) == 0 :
1666
- raise ParserException (
1667
- "let form must have at least one pair of bindings" , form = bindings
1668
- )
1669
1653
elif len (bindings ) % 2 != 0 :
1670
1654
raise ParserException (
1671
1655
"let bindings must appear in name-value pairs" , form = bindings
@@ -1689,13 +1673,13 @@ def _let_ast(ctx: ParserContext, form: ISeq) -> Let:
1689
1673
ctx .put_new_symbol (name , binding )
1690
1674
1691
1675
let_body = runtime .nthrest (form , 2 )
1692
- * statements , ret = map ( partial ( _parse_ast , ctx ) , let_body )
1676
+ stmts , ret = _body_ast ( ctx , let_body )
1693
1677
return Let (
1694
1678
form = form ,
1695
1679
bindings = vec .vector (binding_nodes ),
1696
1680
body = Do (
1697
1681
form = let_body ,
1698
- statements = vec .vector (statements ),
1682
+ statements = vec .vector (stmts ),
1699
1683
ret = ret ,
1700
1684
is_body = True ,
1701
1685
env = ctx .get_node_env (),
@@ -1708,9 +1692,9 @@ def _loop_ast(ctx: ParserContext, form: ISeq) -> Loop:
1708
1692
assert form .first == SpecialForm .LOOP
1709
1693
nelems = count (form )
1710
1694
1711
- if nelems < 3 :
1695
+ if nelems < 2 :
1712
1696
raise ParserException (
1713
- "loop forms must have bindings and at least one body form " , form = form
1697
+ "loop forms must have bindings vector and 0 or more body forms " , form = form
1714
1698
)
1715
1699
1716
1700
bindings = runtime .nth (form , 1 )
@@ -1740,13 +1724,13 @@ def _loop_ast(ctx: ParserContext, form: ISeq) -> Loop:
1740
1724
1741
1725
with ctx .new_recur_point (loop_id , binding_nodes ):
1742
1726
loop_body = runtime .nthrest (form , 2 )
1743
- * statements , ret = map ( partial ( _parse_ast , ctx ) , loop_body )
1727
+ stmts , ret = _body_ast ( ctx , loop_body )
1744
1728
loop_node = Loop (
1745
1729
form = form ,
1746
1730
bindings = vec .vector (binding_nodes ),
1747
1731
body = Do (
1748
1732
form = loop_body ,
1749
- statements = vec .vector (statements ),
1733
+ statements = vec .vector (stmts ),
1750
1734
ret = ret ,
1751
1735
is_body = True ,
1752
1736
env = ctx .get_node_env (),
0 commit comments