39
39
_DO_PREFIX = 'lisp_do'
40
40
_FN_PREFIX = 'lisp_fn'
41
41
_IF_PREFIX = 'lisp_if'
42
+ _IF_TEST_PREFIX = 'if_test'
42
43
_MULTI_ARITY_ARG_NAME = 'multi_arity_args'
43
44
_THROW_PREFIX = 'lisp_throw'
44
45
_TRY_PREFIX = 'lisp_try'
@@ -710,7 +711,15 @@ def _fn_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
710
711
711
712
def _if_ast (ctx : CompilerContext , form : llist .List ) -> ASTStream :
712
713
"""Generate a function call to a utility function which acts as
713
- an if expression and works around Python's if statement."""
714
+ an if expression and works around Python's if statement.
715
+
716
+ Every expression in Basilisp is true if it is not the literal values nil
717
+ or false. This function compiles direct checks for the test value against
718
+ the Python values None and False to accommodate this behavior.
719
+
720
+ Note that the if and else bodies are switched in compilation so that we
721
+ can perform a short-circuit or comparison, rather than exhaustively checking
722
+ for both false and nil each time."""
714
723
assert form .first == _IF
715
724
assert len (form ) in range (3 , 5 )
716
725
@@ -723,10 +732,22 @@ def _if_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
723
732
else_nodes = [] # type: ignore
724
733
lelse = ast .NameConstant (None ) # type: ignore
725
734
735
+ test_name = genname (_IF_TEST_PREFIX )
736
+ test_assign = ast .Assign (targets = [ast .Name (id = test_name , ctx = ast .Store ())],
737
+ value = _unwrap_node (test ))
738
+
726
739
ifstmt = ast .If (
727
- test = _unwrap_node (test ),
728
- body = [ast .Return (value = _unwrap_node (body ))],
729
- orelse = [ast .Return (value = _unwrap_node (lelse ))])
740
+ test = ast .BoolOp (op = ast .Or (),
741
+ values = [ast .Compare (left = ast .NameConstant (None ),
742
+ ops = [ast .Is ()],
743
+ comparators = [ast .Name (id = test_name , ctx = ast .Load ())]),
744
+ ast .Compare (left = ast .NameConstant (False ),
745
+ ops = [ast .Is ()],
746
+ comparators = [ast .Name (id = test_name , ctx = ast .Load ())])
747
+ ]),
748
+ values = [],
749
+ body = [ast .Return (value = _unwrap_node (lelse ))],
750
+ orelse = [ast .Return (value = _unwrap_node (body ))])
730
751
731
752
ifname = genname (_IF_PREFIX )
732
753
@@ -739,7 +760,7 @@ def _if_ast(ctx: CompilerContext, form: llist.List) -> ASTStream:
739
760
kwonlyargs = [],
740
761
defaults = [],
741
762
kw_defaults = []),
742
- body = _unwrap_nodes (chain (test_nodes , body_nodes , else_nodes , [ifstmt ])),
763
+ body = _unwrap_nodes (chain (test_nodes , body_nodes , else_nodes , [test_assign , ifstmt ])),
743
764
decorator_list = [],
744
765
returns = None ))
745
766
yield _node (ast .Call (
0 commit comments