Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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)
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    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
Exemplo n.º 13
0
    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
        )
Exemplo n.º 14
0
    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
Exemplo n.º 15
0
    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
        )
Exemplo n.º 16
0
    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