def _Bind(self, ast): type = self.expression_type(ast.value()) # Convert functional types to polytypes as necessary if isinstance(type, T.Fn): free = [v for v in AST.free_variables(ast.value(), {})] bound = [self.tcon.typings[id] for id in free] bound = [resolve(t, self.tcon.environment) for t in bound] type = T.quantify_type(type, bound) ##This code allows us to unpack tuples returned from functions def match(binder, type): if isinstance(binder, AST.Name): self.tcon.typings[binder.id] = type elif isinstance(binder, AST.Tuple): if len(binder.parameters)!=len(type.parameters): raise InferenceError, \ "binder and value don't match (%s)" % ast for b, t in zip(binder.parameters, type.parameters): match(b, t) else: raise InferenceError, "illegal binder (%s)" % ast match(ast.binder(), type) return None
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 _Procedure(self, proc): if proc.name().id not in self.entry_points: return proc calls = [] for phase in proc.body(): free = S.free_variables(phase) variables = set(free).intersection(proc.typings.keys()) phase.variables = phase.variables + [S.Name(x) for x in variables] return proc
def procedure_prune(ast, entries): needed = set(entries) # First, figure out which procedures we actually need by determining # the free variables in each of the entry points for p in ast: needed.update(S.free_variables(p.body())) # Now, only keep top-level procedures that have been referenced return [p for p in ast if p.name().id in needed]
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 _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 _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