Example #1
0
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
Example #2
0
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)
Example #5
0
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"
Example #6
0
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
Example #7
0
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)
Example #8
0
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
Example #9
0
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() ]
Example #10
0
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
Example #11
0
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()]