class ClosureGiverNodeBase( CodeNodeBase ): """ Mixin for nodes that provide variables for closure takers. """ def __init__( self, name, code_prefix, source_ref ): CodeNodeBase.__init__( self, name = name, code_prefix = code_prefix, source_ref = source_ref ) self.providing = OrderedDict() self.keeper_variables = OrderedSet() def hasProvidedVariable( self, variable_name ): return variable_name in self.providing def getProvidedVariable( self, variable_name ): if variable_name not in self.providing: self.providing[ variable_name ] = self.createProvidedVariable( variable_name = variable_name ) return self.providing[ variable_name ] def createProvidedVariable( self, variable_name ): # Virtual method, pylint: disable=R0201,W0613 assert type( variable_name ) is str return None def registerProvidedVariables( self, variables ): for variable in variables: self.registerProvidedVariable( variable ) def registerProvidedVariable( self, variable ): assert variable is not None self.providing[ variable.getName() ] = variable def getProvidedVariables( self ): return self.providing.values() def getTempKeeperVariable( self ): name = "keeper_%d" % len( self.keeper_variables ) from nuitka import Variables result = Variables.TempKeeperVariable( owner = self, variable_name = name ) self.keeper_variables.add( result ) return result
class ClosureGiverNodeBase(CodeNodeBase): """ Mixin for nodes that provide variables for closure takers. """ def __init__(self, name, code_prefix, source_ref): CodeNodeBase.__init__(self, name=name, code_prefix=code_prefix, source_ref=source_ref) self.providing = OrderedDict() self.keeper_variables = OrderedSet() def hasProvidedVariable(self, variable_name): return variable_name in self.providing def getProvidedVariable(self, variable_name): if variable_name not in self.providing: self.providing[variable_name] = self.createProvidedVariable( variable_name=variable_name) return self.providing[variable_name] def createProvidedVariable(self, variable_name): # Virtual method, pylint: disable=R0201,W0613 assert type(variable_name) is str return None def registerProvidedVariables(self, variables): for variable in variables: self.registerProvidedVariable(variable) def registerProvidedVariable(self, variable): assert variable is not None self.providing[variable.getName()] = variable def getProvidedVariables(self): return self.providing.values() def getTempKeeperVariable(self): name = "keeper_%d" % len(self.keeper_variables) from nuitka import Variables result = Variables.TempKeeperVariable(owner=self, variable_name=name) self.keeper_variables.add(result) return result
class ConstraintCollectionBranch( ConstraintCollectionBase ): def __init__( self, parent ): ConstraintCollectionBase.__init__( self, parent = parent ) self.branch_only_traces = OrderedSet() def process( self, branch ): assert branch.isStatementsSequence(), branch result = self.onStatementsSequence( branch ) if result is not branch: branch.replaceWith( result ) def onVariableSet( self, target_node, value_friend ): # Add a new trace, allocating a new version for the variable, and remember the value # friend. key = self.parent.onVariableSet( target_node = target_node, value_friend = value_friend ) # Remember the version, because it was added to this branch only, which matters # for merge later. self.branch_only_traces.add( key ) return key def onVariableUsage( self, ref_node ): key = self.parent.onVariableUsage( ref_node = ref_node ) if key is not None: self.branch_only_traces.add( key ) return key def getBranchOnlyTraces( self ): return self.branch_only_traces def mergeBranches( self, collection_yes, collection_no ): # Branches in branches, should ask parent about merging them. return self.parent.mergeBranches( collection_yes, collection_no )
class ConstraintCollectionBranch(ConstraintCollectionBase): def __init__(self, parent): ConstraintCollectionBase.__init__(self, parent=parent) self.branch_only_traces = OrderedSet() def process(self, branch): assert branch.isStatementsSequence(), branch result = self.onStatementsSequence(branch) if result is not branch: branch.replaceWith(result) def onVariableSet(self, target_node, value_friend): # Add a new trace, allocating a new version for the variable, and remember the value # friend. key = self.parent.onVariableSet(target_node=target_node, value_friend=value_friend) # Remember the version, because it was added to this branch only, which matters # for merge later. self.branch_only_traces.add(key) return key def onVariableUsage(self, ref_node): key = self.parent.onVariableUsage(ref_node=ref_node) if key is not None: self.branch_only_traces.add(key) return key def getBranchOnlyTraces(self): return self.branch_only_traces def mergeBranches(self, collection_yes, collection_no): # Branches in branches, should ask parent about merging them. return self.parent.mergeBranches(collection_yes, collection_no)
class PythonModule(PythonModuleMixin, ChildrenHavingMixin, ClosureGiverNodeBase): """ Module The module is the only possible root of a tree. When there are many modules they form a forrest. """ kind = "PYTHON_MODULE" named_children = ( "body", ) checkers = { "body": checkModuleBody } def __init__(self, name, package_name, source_ref): ClosureGiverNodeBase.__init__( self, name = name, code_prefix = "module", source_ref = source_ref ) ChildrenHavingMixin.__init__( self, values = {}, ) PythonModuleMixin.__init__( self, name = name, package_name = package_name ) self.variables = set() # The list functions contained in that module. self.functions = OrderedSet() self.active_functions = OrderedSet() self.cross_used_functions = OrderedSet() # SSA trace based information about the module. self.collection = None def getDetails(self): return { "filename" : self.source_ref.getFilename(), "package" : self.package_name, "name" : self.name } def asXml(self): # The class is new style, false alarm: pylint: disable=E1002 result = super( PythonModule, self ).asXml() for function_body in self.functions: result.append( function_body.asXml() ) return result getBody = ChildrenHavingMixin.childGetter("body") setBody = ChildrenHavingMixin.childSetter("body") def isPythonModule(self): return True def getParent(self): assert False def getParentVariableProvider(self): return None def getVariables(self): return self.variables def getFilename(self): return self.source_ref.getFilename() def getVariableForAssignment(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForReference(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForClosure(self, variable_name): return self.getProvidedVariable( variable_name = variable_name ) def createProvidedVariable(self, variable_name): result = Variables.ModuleVariable( module = self, variable_name = variable_name ) assert result not in self.variables self.variables.add(result) return result def isEarlyClosure(self): # Modules should immediately closure variables on use. # pylint: disable=R0201 return True def getCodeName(self): def r(match): c = match.group() if c == '.': return "$" else: return "$$%d$" % ord(c) return "module_" + \ "".join(re.sub("[^a-zA-Z0-9_]", r ,c) for c in self.getFullName()) def addFunction(self, function_body): assert function_body not in self.functions self.functions.add( function_body ) def getFunctions(self): return self.functions def startTraversal(self): self.active_functions = OrderedSet() def addUsedFunction(self, function_body): assert function_body in self.functions assert function_body.isExpressionFunctionBody() if function_body not in self.active_functions: self.active_functions.add(function_body) def getUsedFunctions(self): return self.active_functions def addCrossUsedFunction(self, function_body): if function_body not in self.cross_used_functions: self.cross_used_functions.add(function_body) def getCrossUsedFunctions(self): return self.cross_used_functions def getOutputFilename(self): main_filename = self.getFilename() if main_filename.endswith(".py"): result = main_filename[:-3] else: result = main_filename # There are some characters that somehow are passed to shell, by # Scons or unknown, so lets avoid them for now. return result.replace(")","").replace("(","") # TODO: Can't really use locals for modules, this should probably be made # sure to not be used. def getLocalsMode(self): return "copy"
class PythonModule( ChildrenHavingMixin, ClosureGiverNodeBase, MarkContainsTryExceptIndicator ): """ Module The module is the only possible root of a tree. When there are many modules they form a forrest. """ kind = "PYTHON_MODULE" named_children = ( "body", ) def __init__( self, name, package, source_ref ): assert type(name) is str, type(name) assert "." not in name, name assert package is None or ( type( package ) is str and package != "" ) ClosureGiverNodeBase.__init__( self, name = name, code_prefix = "module", source_ref = source_ref ) ChildrenHavingMixin.__init__( self, values = {} ) MarkContainsTryExceptIndicator.__init__( self ) self.package = package self.variables = set() # The list functions contained in that module. self.functions = OrderedSet() def getDetails( self ): return { "filename" : self.source_ref.getFilename(), "package" : self.package, "name" : self.name } def asXml( self ): # The class is new style, false alarm: pylint: disable=E1002 result = super( PythonModule, self ).asXml() for function_body in self.functions: result.append( function_body.asXml() ) return result getBody = ChildrenHavingMixin.childGetter( "body" ) setBody = ChildrenHavingMixin.childSetter( "body" ) def isPythonModule( self ): return True def getParent( self ): assert False def getParentVariableProvider( self ): return None def getVariables( self ): return self.variables def getFilename( self ): return self.source_ref.getFilename() def getPackage( self ): return self.package def getFullName( self ): if self.package: return self.package + "." + self.getName() else: return self.getName() def getVariableForAssignment( self, variable_name ): result = self.getProvidedVariable( variable_name ) return result.makeReference( self ) def getVariableForReference( self, variable_name ): result = self.getProvidedVariable( variable_name ) return result.makeReference( self ) def getVariableForClosure( self, variable_name ): return self.getProvidedVariable( variable_name = variable_name ) def createProvidedVariable( self, variable_name ): result = Variables.ModuleVariable( module = self, variable_name = variable_name ) assert result not in self.variables self.variables.add( result ) return result def isEarlyClosure( self ): # Modules should immediately closure variables on use, pylint: disable=R0201 return True def isMainModule( self ): return False def getCodeName( self ): return "module_" + self.getFullName().replace( ".", "__" ).replace( "-", "_" ) def addFunction( self, function_body ): assert function_body not in self.functions self.functions.add( function_body ) def getFunctions( self ): return self.functions def getOutputFilename( self ): main_filename = self.getFilename() if main_filename.endswith( ".py" ): return main_filename[:-3] else: return main_filename
class PythonModule(PythonModuleMixin, ChildrenHavingMixin, ClosureGiverNodeBase): """ Module The module is the only possible root of a tree. When there are many modules they form a forrest. """ kind = "PYTHON_MODULE" named_children = ( "body", ) checkers = { "body": checkModuleBody } def __init__(self, name, package_name, source_ref): ClosureGiverNodeBase.__init__( self, name = name, code_prefix = "module", source_ref = source_ref ) PythonModuleMixin.__init__( self, name = name, package_name = package_name ) ChildrenHavingMixin.__init__( self, values = { "body" : None # delayed }, ) self.variables = set() # The list functions contained in that module. self.functions = OrderedSet() self.active_functions = OrderedSet() self.cross_used_functions = OrderedSet() # SSA trace based information about the module. self.collection = None def getDetails(self): return { "filename" : self.source_ref.getFilename(), "package" : self.package_name, "name" : self.name } def asXml(self): result = super(PythonModule, self).asXml() for function_body in self.functions: result.append(function_body.asXml()) return result getBody = ChildrenHavingMixin.childGetter("body") setBody = ChildrenHavingMixin.childSetter("body") @staticmethod def isPythonModule(): return True def getParent(self): assert False def getParentVariableProvider(self): return None def getVariables(self): return self.variables def getFilename(self): return self.source_ref.getFilename() def getVariableForAssignment(self, variable_name): return self.getProvidedVariable(variable_name) def getVariableForReference(self, variable_name): return self.getProvidedVariable(variable_name) def getVariableForClosure(self, variable_name): return self.getProvidedVariable( variable_name = variable_name ) def createProvidedVariable(self, variable_name): result = Variables.ModuleVariable( module = self, variable_name = variable_name ) assert result not in self.variables self.variables.add(result) return result def isEarlyClosure(self): # Modules should immediately closure variables on use. # pylint: disable=R0201 return True def getCodeName(self): def r(match): c = match.group() if c == '.': return "$" else: return "$$%d$" % ord(c) return "".join( re.sub("[^a-zA-Z0-9_]", r ,c) for c in self.getFullName() ) def addFunction(self, function_body): assert function_body not in self.functions self.functions.add(function_body) def getFunctions(self): return self.functions def startTraversal(self): self.active_functions = OrderedSet() def addUsedFunction(self, function_body): assert function_body in self.functions assert function_body.isExpressionFunctionBody() if function_body not in self.active_functions: self.active_functions.add(function_body) def getUsedFunctions(self): return self.active_functions def addCrossUsedFunction(self, function_body): if function_body not in self.cross_used_functions: self.cross_used_functions.add(function_body) def getCrossUsedFunctions(self): return self.cross_used_functions def getOutputFilename(self): main_filename = self.getFilename() if main_filename.endswith(".py"): result = main_filename[:-3] else: result = main_filename # There are some characters that somehow are passed to shell, by # Scons or unknown, so lets avoid them for now. return result.replace(")","").replace("(","") # TODO: Can't really use locals for modules, this should probably be made # sure to not be used. @staticmethod def getLocalsMode(): return "copy" def computeModule(self): self.collection = ConstraintCollectionModule() module_body = self.getBody() if module_body is not None: result = module_body.computeStatementsSequence( constraint_collection = self.collection ) if result is not module_body: self.setBody(result) self.collection.makeVariableTraceOptimizations(self)
class PythonModule(ChildrenHavingMixin, ClosureGiverNodeBase, MarkContainsTryExceptIndicator): """ Module The module is the only possible root of a tree. When there are many modules they form a forrest. """ kind = "PYTHON_MODULE" named_children = ("body", ) def __init__(self, name, package, source_ref): assert type(name) is str, type(name) assert "." not in name, name assert package is None or (type(package) is str and package != "") ClosureGiverNodeBase.__init__(self, name=name, code_prefix="module", source_ref=source_ref) ChildrenHavingMixin.__init__(self, values={}) MarkContainsTryExceptIndicator.__init__(self) self.package = package self.variables = set() # The list functions contained in that module. self.functions = OrderedSet() def getDetails(self): return { "filename": self.source_ref.getFilename(), "package": self.package, "name": self.name } def asXml(self): # The class is new style, false alarm: pylint: disable=E1002 result = super(PythonModule, self).asXml() for function_body in self.functions: result.append(function_body.asXml()) return result getBody = ChildrenHavingMixin.childGetter("body") setBody = ChildrenHavingMixin.childSetter("body") def isPythonModule(self): return True def getParent(self): assert False def getParentVariableProvider(self): return None def getVariables(self): return self.variables def getFilename(self): return self.source_ref.getFilename() def getPackage(self): return self.package def getFullName(self): if self.package: return self.package + "." + self.getName() else: return self.getName() def getVariableForAssignment(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForReference(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForClosure(self, variable_name): return self.getProvidedVariable(variable_name=variable_name) def createProvidedVariable(self, variable_name): result = Variables.ModuleVariable(module=self, variable_name=variable_name) assert result not in self.variables self.variables.add(result) return result def isEarlyClosure(self): # Modules should immediately closure variables on use, pylint: disable=R0201 return True def isMainModule(self): return False def getCodeName(self): return "module_" + self.getFullName().replace(".", "__").replace( "-", "_") def addFunction(self, function_body): assert function_body not in self.functions self.functions.add(function_body) def getFunctions(self): return self.functions def getOutputFilename(self): main_filename = self.getFilename() if main_filename.endswith(".py"): return main_filename[:-3] else: return main_filename
class ClosureGiverNodeBase(CodeNodeBase): """ Mixin for nodes that provide variables for closure takers. """ def __init__(self, name, code_prefix, source_ref): CodeNodeBase.__init__( self, name = name, code_prefix = code_prefix, source_ref = source_ref ) self.providing = OrderedDict() self.keeper_variables = OrderedSet() self.temp_variables = OrderedDict() self.temp_scopes = OrderedDict() def hasProvidedVariable(self, variable_name): return variable_name in self.providing def getProvidedVariable(self, variable_name): if variable_name not in self.providing: self.providing[ variable_name ] = self.createProvidedVariable( variable_name = variable_name ) return self.providing[ variable_name ] def createProvidedVariable(self, variable_name): # Virtual method, pylint: disable=R0201,W0613 assert type( variable_name ) is str return None def registerProvidedVariables(self, variables): for variable in variables: self.registerProvidedVariable( variable ) def registerProvidedVariable(self, variable): assert variable is not None self.providing[ variable.getName() ] = variable def getProvidedVariables(self): return self.providing.values() def allocateTempKeeperVariable(self): name = "keeper_%d" % len( self.keeper_variables ) result = Variables.TempKeeperVariable( owner = self, variable_name = name ) self.keeper_variables.add( result ) return result def getTempKeeperVariables(self): return self.keeper_variables def removeTempKeeperVariable(self, variable): self.keeper_variables.discard( variable ) def allocateTempScope(self, name, allow_closure = False): self.temp_scopes[ name ] = self.temp_scopes.get( name, 0 ) + 1 # TODO: Instead of using overly long code name, could just visit parents # and make sure to allocate the scope at the top. if allow_closure: return "%s_%s_%d" % ( self.getCodeName(), name, self.temp_scopes[ name ] ) else: return "%s_%d" % ( name, self.temp_scopes[ name ] ) def allocateTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % ( temp_scope, name ) else: full_name = name del name assert full_name not in self.temp_variables, full_name result = Variables.TempVariable( owner = self, variable_name = full_name ) self.temp_variables[ full_name ] = result return result def getTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % ( temp_scope, name ) else: full_name = name return self.temp_variables[ full_name ] def getTempVariables(self): return tuple( self.temp_variables.values() ) def removeTempVariable(self, variable): del self.temp_variables[ variable.getName() ]
class PythonModule(PythonModuleMixin, ChildrenHavingMixin, ClosureGiverNodeBase, MarkContainsTryExceptIndicator): """ Module The module is the only possible root of a tree. When there are many modules they form a forrest. """ kind = "PYTHON_MODULE" named_children = ("body", ) checkers = {"body": checkModuleBody} def __init__(self, name, package_name, source_ref): ClosureGiverNodeBase.__init__(self, name=name, code_prefix="module", source_ref=source_ref) ChildrenHavingMixin.__init__( self, values={}, ) MarkContainsTryExceptIndicator.__init__(self) PythonModuleMixin.__init__(self, name=name, package_name=package_name) self.variables = set() # The list functions contained in that module. self.functions = OrderedSet() self.active_functions = OrderedSet() # SSA trace based information about the module. self.collection = None def getDetails(self): return { "filename": self.source_ref.getFilename(), "package": self.package_name, "name": self.name } def asXml(self): # The class is new style, false alarm: pylint: disable=E1002 result = super(PythonModule, self).asXml() for function_body in self.functions: result.append(function_body.asXml()) return result getBody = ChildrenHavingMixin.childGetter("body") setBody = ChildrenHavingMixin.childSetter("body") def isPythonModule(self): return True def getParent(self): assert False def getParentVariableProvider(self): return None def getVariables(self): return self.variables def getFilename(self): return self.source_ref.getFilename() def getVariableForAssignment(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForReference(self, variable_name): result = self.getProvidedVariable(variable_name) return result.makeReference(self) def getVariableForClosure(self, variable_name): return self.getProvidedVariable(variable_name=variable_name) def createProvidedVariable(self, variable_name): result = Variables.ModuleVariable(module=self, variable_name=variable_name) assert result not in self.variables self.variables.add(result) return result def isEarlyClosure(self): # Modules should immediately closure variables on use. # pylint: disable=R0201 return True def getCodeName(self): def r(match): c = match.group() if c == '.': return "$" else: return "$$%d$" % ord(c) return "module_" + \ "".join(re.sub("[^a-zA-Z0-9_]", r ,c) for c in self.getFullName()) def addFunction(self, function_body): assert function_body not in self.functions self.functions.add(function_body) def getFunctions(self): return self.functions def startTraversal(self): self.active_functions = OrderedSet() def addUsedFunction(self, function_body): assert function_body in self.functions assert function_body.isExpressionFunctionBody() if function_body not in self.active_functions: self.active_functions.add(function_body) def getUsedFunctions(self): return self.active_functions def getOutputFilename(self): main_filename = self.getFilename() if main_filename.endswith(".py"): return main_filename[:-3] else: return main_filename
class ClosureGiverNodeBase(CodeNodeBase): """ Mixin for nodes that provide variables for closure takers. """ def __init__(self, name, code_prefix, source_ref): CodeNodeBase.__init__(self, name=name, code_prefix=code_prefix, source_ref=source_ref) self.providing = OrderedDict() self.keeper_variables = OrderedSet() self.temp_variables = OrderedDict() self.temp_scopes = OrderedDict() def hasProvidedVariable(self, variable_name): return variable_name in self.providing def getProvidedVariable(self, variable_name): if variable_name not in self.providing: self.providing[variable_name] = self.createProvidedVariable( variable_name=variable_name) return self.providing[variable_name] def createProvidedVariable(self, variable_name): # Virtual method, pylint: disable=R0201,W0613 assert type(variable_name) is str return None def registerProvidedVariables(self, variables): for variable in variables: self.registerProvidedVariable(variable) def registerProvidedVariable(self, variable): assert variable is not None self.providing[variable.getName()] = variable def getProvidedVariables(self): return self.providing.values() def allocateTempKeeperVariable(self): name = "keeper_%d" % len(self.keeper_variables) result = Variables.TempKeeperVariable(owner=self, variable_name=name) self.keeper_variables.add(result) return result def getTempKeeperVariables(self): return self.keeper_variables def removeTempKeeperVariable(self, variable): self.keeper_variables.discard(variable) def allocateTempScope(self, name, allow_closure=False): self.temp_scopes[name] = self.temp_scopes.get(name, 0) + 1 # TODO: Instead of using overly long code name, could just visit parents # and make sure to allocate the scope at the top. if allow_closure: return "%s_%s_%d" % (self.getCodeName(), name, self.temp_scopes[name]) else: return "%s_%d" % (name, self.temp_scopes[name]) def allocateTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % (temp_scope, name) else: full_name = name del name assert full_name not in self.temp_variables, full_name result = Variables.TempVariable(owner=self, variable_name=full_name) self.temp_variables[full_name] = result return result def getTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % (temp_scope, name) else: full_name = name return self.temp_variables[full_name] def getTempVariables(self): return tuple(self.temp_variables.values()) def removeTempVariable(self, variable): del self.temp_variables[variable.getName()]