merge branch 'if-no-waste'

This commit is contained in:
Zack M. Davis 2015-10-13 21:59:18 -07:00
commit 05857544f1

View File

@ -377,6 +377,7 @@ class HyASTCompiler(object):
self.anon_var_count = 0 self.anon_var_count = 0
self.imports = defaultdict(set) self.imports = defaultdict(set)
self.module_name = module_name self.module_name = module_name
self.temp_if = None
if not module_name.startswith("hy.core"): if not module_name.startswith("hy.core"):
# everything in core needs to be explicit. # everything in core needs to be explicit.
load_stdlib() load_stdlib()
@ -1003,11 +1004,41 @@ class HyASTCompiler(object):
def compile_if(self, expression): def compile_if(self, expression):
expression.pop(0) expression.pop(0)
cond = self.compile(expression.pop(0)) cond = self.compile(expression.pop(0))
body = self.compile(expression.pop(0)) body = self.compile(expression.pop(0))
orel = Result() orel = Result()
nested = root = False
if expression: 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 # We want to hoist the statements from the condition
ret = cond ret = cond
@ -1015,7 +1046,7 @@ class HyASTCompiler(object):
if body.stmts or orel.stmts: if body.stmts or orel.stmts:
# We have statements in our bodies # We have statements in our bodies
# Get a temporary variable for the result storage # 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), name = ast.Name(id=ast_str(var), arg=ast_str(var),
ctx=ast.Store(), ctx=ast.Store(),
lineno=expression.start_line, lineno=expression.start_line,
@ -1028,10 +1059,12 @@ class HyASTCompiler(object):
col_offset=expression.start_column) col_offset=expression.start_column)
# and of the else clause # and of the else clause
orel += ast.Assign(targets=[name], if not nested or not orel.stmts or (not root and
value=orel.force_expr, var != self.temp_if):
lineno=expression.start_line, orel += ast.Assign(targets=[name],
col_offset=expression.start_column) value=orel.force_expr,
lineno=expression.start_line,
col_offset=expression.start_column)
# Then build the if # Then build the if
ret += ast.If(test=ret.force_expr, ret += ast.If(test=ret.force_expr,
@ -1054,6 +1087,10 @@ class HyASTCompiler(object):
orelse=orel.force_expr, orelse=orel.force_expr,
lineno=expression.start_line, lineno=expression.start_line,
col_offset=expression.start_column) col_offset=expression.start_column)
if root:
self.temp_if = None
return ret return ret
@builds("break") @builds("break")