def _handleNonLocal(node): # Take closure variables for non-local declarations. for non_local_names, source_ref in node.getNonlocalDeclarations(): for non_local_name in non_local_names: variable = node.getClosureVariable( variable_name = non_local_name ) if variable.isModuleVariable(): SyntaxErrors.raiseSyntaxError( "no binding for nonlocal '%s' found" % ( non_local_name ), source_ref = None if isFullCompat() and \ python_version < 340 else source_ref, display_file = not isFullCompat() or \ python_version >= 340, display_line = not isFullCompat() or \ python_version >= 340 ) node.registerProvidedVariable(variable) addVariableUsage(variable, node)
def completeVariableClosures(tree): visitors = ( VariableClosureLookupVisitorPhase1(), VariableClosureLookupVisitorPhase2(), VariableClosureLookupVisitorPhase3() ) for visitor in visitors: visitTree(tree, visitor) if tree.isCompiledPythonModule(): for function in tree.getFunctions(): visitTree(function, visitor) if tree.isCompiledPythonModule(): for function in tree.getFunctions(): addFunctionVariableReleases(function) # Python3 is influenced by the mere use of a variable named as # "super". So we need to prepare ability to take closure. if function.hasFlag("has_super"): if not function.hasVariableName("__class__"): class_var = function.getClosureVariable("__class__") function.registerProvidedVariable(class_var) addVariableUsage(class_var, function) if not function.hasVariableName("self"): self_var = function.getClosureVariable("self") function.registerProvidedVariable(self_var) addVariableUsage(self_var, function)
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 _handleNonLocal(node): # Take closure variables for non-local declarations. for non_local_names, source_ref in node.getNonlocalDeclarations(): for non_local_name in non_local_names: variable = node.getClosureVariable( variable_name=non_local_name) if variable.isModuleVariable(): SyntaxErrors.raiseSyntaxError( "no binding for nonlocal '%s' found" % ( non_local_name ), source_ref = None if isFullCompat() and \ python_version < 340 else source_ref, display_file = not isFullCompat() or \ python_version >= 340, display_line = not isFullCompat() or \ python_version >= 340 ) node.registerProvidedVariable(variable) addVariableUsage(variable, node)
def completeVariableClosures(tree): visitors = (VariableClosureLookupVisitorPhase1(), VariableClosureLookupVisitorPhase2(), VariableClosureLookupVisitorPhase3()) for visitor in visitors: visitTree(tree, visitor) if tree.isCompiledPythonModule(): for function in tree.getFunctions(): visitTree(function, visitor) if tree.isCompiledPythonModule(): for function in tree.getFunctions(): addFunctionVariableReleases(function) # Python3 is influenced by the mere use of a variable named as # "super". So we need to prepare ability to take closure. if function.hasFlag("has_super"): if not function.hasVariableName("__class__"): class_var = function.getClosureVariable("__class__") function.registerProvidedVariable(class_var) addVariableUsage(class_var, function) if not function.hasVariableName("self"): self_var = function.getClosureVariable("self") function.registerProvidedVariable(self_var) addVariableUsage(self_var, function)
def replacement(): if func.cached_value is None: func.cached_value = func() for variable in func.cached_value.getVariables(): addVariableUsage(variable, func.cached_value) return func.cached_value
def wrapSuperBuiltin(type_arg, object_arg, source_ref): if type_arg is None and python_version >= 300: provider = node.getParentVariableProvider() if python_version < 340 or True: # TODO: Temporarily reverted: type_arg = ExpressionVariableRef(variable_name="__class__", source_ref=source_ref) # Ought to be already closure taken. type_arg.setVariable(provider.getVariableForClosure(variable_name="__class__")) # If we already have this as a local variable, then use that # instead. if type_arg.getVariable().getOwner() is provider: type_arg = None else: addVariableUsage(type_arg.getVariable(), provider) else: parent_provider = provider.getParentVariableProvider() class_var = parent_provider.getTempVariable(temp_scope=None, name="__class__") type_arg = ExpressionTempVariableRef(variable=class_var, source_ref=source_ref) addVariableUsage(type_arg.getVariable(), provider) if type_arg is None: return makeRaiseExceptionReplacementExpression( expression=node, exception_type="SystemError" if python_version < 331 else "RuntimeError", exception_value="super(): __class__ cell not found", ) if object_arg is None: if provider.getParameters().getArgumentCount() > 0: par1_name = provider.getParameters().getArgumentNames()[0] # TODO: Nested first argument would kill us here, need a # test for that. object_arg = ExpressionVariableRef(variable_name=par1_name, source_ref=source_ref) object_arg.setVariable(provider.getVariableForReference(variable_name=par1_name)) if not object_arg.getVariable().isParameterVariable(): return makeRaiseExceptionReplacementExpression( expression=node, exception_type="SystemError" if python_version < 330 else "RuntimeError", exception_value="super(): __class__ cell not found", ) else: return makeRaiseExceptionReplacementExpression( expression=node, exception_type="RuntimeError", exception_value="super(): no arguments" ) return ExpressionBuiltinSuper(super_type=type_arg, super_object=object_arg, source_ref=source_ref)
def onEnterNode(self, node): if node.isExpressionVariableRef(): provider = node.getParentVariableProvider() if node.getVariable() is None: self._attachVariable(node, provider) addVariableUsage(node.getVariable(), provider) elif node.isExpressionTempVariableRef(): provider = node.getParentVariableProvider() addVariableUsage(node.getVariable(), provider)
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.isExpressionGeneratorObjectBody(): self._handleNonLocal(node) # Python3.4 allows for class declarations to be made global, even # after they were declared, so we need to fix this up. # TODO: Then this may not even have to be here at all. if python_version >= 340: self._handleQualnameSetup(node) elif node.isExpressionCoroutineObjectBody(): self._handleNonLocal(node) # TODO: Then this may not even have to be here at all. self._handleQualnameSetup(node) elif node.isExpressionClassBody(): self._handleNonLocal(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) elif node.isExpressionFunctionBody(): 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.isCompiledPythonModule(): break if current.isExpressionClassBody(): 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.isStatementLoopBreak() or node.isStatementLoopContinue(): current = node while True: if current.isParentVariableProvider(): if node.isStatementLoopContinue(): 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 wrapSuperBuiltin(type_arg, object_arg, source_ref): if type_arg is None and python_version >= 300: provider = node.getParentVariableProvider() type_arg = ExpressionVariableRef( variable_name = "__class__", source_ref = source_ref ) # Ought to be already closure taken. type_arg.setVariable( provider.getVariableForReference( variable_name = "__class__" ) ) # If we already have this as a local variable, then use that # instead. type_arg_owner = type_arg.getVariable().getOwner() if type_arg_owner is provider or \ not (type_arg_owner.isExpressionFunctionBody() or \ type_arg_owner.isExpressionClassBody()): type_arg = None else: addVariableUsage(type_arg.getVariable(), provider) if type_arg is None: return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "SystemError" if python_version < 331 else "RuntimeError", exception_value = "super(): __class__ cell not found", ) if object_arg is None: if provider.isExpressionGeneratorObjectBody(): parameter_provider = provider.getParentVariableProvider() else: parameter_provider = provider if parameter_provider.getParameters().getArgumentCount() > 0: par1_name = parameter_provider.getParameters().getArgumentNames()[0] object_arg = ExpressionVariableRef( variable_name = par1_name, source_ref = source_ref ) object_arg.setVariable( provider.getVariableForReference( variable_name = par1_name ) ) if not object_arg.getVariable().isParameterVariable(): return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "SystemError" if python_version < 330 else "RuntimeError", exception_value = "super(): __class__ cell not found", ) else: return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "RuntimeError", exception_value = "super(): no arguments" ) return ExpressionBuiltinSuper( super_type = type_arg, super_object = object_arg, source_ref = source_ref )
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 wrapSuperBuiltin(type, object, source_ref): if type is None and python_version >= 300: provider = node.getParentVariableProvider() if python_version < 340 or True: # TODO: Temporarily reverted: type = ExpressionVariableRef( variable_name = "__class__", source_ref = source_ref ) # Ought to be already closure taken. type.setVariable( provider.getVariableForClosure( variable_name = "__class__" ) ) # If we already have this as a local variable, then use that # instead. if not type.getVariable().isClosureReference(): type = None else: from nuitka.VariableRegistry import addVariableUsage addVariableUsage(type.getVariable(), provider) else: parent_provider = provider.getParentVariableProvider() class_var = parent_provider.getTempVariable( temp_scope = None, name = "__class__" ) type = ExpressionTempVariableRef( variable = class_var.makeReference(parent_provider).makeReference(provider), source_ref = source_ref ) from nuitka.VariableRegistry import addVariableUsage addVariableUsage(type.getVariable(), provider) from nuitka.nodes.NodeMakingHelpers import \ makeRaiseExceptionReplacementExpression if type is None: return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "SystemError" if python_version < 331 else "RuntimeError", exception_value = "super(): __class__ cell not found", ) if object is None: if provider.getParameters().getArgumentCount() > 0: par1_name = provider.getParameters().getArgumentNames()[0] # TODO: Nested first argument would kill us here, need a # test for that. object = ExpressionVariableRef( variable_name = par1_name, source_ref = source_ref ) object.setVariable( provider.getVariableForReference( variable_name = par1_name ) ) if not object.getVariable().isParameterVariable(): return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "SystemError" if python_version < 330 else "RuntimeError", exception_value = "super(): __class__ cell not found", ) else: return makeRaiseExceptionReplacementExpression( expression = node, exception_type = "RuntimeError", exception_value = "super(): no arguments" ) return ExpressionBuiltinSuper( super_type = type, super_object = object, source_ref = source_ref )
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(): node.setVariable( provider.getVariableForReference( variable_name=node.getVariableName())) elif node.isExpressionTempVariableRef(): if node.getVariable().getOwner() != node.getParentVariableProvider( ): node.setVariable( node.getParentVariableProvider().addClosureVariable( node.getVariable())) assert node.getVariable().isClosureReference(), \ node.getVariable() elif node.isExpressionFunctionBody(): if python_version >= 300: self._handleNonLocal(node) for variable in node.getParameters().getAllVariables(): addVariableUsage(variable, 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 source_ref = node.getSourceReference() # source_ref.line += 1 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 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(): node.setVariable( provider.getVariableForReference( variable_name = node.getVariableName() ) ) elif node.isExpressionTempVariableRef(): if node.getVariable().getOwner() != node.getParentVariableProvider(): node.setVariable( node.getParentVariableProvider().addClosureVariable( node.getVariable() ) ) assert node.getVariable().isClosureReference(), \ 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 and node.isClassDictCreation(): class_assign, qualname_assign = node.qualname_setup class_variable = class_assign.getTargetVariableRef().getVariable() if class_variable.isModuleVariable() and \ class_variable.isFromGlobalStatement(): qualname_node = qualname_assign.getAssignSource() qualname_node.replaceWith( makeConstantReplacementNode( constant = class_variable.getName(), node = qualname_node ) ) node.qualname_provider = node.getParentModule() # TODO: Actually for nested global classes, this approach # may not work, as their qualnames will be wrong. In that # case a dedicated node for qualname references might be # needed. del node.qualname_setup # 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 source_ref = node.getSourceReference() # source_ref.line += 1 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