diff --git a/hy/compiler.py b/hy/compiler.py index 4574a3f..c55fbbc 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -377,6 +377,7 @@ class HyASTCompiler(object): self.anon_var_count = 0 self.imports = defaultdict(set) self.module_name = module_name + self.temp_if = None if not module_name.startswith("hy.core"): # everything in core needs to be explicit. load_stdlib() @@ -1003,11 +1004,41 @@ class HyASTCompiler(object): def compile_if(self, expression): expression.pop(0) cond = self.compile(expression.pop(0)) - body = self.compile(expression.pop(0)) + orel = Result() + nested = root = False if expression: - orel = self.compile(expression.pop(0)) + orel_expr = expression.pop(0) + if isinstance(orel_expr, HyExpression) and isinstance(orel_expr[0], + HySymbol) and orel_expr[0] == 'if': + # Nested ifs: don't waste temporaries + root = self.temp_if is None + nested = True + self.temp_if = self.temp_if or self.get_anon_var() + orel = self.compile(orel_expr) + + if not cond.stmts and isinstance(cond.force_expr, ast.Name): + name = cond.force_expr.id + branch = None + if name == 'True': + branch = body + elif name in ('False', 'None'): + branch = orel + if branch is not None: + if self.temp_if and branch.stmts: + name = ast.Name(id=ast_str(self.temp_if), + arg=ast_str(self.temp_if), + ctx=ast.Store(), + lineno=expression.start_line, + col_offset=expression.start_column) + + branch += ast.Assign(targets=[name], + value=body.force_expr, + lineno=expression.start_line, + col_offset=expression.start_column) + + return branch # We want to hoist the statements from the condition ret = cond @@ -1015,7 +1046,7 @@ class HyASTCompiler(object): if body.stmts or orel.stmts: # We have statements in our bodies # Get a temporary variable for the result storage - var = self.get_anon_var() + var = self.temp_if or self.get_anon_var() name = ast.Name(id=ast_str(var), arg=ast_str(var), ctx=ast.Store(), lineno=expression.start_line, @@ -1028,10 +1059,12 @@ class HyASTCompiler(object): col_offset=expression.start_column) # and of the else clause - orel += ast.Assign(targets=[name], - value=orel.force_expr, - lineno=expression.start_line, - col_offset=expression.start_column) + if not nested or not orel.stmts or (not root and + var != self.temp_if): + orel += ast.Assign(targets=[name], + value=orel.force_expr, + lineno=expression.start_line, + col_offset=expression.start_column) # Then build the if ret += ast.If(test=ret.force_expr, @@ -1054,6 +1087,10 @@ class HyASTCompiler(object): orelse=orel.force_expr, lineno=expression.start_line, col_offset=expression.start_column) + + if root: + self.temp_if = None + return ret @builds("break")