From 21bbab4e09b3116583431955be683148ddf84fad Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Tue, 25 Aug 2015 11:45:20 -0500 Subject: [PATCH 1/2] Remove redundant assignments with nested ifs (closes #842) --- hy/compiler.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index f3cc9ac..e9037be 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -375,6 +375,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() @@ -1004,8 +1005,16 @@ class HyASTCompiler(object): 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) # We want to hoist the statements from the condition ret = cond @@ -1013,7 +1022,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, @@ -1026,10 +1035,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, @@ -1052,6 +1063,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") From c3190ca07da9258b7bbd5f0bdfbb4583247afc06 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Tue, 22 Sep 2015 12:17:47 -0500 Subject: [PATCH 2/2] Optimize simple cases such as 'if True' --- hy/compiler.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hy/compiler.py b/hy/compiler.py index e9037be..7ed71a0 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1002,8 +1002,8 @@ 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: @@ -1016,6 +1016,28 @@ class HyASTCompiler(object): 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