def _Bind(self, stmt): var = stmt.binder() varNames = [x.id for x in flatten(var)] operation = S.substituted_expression(stmt.value(), self.env) for name in varNames: if name not in self.exceptions: rename = '%s_%s' % (name, self.serial.next()) else: rename = name self.env[name] = S.Name(rename) result = S.Bind(S.substituted_expression(var, self.env), operation) return result
def _Procedure(self, ast): binders = [v.id for v in flatten(ast.variables)] # NOTE: this includes name _ClosureRecursion._Procedure(self, ast) # Take the free variable list, stick it in a set to make sure we don't # duplicate a variable, and then put it back in a list to make sure # it's got a defined ordering, which sets don't have free = list(set([v for v in S.free_variables(ast.body(), binders) if v in self.env])) if free: bound = [S.Name("_K%d" % i) for i in range(len(free))] ast.variables = ast.variables + bound ast.parameters = S.substituted_expression(ast.parameters, dict(zip(free, bound))) # Transform recursive calls of this procedure within its own body. recursive = _ClosureRecursion(self.env) self.env[ast.name().id] = S.Closure(bound, ast.name()) ast.parameters = recursive.rewrite(ast.parameters) # Register rewrite for calls to this procedure in later # parts of the defining scope self.env[ast.name().id] = S.Closure([S.Name(x) for x in free], ast.name()) # else: # self.locally_bound([ast.name()]) return ast
def _While(self, cond): condition = S.substituted_expression(cond.parameters[0], self.env) self.freeze = True self.rewrite_children(cond) cond.parameters[0] = condition self.freeze = False return cond
def _Apply(self, appl): fn = appl.function() if isinstance(fn, S.Closure): fn_name = fn.body().id else: fn_name = fn.id if fn_name in self.procedures: instantiatedFunction = self.procedures[fn_name] functionArguments = instantiatedFunction.variables[1:] instantiatedArguments = appl.parameters[1:] if isinstance(fn, S.Closure): instantiatedArguments.extend(fn.variables) env = pltools.Environment() for (internal, external) in zip(functionArguments, instantiatedArguments): env[internal.id] = external return_finder = ReturnFinder() return_finder.visit(instantiatedFunction) #XXX HACK. Need to do conditional statement->expression conversion # In order to make inlining possible if return_finder.return_in_conditional: return appl env[return_finder.return_value.id] = self.activeBinding statements = filter(lambda x: not isinstance(x, S.Return), instantiatedFunction.body()) statements = [S.substituted_expression(x, env) for x in \ statements] singleAssignmentInstantiation = single_assignment_conversion( statements, exceptions=set((x.id for x in flatten(self.activeBinding))), M=self.M) self.statements = singleAssignmentInstantiation return None return appl
def _Apply(self, appl): fn = appl.function() if isinstance(fn, S.Closure): fn_name = fn.body().id else: fn_name = fn.id if fn_name in self.procedures: instantiatedFunction = self.procedures[fn_name] functionArguments = instantiatedFunction.variables[1:] instantiatedArguments = appl.parameters[1:] if isinstance(fn, S.Closure): instantiatedArguments.extend(fn.variables) env = pltools.Environment() for (internal, external) in zip(functionArguments, instantiatedArguments): env[internal.id] = external return_finder = ReturnFinder() return_finder.visit(instantiatedFunction) #XXX HACK. Need to do conditional statement->expression conversion # In order to make inlining possible if return_finder.return_in_conditional: return appl env[return_finder.return_value.id] = self.activeBinding statements = filter(lambda x: not isinstance(x, S.Return), instantiatedFunction.body()) statements = [S.substituted_expression(x, env) for x in \ statements] singleAssignmentInstantiation = single_assignment_conversion(statements, exceptions=set((x.id for x in flatten(self.activeBinding))), M=self.M) self.statements = singleAssignmentInstantiation return None return appl
def _Closure(self, c): closed_over_literal = any( map(lambda x: not isinstance(x, S.Name), c.closed_over())) if not closed_over_literal: return c #Find procedure being closed over proc_name = c.body().id proc = self.procedures[proc_name] proc_args = proc.formals() closed_args = c.closed_over() #Construct new set of arguments, with literals closed over removed replaced_args = proc_args[:-len(closed_args)] replaced_closed_over = [] #Also record what replacements to make replacement = {} for orig_arg, closed_arg in zip(proc_args[-len(closed_args):], closed_args): if isinstance(closed_arg, S.Name): replaced_args.append(orig_arg) replaced_closed_over.append(closed_arg) else: replacement[orig_arg.id] = closed_arg #If we are only closing over literals, we will return a name #rather than a reduced closure. Check. fully_opened = len(replacement) == len(closed_args) replaced_stmts = [ S.substituted_expression(si, replacement) \ for si in proc.body()] replaced_name = S.Name(proc_name + self.name_supply.next()) self.propagated.append( S.Procedure(replaced_name, replaced_args, replaced_stmts)) if fully_opened: return replaced_name else: return S.Closure(replaced_closed_over, replaced_name)
def _Procedure(self, proc): if proc.name().id not in self.entry_points: return proc self.env = P.Environment() self.rewrite_children(proc) proc.parameters = S.stripNull(proc.parameters) proc = S.substituted_expression(proc, self.env) return proc
def _Cond(self, cond): condition = S.substituted_expression(cond.parameters[0], self.env) self.env.begin_scope() body = self.rewrite(cond.body()) self.env.end_scope() self.env.begin_scope() orelse = self.rewrite(cond.orelse()) self.env.end_scope() return S.Cond(condition, body, orelse)
def _Bind(self, stmt): var = stmt.binder() varNames = [x.id for x in flatten(var)] operation = S.substituted_expression(stmt.value(), self.env) for name in varNames: if self.freeze: if name in self.env: rename = self.env[name] elif name not in self.exceptions: rename = markGenerated('%s_%s' % (name, SingleAssignmentRewrite.serial.next())) else: rename = name elif name not in self.exceptions: rename = markGenerated('%s_%s' % (name, SingleAssignmentRewrite.serial.next())) else: rename = name self.env[name] = S.Name(rename) result = S.Bind(S.substituted_expression(var, self.env), operation) return result
def _Apply(self, apply): functionName = apply.parameters[0].id if functionName in self.procedures: instantiatedFunction = self.procedures[functionName] functionArguments = instantiatedFunction.variables[1:] instantiatedArguments = apply.parameters[1:] env = pltools.Environment() for (internal, external) in zip(functionArguments, instantiatedArguments): env[internal.id] = external return_finder = ReturnFinder(self.activeBinding, env) return_finder.visit(instantiatedFunction) statements = [S.substituted_expression(x, env) for x in \ instantiatedFunction.body() \ if not isinstance(x, S.Return)] singleAssignmentInstantiation = single_assignment_conversion(statements, exceptions=set((x.id for x in flatten(self.activeBinding)))) self.statements = singleAssignmentInstantiation return None return apply
def _Lambda(self, e): _ClosureRecursion._Lambda(self, e) formals = [v.id for v in flatten(e.formals())] # Take the free variable list, stick it in a set to make sure we don't # duplicate a variable, and then put it back in a list to make sure # it's got a defined ordering, which sets don't have free = list(set([v for v in S.free_variables(e.body(), formals) if v in self.env])) if free: bound = [S.Name("_K%d" % i) for i in range(len(free))] body = S.substituted_expression(e.body(), dict(zip(free, bound))) e.parameters = [body] e.variables = e.variables + bound return S.Closure([S.Name(x) for x in free], e) else: return e
def _Apply(self, apply): functionName = apply.parameters[0].id if functionName in self.procedures: instantiatedFunction = self.procedures[functionName] functionArguments = instantiatedFunction.variables[1:] instantiatedArguments = apply.parameters[1:] env = pltools.Environment() for (internal, external) in zip(functionArguments, instantiatedArguments): env[internal.id] = external return_finder = ReturnFinder(self.activeBinding, env) return_finder.visit(instantiatedFunction) statements = [S.substituted_expression(x, env) for x in \ instantiatedFunction.body() \ if not isinstance(x, S.Return)] singleAssignmentInstantiation = single_assignment_conversion( statements, exceptions=set((x.id for x in flatten(self.activeBinding)))) self.statements = singleAssignmentInstantiation return None return apply
def _Lambda(self, e): _ClosureRecursion._Lambda(self, e) formals = [v.id for v in flatten(e.formals())] # Take the free variable list, stick it in a set to make sure we don't # duplicate a variable, and then put it back in a list to make sure # it's got a defined ordering, which sets don't have free = list( set([ v for v in S.free_variables(e.body(), formals) if v in self.env ])) if free: bound = [S.Name("_K%d" % i) for i in range(len(free))] body = S.substituted_expression(e.body(), dict(zip(free, bound))) e.parameters = [body] e.variables = e.variables + bound return S.Closure([S.Name(x) for x in free], e) else: return e
def _Closure(self, c): closed_over_literal = any(map(lambda x: not isinstance(x, S.Name), c.closed_over())) if not closed_over_literal: return c #Find procedure being closed over proc_name = c.body().id proc = self.procedures[proc_name] proc_args = proc.formals() closed_args = c.closed_over() #Construct new set of arguments, with literals closed over removed replaced_args = proc_args[:-len(closed_args)] replaced_closed_over = [] #Also record what replacements to make replacement = {} for orig_arg, closed_arg in zip(proc_args[-len(closed_args):], closed_args): if isinstance(closed_arg, S.Name): replaced_args.append(orig_arg) replaced_closed_over.append(closed_arg) else: replacement[orig_arg.id] = closed_arg #If we are only closing over literals, we will return a name #rather than a reduced closure. Check. fully_opened = len(replacement) == len(closed_args) replaced_stmts = [ S.substituted_expression(si, replacement) \ for si in proc.body()] replaced_name = S.Name(proc_name + self.name_supply.next()) self.propagated.append( S.Procedure( replaced_name, replaced_args, replaced_stmts)) if fully_opened: return replaced_name else: return S.Closure(replaced_closed_over, replaced_name)
def _Procedure(self, ast): binders = [v.id for v in flatten(ast.variables)] # NOTE: this includes name _ClosureRecursion._Procedure(self, ast) # Take the free variable list, stick it in a set to make sure we don't # duplicate a variable, and then put it back in a list to make sure # it's got a defined ordering, which sets don't have free = list( set([ v for v in S.free_variables(ast.body(), binders) if v in self.env ])) if free: bound = [S.Name("_K%d" % i) for i in range(len(free))] ast.variables = ast.variables + bound ast.parameters = S.substituted_expression(ast.parameters, dict(zip(free, bound))) # Transform recursive calls of this procedure within its own body. recursive = _ClosureRecursion(self.env) self.env[ast.name().id] = bound ast.parameters = recursive.rewrite(ast.parameters) # Register rewrite for calls to this procedure in later # parts of the defining scope self.env[ast.name().id] = S.Closure([S.Name(x) for x in free], ast.name()) # else: # self.locally_bound([ast.name()]) return ast
def _Cond(self, cond): condition = S.substituted_expression(cond.parameters[0], self.env) self.rewrite_children(cond) return S.Cond(condition, cond.parameters[1], cond.parameters[2])
def _Return(self, stmt): result = S.Return(S.substituted_expression(stmt.value(), self.env)) return result