def setOwner(self, owner): if self.owner is not None: return ParameterSpecTuple.setOwner( self, owner ) if self.list_star_arg: self.list_star_variable = Variables.ParameterVariable( owner, self.list_star_arg, False ) else: self.list_star_variable = None if self.dict_star_arg: self.dict_star_variable = Variables.ParameterVariable( owner = owner, parameter_name = self.dict_star_arg, kw_only = False ) else: self.dict_star_variable = None self.kw_only_variables = [ Variables.ParameterVariable( self.owner, kw_only_arg, True ) for kw_only_arg in self.kw_only_args ]
def setOwner(self, owner): if self.owner is not None: return self.owner = owner self.normal_variables = [] for normal_arg in self.normal_args: if type(normal_arg) is str: normal_variable = Variables.ParameterVariable( owner=self.owner, parameter_name=normal_arg) else: assert False, normal_arg self.normal_variables.append(normal_variable) if self.list_star_arg: self.list_star_variable = Variables.ParameterVariable( owner=owner, parameter_name=self.list_star_arg) else: self.list_star_variable = None if self.dict_star_arg: self.dict_star_variable = Variables.ParameterVariable( owner=owner, parameter_name=self.dict_star_arg) else: self.dict_star_variable = None self.kw_only_variables = [ Variables.ParameterVariable(owner=self.owner, parameter_name=kw_only_arg) for kw_only_arg in self.kw_only_args ]
def setOwner(self, owner): assert self.owner is None self.owner = owner self.normal_variables = [] for count, normal_arg in enumerate( self.normal_args ): if type( normal_arg ) == str: normal_variable = Variables.ParameterVariable( owner = self.owner, parameter_name = normal_arg, kw_only = False ) elif type( normal_arg ) == tuple: sub_parameter_spec = ParameterSpecTuple( normal_args = normal_arg, nest_count = self.nest_count + 1 ) sub_parameter_spec.setOwner( self.owner ) sub_parameter_name = "Unpackable_%s_%s" % ( self.nest_count, count+1 ) normal_variable = Variables.NestedParameterVariable( owner = self.owner, parameter_name = sub_parameter_name, parameter_spec = sub_parameter_spec ) else: assert False, normal_arg self.normal_variables.append( normal_variable )
def makeOptimizationPass(): """Make a single pass for optimization, indication potential completion.""" # Controls complex optimization finished = True ModuleRegistry.startTraversal() _restartProgress() while True: current_module = ModuleRegistry.nextModule() if current_module is None: break _traceProgress(current_module) # The tag set is global, so it can react to changes without context. # pylint: disable=global-statement global tag_set tag_set = TagSet() changed = optimizeModule(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. This must be done after global # optimization due to cross module usages. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for unused_function in current_module.getUnusedFunctions(): Variables.updateVariablesFromCollection( old_collection=unused_function.trace_collection, new_collection=None, source_ref=unused_function.getSourceReference(), ) unused_function.trace_collection = None used_functions = tuple( function for function in current_module.subnode_functions if function in current_module.getUsedFunctions() ) current_module.setChild("functions", used_functions) _endProgress() return finished
def makeOptimizationPass(): """Make a single pass for optimization, indication potential completion.""" # Controls complex optimization finished = True ModuleRegistry.startTraversal() _restartProgress() while True: current_module = ModuleRegistry.nextModule() if current_module is None: # TODO: Internal module seems to cause extra passes. # optimizeModule(getInternalModule()) break _traceProgressModuleStart(current_module) changed = optimizeModule(current_module) _traceProgressModuleEnd(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. This must be done after global # optimization due to cross module usages. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for unused_function in current_module.getUnusedFunctions(): Variables.updateVariablesFromCollection( old_collection=unused_function.trace_collection, new_collection=None, source_ref=unused_function.getSourceReference(), ) unused_function.trace_collection = None used_functions = tuple( function for function in current_module.subnode_functions if function in current_module.getUsedFunctions() ) current_module.setChild("functions", used_functions) _endProgress() return finished
def makeOptimizationPass(initial_pass): """ Make a single pass for optimization, indication potential completion. """ finished = True ModuleRegistry.startTraversal() if _progress: if initial_pass: info("Initial optimization pass.") else: info("Next global optimization pass.") while True: current_module = ModuleRegistry.nextModule() if current_module is None: break if _progress: _traceProgress(current_module) # The tag set is global, so it can react to changes without context. # pylint: disable=global-statement global tag_set tag_set = TagSet() changed = optimizeModule(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for function in current_module.getUnusedFunctions(): Variables.updateFromCollection( old_collection=function.trace_collection, new_collection=None) function.trace_collection = None for current_module in ModuleRegistry.getDoneModules(): if optimizeVariables(current_module): finished = False return finished
def makeOptimizationPass(initial_pass): """ Make a single pass for optimization, indication potential completion. """ finished = True ModuleRegistry.startTraversal() if _progress: if initial_pass: printLine("Initial optimization pass.") else: printLine("Next global optimization pass.") while True: current_module = ModuleRegistry.nextModule() if current_module is None: break if _progress: _traceProgress(current_module) # The tag set is global, so it can react to changes without context. # pylint: disable=W0603 global tag_set tag_set = TagSet() changed = optimizeModule(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for function in current_module.getUnusedFunctions(): Variables.updateFromCollection( old_collection = function.trace_collection, new_collection = None ) function.trace_collection = None for current_module in ModuleRegistry.getDoneModules(): optimizeVariables(current_module) return finished
def allocateTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % ( temp_scope, name ) else: assert name != "result" 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 addVariableUsage(result, self) return result
def getLocalVariable(self, owner, variable_name): if variable_name not in self.local_variables: result = Variables.LocalVariable(owner=owner, variable_name=variable_name) self.local_variables[variable_name] = result return self.local_variables[variable_name]
def _optimizeModulePass(module, tag_set): def signalChange(tags, source_ref, message): """ Indicate a change to the optimization framework. """ debug("%s : %s : %s" % (source_ref.getAsString(), tags, message)) tag_set.onSignal(tags) constraint_collection = ConstraintCollectionModule(signalChange) constraint_collection.process(module=module) written_variables = constraint_collection.getWrittenVariables() for variable in Variables.getModuleVariables(module=module): old_value = variable.getReadOnlyIndicator() new_value = variable not in written_variables if old_value is not new_value and new_value: # Don't suddenly start to write. assert not (new_value is False and old_value is True) constraint_collection.signalChange( "read_only_mvar", module.getSourceReference(), "Determined variable '%s' is only read." % variable.getName()) variable.setReadOnlyIndicator(new_value)
def _optimizeModulePass( module, tag_set ): def signalChange( tags, source_ref, message ): """ Indicate a change to the optimization framework. """ debug( "%s : %s : %s" % ( source_ref.getAsString(), tags, message ) ) tag_set.onSignal( tags ) constraint_collection = ConstraintCollectionModule( signalChange ) constraint_collection.process( module = module ) written_variables = constraint_collection.getWrittenVariables() for variable in Variables.getModuleVariables( module = module ): old_value = variable.getReadOnlyIndicator() new_value = variable not in written_variables if old_value is not new_value and new_value: # Don't suddenly start to write. assert not (new_value is False and old_value is True) constraint_collection.signalChange( "read_only_mvar", module.getSourceReference(), "Determined variable '%s' is only read." % variable.getName() ) variable.setReadOnlyIndicator( new_value )
def createProvidedVariable(self, variable_name): # print("createProvidedVariable", self, variable_name) return Variables.LocalVariable( owner = self, variable_name = variable_name )
def createProvidedVariable(self, variable_name): # print( "createProvidedVariable", self, variable_name ) if self.local_locals: if self.isClassDictCreation(): return Variables.ClassVariable(owner=self, variable_name=variable_name) else: return Variables.LocalVariable(owner=self, variable_name=variable_name) else: # Make sure the provider knows it has to provide a variable of this # name for the assigment. self.provider.getVariableForAssignment(variable_name=variable_name) return self.getClosureVariable(variable_name=variable_name)
def getVariableForReference(self, variable_name): # print ( "REF func", self, variable_name ) if self.hasProvidedVariable(variable_name): result = self.getProvidedVariable(variable_name) else: result = self.getClosureVariable( variable_name = variable_name ) # Remember that we need that closure variable for something, so # we don't create it again all the time. if not result.isModuleVariable(): self.registerProvidedVariable(result) # For "exec" containing/star import containing, we get a # closure variable already, but if it is a module variable, # only then make it a maybe local variable. if self.isUnoptimized() and result.isModuleVariable(): result = Variables.MaybeLocalVariable( owner = self, maybe_variable = result ) self.registerProvidedVariable(result) return result
def getLocalsDictVariable(self, variable_name): if variable_name not in self.variables: result = Variables.LocalsDictVariable(owner=self, variable_name=variable_name) self.variables[variable_name] = result return self.variables[variable_name]
def createProvidedVariable(self, variable_name): assert variable_name not in self.variables result = Variables.ModuleVariable(module=self, variable_name=variable_name) self.variables[variable_name] = result return result
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 getTempVariable(self, name): assert name not in self.temp_variables, name result = Variables.TempVariable(owner=self, variable_name=name) self.temp_variables[name] = result return result
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 createTempVariable(self, temp_name): if temp_name in self.temp_variables: return self.temp_variables[temp_name] result = Variables.TempVariable(owner=self, variable_name=temp_name) self.temp_variables[temp_name] = result return result
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
def demoteClosureVariable(self, variable): assert variable.isLocalVariable() self.taken.remove(variable) assert variable.getOwner() is not self new_variable = Variables.LocalVariable( owner=self, variable_name=variable.getName()) self.providing[variable.getName()] = new_variable updateVariableUsage(provider=self, old_variable=variable, new_variable=new_variable) VariableRegistry.addVariableUsage(new_variable, self)
def getVariableForReference(self, variable_name): # print ( "REF func", self, variable_name ) if self.hasProvidedVariable(variable_name): result = self.getProvidedVariable(variable_name) else: # For exec containing/star import containing, get a closure variable # and if it is a module variable, only then make it a maybe local # variable. result = self.getClosureVariable(variable_name=variable_name) if self.isUnoptimized() and result.isModuleVariable(): result = Variables.MaybeLocalVariable( owner=self, variable_name=variable_name) # Remember that we need that closure for something. self.registerProvidedVariable(result) return result
def demoteClosureVariable(self, variable): assert variable.isLocalVariable() self.taken.remove(variable) assert variable.getOwner() is not self new_variable = Variables.LocalVariable( owner=self, variable_name=variable.getName()) for variable_trace in variable.traces: if variable_trace.getOwner() is self: new_variable.addTrace(variable_trace) new_variable.updateUsageState() self.providing[variable.getName()] = new_variable updateVariableUsage(provider=self, old_variable=variable, new_variable=new_variable)
def updateVariablesFromCollection(self, old_collection, source_ref): Variables.updateVariablesFromCollection(old_collection, self, source_ref)
def updateVariablesFromCollection(self, old_collection): Variables.updateVariablesFromCollection(old_collection, self)
def makeOptimizationPass(initial_pass): """ Make a single pass for optimization, indication potential completion. """ # Controls complex optimization, pylint: disable=too-many-branches finished = True ModuleRegistry.startTraversal() if _progress: if initial_pass: info("Initial optimization pass.") else: info("Next global optimization pass.") while True: current_module = ModuleRegistry.nextModule() if current_module is None: break if _progress: _traceProgress(current_module) # The tag set is global, so it can react to changes without context. # pylint: disable=global-statement global tag_set tag_set = TagSet() changed = optimizeModule(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for function in current_module.getUnusedFunctions(): Variables.updateVariablesFromCollection( old_collection=function.trace_collection, new_collection=None ) function.trace_collection = None for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): if optimizeVariables(current_module): finished = False used_functions = current_module.getUsedFunctions() for unused_function in current_module.getUnusedFunctions(): unused_function.trace_collection = None used_functions = tuple( function for function in current_module.getFunctions() if function in used_functions ) current_module.setFunctions(used_functions) if Variables.complete: if optimizeLocalsDictsHandles(): finished = False return finished
def getLocalVariableNames(self): return Variables.getNames(self.getLocalVariables())
def getParameterNames(self): return Variables.getNames(self.getVariables())
def onEnterNode(self, node): # Mighty complex code with lots of branches and statements, but it # couldn't be less without making it more difficult. # pylint: disable=R0912,R0915 if node.isExpressionTargetVariableRef(): provider = node.getParentVariableProvider() if node.getVariable() is None: variable_name = node.getVariableName() variable = provider.getVariableForAssignment( variable_name=variable_name) node.setVariable(variable) addVariableUsage(node.getVariable(), provider) elif node.isExpressionTargetTempVariableRef(): provider = node.getParentVariableProvider() addVariableUsage(node.getVariable(), provider) elif node.isExpressionVariableRef(): if node.getVariable() is None: provider = node.getParentVariableProvider() if provider.isEarlyClosure(): variable = provider.getVariableForReference( variable_name=node.getVariableName()) # Python3.4 version respects closure variables taken can be # overridden by writes to locals. It should be done for # globals too, on all versions, but for Python2 the locals # dictionary is avoided unless "exec" appears, so it's not # done. if variable.getOwner() is not provider: if python_version >= 340 or \ (python_version >= 300 and \ variable.isModuleVariable()): variable = Variables.MaybeLocalVariable( owner=provider, maybe_variable=variable) node.setVariable(variable) elif node.isExpressionTempVariableRef(): if node.getVariable().getOwner() != node.getParentVariableProvider( ): node.setVariable( node.getParentVariableProvider().addClosureVariable( node.getVariable())) elif node.isExpressionFunctionBody(): if python_version >= 300: self._handleNonLocal(node) for variable in node.getParameters().getAllVariables(): addVariableUsage(variable, node) # Python3.4 allows for class declarations to be made global, even # after they were declared, so we need to fix this up. if python_version >= 340: self._handleQualnameSetup(node) # Attribute access of names of class functions should be mangled, if # they start with "__", but do not end in "__" as well. elif node.isExpressionAttributeLookup() or \ node.isStatementAssignmentAttribute() or \ node.isStatementDelAttribute(): attribute_name = node.getAttributeName() if attribute_name.startswith("__") and \ not attribute_name.endswith("__"): seen_function = False current = node while True: current = current.getParentVariableProvider() if current.isPythonModule(): break assert current.isExpressionFunctionBody() if current.isClassDictCreation(): if seen_function: node.setAttributeName( "_%s%s" % (current.getName().lstrip("_"), attribute_name)) break else: seen_function = True # Check if continue and break are properly in loops. If not, raise a # syntax error. elif node.isStatementBreakLoop() or node.isStatementContinueLoop(): current = node while True: if current.isPythonModule() or \ current.isExpressionFunctionBody(): if node.isStatementContinueLoop(): message = "'continue' not properly in loop" col_offset = 16 if python_version >= 300 else None display_line = True source_line = None else: message = "'break' outside loop" if isFullCompat(): col_offset = 2 if python_version >= 300 else None display_line = True source_line = "" if python_version >= 300 else None else: col_offset = 13 display_line = True source_line = None SyntaxErrors.raiseSyntaxError( message, source_ref=node.getSourceReference(), col_offset=col_offset, display_line=display_line, source_line=source_line) current = current.getParent() if current.isStatementLoop(): break
def mangle(variable_name): return Variables.mangleName(variable_name, provider)
def makeOptimizationPass(): """Make a single pass for optimization, indication potential completion.""" # Controls complex optimization, pylint: disable=too-many-branches finished = True ModuleRegistry.startTraversal() while True: current_module = ModuleRegistry.nextModule() if current_module is None: break if _progress: _traceProgress(current_module) # The tag set is global, so it can react to changes without context. # pylint: disable=global-statement global tag_set tag_set = TagSet() changed = optimizeModule(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for function in current_module.getUnusedFunctions(): Variables.updateVariablesFromCollection( old_collection=function.trace_collection, new_collection=None, source_ref=function.getSourceReference(), ) function.trace_collection = None for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): if optimizeVariables(current_module): finished = False used_functions = current_module.getUsedFunctions() for unused_function in current_module.getUnusedFunctions(): unused_function.trace_collection = None used_functions = tuple( function for function in current_module.getFunctions() if function in used_functions) current_module.setFunctions(used_functions) if Variables.complete: if optimizeLocalsDictsHandles(): finished = False return finished