src/basilisp/lang/compiler/parser.py
def _assert_recur_is_tail(node: Node) -> None:  # pylint: disable=too-many-branches
    """Assert that `recur` forms only appear in the tail position of this
    or child AST nodes.

    `recur` forms may only appear in `do` nodes (both literal and synthetic
    `do` nodes) and in either the :then or :else expression of an `if` node."""
    if node.op == NodeOp.DO:
        assert isinstance(node, Do)
        for child in node.statements:
            _assert_no_recur(child)
        _assert_recur_is_tail(node.ret)
    elif node.op in {NodeOp.FN, NodeOp.FN_METHOD, NodeOp.METHOD}:
        assert isinstance(node, (Fn, FnMethod, Method))
        node.visit(_assert_recur_is_tail)
    elif node.op == NodeOp.IF:
        assert isinstance(node, If)
        _assert_no_recur(node.test)
        _assert_recur_is_tail(node.then)
        _assert_recur_is_tail(node.else_)
    elif node.op in {NodeOp.LET, NodeOp.LETFN}:
        assert isinstance(node, (Let, LetFn))
        for binding in node.bindings:
            assert binding.init is not None
            _assert_no_recur(binding.init)
        _assert_recur_is_tail(node.body)
    elif node.op == NodeOp.LOOP:
        assert isinstance(node, Loop)
        for binding in node.bindings:
            assert binding.init is not None
            _assert_no_recur(binding.init)
    elif node.op == NodeOp.RECUR:
        pass
    elif node.op == NodeOp.TRY:
        assert isinstance(node, Try)
        _assert_recur_is_tail(node.body)
        for catch in node.catches:
            _assert_recur_is_tail(catch)
        if node.finally_:
            _assert_no_recur(node.finally_)
    else:
        node.visit(_assert_no_recur)
def _assert_recur_is_tail(node: Node) -> None:  # pylint: disable=too-many-branches
    if node.op == NodeOp.DO:
        assert isinstance(node, Do)
        for child in node.statements:
            _assert_no_recur(child)
        _assert_recur_is_tail(node.ret)
    elif node.op in {NodeOp.FN, NodeOp.FN_METHOD, NodeOp.METHOD}:
        assert isinstance(node, (Fn, FnMethod, Method))
        node.visit(_assert_recur_is_tail)
    elif node.op == NodeOp.IF:
        assert isinstance(node, If)
        _assert_no_recur(node.test)
        _assert_recur_is_tail(node.then)
        _assert_recur_is_tail(node.else_)
    elif node.op in {NodeOp.LET, NodeOp.LETFN}:
        assert isinstance(node, (Let, LetFn))
        for binding in node.bindings:
            assert binding.init is not None
            _assert_no_recur(binding.init)
        _assert_recur_is_tail(node.body)
    elif node.op == NodeOp.LOOP:
        assert isinstance(node, Loop)
        for binding in node.bindings:
            assert binding.init is not None
            _assert_no_recur(binding.init)
    elif node.op == NodeOp.RECUR:
        pass
    elif node.op == NodeOp.TRY:
        assert isinstance(node, Try)
        _assert_recur_is_tail(node.body)
        for catch in node.catches:
            _assert_recur_is_tail(catch)
        if node.finally_:
            _assert_no_recur(node.finally_)
    else:
        node.visit(_assert_no_recur)
def _assert_recur_is_tail ( node : Node ) -> None : # pylint: disable=too-many-branches if node . op == NodeOp . DO : assert isinstance ( node , Do ) for child in node . statements : _assert_no_recur ( child ) _assert_recur_is_tail ( node . ret ) elif node . op in { NodeOp . FN , NodeOp . FN_METHOD , NodeOp . METHOD } : assert isinstance ( node , ( Fn , FnMethod , Method ) ) node . visit ( _assert_recur_is_tail ) elif node . op == NodeOp . IF : assert isinstance ( node , If ) _assert_no_recur ( node . test ) _assert_recur_is_tail ( node . then ) _assert_recur_is_tail ( node . else_ ) elif node . op in { NodeOp . LET , NodeOp . LETFN } : assert isinstance ( node , ( Let , LetFn ) ) for binding in node . bindings : assert binding . init is not None _assert_no_recur ( binding . init ) _assert_recur_is_tail ( node . body ) elif node . op == NodeOp . LOOP : assert isinstance ( node , Loop ) for binding in node . bindings : assert binding . init is not None _assert_no_recur ( binding . init ) elif node . op == NodeOp . RECUR : pass elif node . op == NodeOp . TRY : assert isinstance ( node , Try ) _assert_recur_is_tail ( node . body ) for catch in node . catches : _assert_recur_is_tail ( catch ) if node . finally_ : _assert_no_recur ( node . finally_ ) else : node . visit ( _assert_no_recur )
Assert that `recur` forms only appear in the tail position of this
    or child AST nodes.

    `recur` forms may only appear in `do` nodes (both literal and synthetic
    `do` nodes) and in either the :then or :else expression of an `if` node.
Assert that recur forms only appear in the tail position of this or child AST nodes .