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 _Lambda(self, e): fn = S.Name(self.names.next()) self.rewrite_children(e) body = S.Return(e.parameters[0]) self.proclist.append(S.Procedure(fn, e.variables, [body])) return fn
def _Procedure(self, proc): names = pltools.name_supply(stems=['tuple'], drop_zero=False) disassembly = [] def make_name(arg): if not isinstance(arg, S.Tuple): return arg else: made_name = S.Name(names.next()) assembled = S.Bind(S.Tuple(*[make_name(x) for x in arg]), made_name) disassembly.insert(0, assembled) return made_name new_variables = map(make_name, proc.formals()) return S.Procedure(proc.name(), new_variables, disassembly + proc.parameters)