def function_definition_rename(node, scope): if node.lhs.identifier in BUILTIN_FUNCTIONS: raise FunkyRenamingError( "Cannot redefine builtin function '{}'.".format( node.lhs.identifier)) if node.lhs.identifier not in scope.local: if scope.is_pending_definition(node.lhs.identifier): newid = scope.get_pending_name(node.lhs.identifier) if node.lhs.identifier in scope.pending_definition: del scope.pending_definition[node.lhs.identifier] else: newid = get_unique_varname() scope[node.lhs.identifier] = { "id": newid, "arity": len(node.lhs.parameters) } tmp_scope = Scope(parent=scope) rename(node.lhs, tmp_scope) node.lhs.identifier = scope[node.lhs.identifier]["id"] tmp_scope2 = Scope(parent=tmp_scope) rename(node.rhs, tmp_scope2) scope.pending_definition.update(tmp_scope.pending_definition) scope.pending_definition.update(tmp_scope2.pending_definition)
def let_rename(node, scope): tmp_scope = Scope(parent=scope) for decl in node.declarations: rename(decl, tmp_scope) rename(node.expression, tmp_scope) scope.pending_definition.update(tmp_scope.pending_definition)
def alternative_rename(node, scope): # alternatives in a match statement are able to override previously named # variables implicitly if their pattern re-uses a name that has already # been defined. The name would now refer to a more local item. Therefore, # we have to create a temporary scope to silence errors relating to name # reuse. tmp_scope = Scope(parent=scope) rename(node.pattern, tmp_scope) rename(node.expression, tmp_scope)
def new_cons_statement_rename(node, scope): if node.identifier in scope: raise FunkyRenamingError("Duplicate definition of constructor type " \ "'{}'.".format(node.identifier)) elif node.identifier in BUILTIN_PRIMITIVES: raise FunkyRenamingError("Cannot define type with builtin name " \ "'{}'.".format(node.identifier)) # we don't rename the type, only the variables scope[node.identifier] = node.identifier tmp_scope_1 = Scope(parent=scope) for i, param in enumerate(node.type_parameters): tmp_scope_1[param] = get_parameter_name(node.identifier, i) tmp_scope_2 = Scope(parent=tmp_scope_1) for cons in node.constructors: rename(cons, tmp_scope_2) scope.local.update(tmp_scope_2.local)
def reset(self): """Resets the scope and bindings.""" self.imported = set([]) self.scope = Scope() # global_types is the collection of user-defined type declarations. self.global_types = [] # global_let is a core let whose bindings are just the bindings the # user has introduced, and whose expression is 'dynamic' -- it is # changed each time the user asks for an expression to be evaluated and # recompiled as a new program to give the new result. self.global_let = CoreLet([], CoreLiteral(0))
def pattern_definition_rename(node, scope): if node.variable.name in BUILTIN_FUNCTIONS: raise FunkyRenamingError( "Cannot redefine built-in function '{}'.".format( node.variable.name)) rename(node.variable, scope, is_main=isinstance(node.variable, Parameter) and \ node.variable.name == "main") tmp_scope = Scope(parent=scope) rename(node.expression, tmp_scope) scope.pending_definition.update(tmp_scope.pending_definition)
def do_rename(source_tree): """Renames items in the source tree so that they all have a unique name Also performs sanity checks such as making sure that duplicate declarations don't exist, etc. :param source_tree: the source tree from parsing """ logging.info("Renaming and sanity checking parse tree...") scope = Scope() rename(source_tree, scope) check_scope_for_errors(scope) logging.info("Renaming and sanity checking parse tree completed.") return scope # <- in case anybody wants it
def module_rename(node, scope=Scope()): rename(node.body, scope)
def lambda_rename(node, scope): tmp_scope = Scope(parent=scope) for p in node.parameters: rename(p, tmp_scope) rename(node.expression, tmp_scope) scope.pending_definition.update(tmp_scope.pending_definition)