def compileTree():
    source_dir = OutputDirectories.getSourceDirectoryPath()

    general.info("Completed Python level compilation and optimization.")

    if not Options.shallOnlyExecCCompilerCall():
        general.info("Generating source code for C backend compiler.")

        if Options.isShowProgress() or Options.isShowMemory():
            general.info(
                "Total memory usage before generating C code: {memory}:".
                format(
                    memory=MemoryUsage.getHumanReadableProcessMemoryUsage()))
        # Now build the target language code for the whole tree.
        makeSourceDirectory()

        bytecode_accessor = ConstantAccessor(data_filename="__bytecode.const",
                                             top_level_name="bytecode_data")

        # This should take all bytecode values, even ones needed for frozen or
        # not produce anything.
        loader_code = LoaderCodes.getMetapathLoaderBodyCode(bytecode_accessor)

        writeSourceCode(filename=os.path.join(source_dir, "__loader.c"),
                        source_code=loader_code)

    else:
        source_dir = OutputDirectories.getSourceDirectoryPath()

        if not os.path.isfile(os.path.join(source_dir, "__helpers.h")):
            general.sysexit("Error, no previous build directory exists.")

    if Options.isShowProgress() or Options.isShowMemory():
        general.info(
            "Total memory usage before running scons: {memory}:".format(
                memory=MemoryUsage.getHumanReadableProcessMemoryUsage()))

    if Options.isShowMemory():
        InstanceCounters.printStats()

    if Options.is_debug:
        Reports.doMissingOptimizationReport()

    if Options.shallNotDoExecCCompilerCall():
        return True, {}

    general.info(
        "Running data composer tool for optimal constant value handling.")

    # TODO: On Windows, we could run this in parallel to Scons, on Linux we need it
    # for linking.
    runDataComposer(source_dir)

    general.info("Running C level backend compilation via Scons.")

    # Run the Scons to build things.
    result, options = runSconsBackend(quiet=not Options.isShowScons())

    return result, options
Exemplo n.º 2
0
def compileTree(main_module):
    source_dir = getSourceDirectoryPath(main_module)

    if not Options.shallOnlyExecCCompilerCall():
        # Now build the target language code for the whole tree.
        makeSourceDirectory(
            main_module = main_module
        )

        frozen_code = generateBytecodeFrozenCode()

        if frozen_code is not None:
            writeSourceCode(
                filename    = os.path.join(
                    source_dir,
                    "__frozen.c"
                ),
                source_code = frozen_code
            )

        writeBinaryData(
            filename    = os.path.join(
                source_dir,
                "__constants.bin"
            ),
            binary_data = ConstantCodes.stream_data.getBytes()
        )
    else:
        source_dir = getSourceDirectoryPath(main_module)

        if not os.path.isfile(os.path.join(source_dir, "__helpers.h")):
            sys.exit("Error, no previous build directory exists.")

    if Options.isShowProgress() or Options.isShowMemory():
        info(
            "Total memory usage before running scons: {memory}:".format(
                memory = MemoryUsage.getHumanReadableProcessMemoryUsage()
            )
        )

    if Options.isShowMemory():
        InstanceCounters.printStats()

    if Options.isDebug():
        Reports.doMissingOptimizationReport()

    if Options.shallNotDoExecCCompilerCall():
        return True, {}

    # Run the Scons to build things.
    result, options = runScons(
        main_module = main_module,
        quiet       = not Options.isShowScons()
    )

    return result, options
Exemplo n.º 3
0
def compileTree(main_module):
    source_dir = getSourceDirectoryPath(main_module)

    if not Options.shallOnlyExecCppCall():
        # Now build the target language code for the whole tree.
        makeSourceDirectory(
            main_module = main_module
        )

        if Options.isStandaloneMode():
            for module in detectLateImports():
                ModuleRegistry.addUncompiledModule(module)

        frozen_code = generateBytecodeFrozenCode()

        if frozen_code is not None:

            writeSourceCode(
                filename    = Utils.joinpath(
                    source_dir,
                    "__frozen.cpp"
                ),
                source_code = frozen_code
            )

        writeBinaryData(
            filename    = Utils.joinpath(source_dir, "__constants.bin"),
            binary_data = ConstantCodes.stream_data.getBytes()
        )
    else:
        source_dir = getSourceDirectoryPath(main_module)

        if not Utils.isFile(Utils.joinpath(source_dir, "__helpers.hpp")):
            sys.exit("Error, no previous build directory exists.")

    if Options.isShowProgress() or Options.isShowMemory():
        Tracing.printLine(
            "Total memory usage before running scons: {memory}:".format(
                memory = Utils.getHumanReadableProcessMemoryUsage()
            )
        )

    if Options.isShowMemory():
        InstanceCounters.printStats()

    if Options.shallNotDoExecCppCall():
        return True, {}

    # Run the Scons to build things.
    result, options = runScons(
        main_module = main_module,
        quiet       = not Options.isShowScons()
    )

    return result, options
Exemplo n.º 4
0
def compileTree(main_module):
    source_dir = getSourceDirectoryPath(main_module)

    if not Options.shallOnlyExecCCompilerCall():
        # Now build the target language code for the whole tree.
        makeSourceDirectory(main_module=main_module)

        frozen_code = generateBytecodeFrozenCode()

        if frozen_code is not None:
            writeSourceCode(
                filename=os.path.join(source_dir, "__frozen.c"), source_code=frozen_code
            )

        writeBinaryData(
            filename=os.path.join(source_dir, "__constants.bin"),
            binary_data=ConstantCodes.stream_data.getBytes(),
        )
    else:
        source_dir = getSourceDirectoryPath(main_module)

        if not os.path.isfile(os.path.join(source_dir, "__helpers.h")):
            sys.exit("Error, no previous build directory exists.")

    if Options.isShowProgress() or Options.isShowMemory():
        info(
            "Total memory usage before running scons: {memory}:".format(
                memory=MemoryUsage.getHumanReadableProcessMemoryUsage()
            )
        )

    if Options.isShowMemory():
        InstanceCounters.printStats()

    if Options.isDebug():
        Reports.doMissingOptimizationReport()

    if Options.shallNotDoExecCCompilerCall():
        return True, {}

    # Run the Scons to build things.
    result, options = runScons(main_module=main_module, quiet=not Options.isShowScons())

    return result, options
Exemplo n.º 5
0
class ValueTraceBase(object):
    # We are going to have many instance attributes, but should strive to minimize, as
    # there is going to be a lot of fluctuation in these objects.

    __slots__ = (
        "owner",
        "usage_count",
        "name_usage_count",
        "merge_usage_count",
        "closure_usages",
        "previous",
    )

    @InstanceCounters.counted_init
    def __init__(self, owner, previous):
        self.owner = owner

        # Definite usage indicator.
        self.usage_count = 0

        # If 0, this indicates, the variable name needs to be assigned as name.
        self.name_usage_count = 0

        # If 0, this indicates no value merges happened on the value.
        self.merge_usage_count = 0

        self.closure_usages = False

        # Previous trace this is replacing.
        self.previous = previous

    __del__ = InstanceCounters.counted_del()

    def __repr__(self):
        return "<%s of %s>" % (self.__class__.__name__,
                               self.owner.getCodeName())

    def getOwner(self):
        return self.owner

    @staticmethod
    def isLoopTrace():
        return False

    def addUsage(self):
        self.usage_count += 1

    def addNameUsage(self):
        self.usage_count += 1
        self.name_usage_count += 1

        if self.name_usage_count <= 2 and self.previous is not None:
            self.previous.addNameUsage()

    def addMergeUsage(self):
        self.usage_count += 1
        self.merge_usage_count += 1

    def getUsageCount(self):
        return self.usage_count

    def getNameUsageCount(self):
        return self.name_usage_count

    def getMergeUsageCount(self):
        return self.merge_usage_count

    def getMergeOrNameUsageCount(self):
        return self.merge_usage_count + self.name_usage_count

    def getPrevious(self):
        return self.previous

    @staticmethod
    def isAssignTrace():
        return False

    @staticmethod
    def isUnassignedTrace():
        return False

    @staticmethod
    def isDeletedTrace():
        return False

    @staticmethod
    def isUninitTrace():
        return False

    @staticmethod
    def isInitTrace():
        return False

    @staticmethod
    def isUnknownTrace():
        return False

    @staticmethod
    def isMergeTrace():
        return False

    def mustHaveValue(self):
        """Will this definitely have a value.

        Every trace has this overloaded.
        """
        assert False, self

    def mustNotHaveValue(self):
        """Will this definitely have a value.

        Every trace has this overloaded.
        """
        assert False, self

    def getReplacementNode(self, usage):
        # Virtual method, pylint: disable=no-self-use,unused-argument

        return None

    def hasShapeDictionaryExact(self):
        # Virtual method, pylint: disable=no-self-use
        return False
Exemplo n.º 6
0
class ValueTraceBase(object):
    # We are going to have many instance attributes

    __slots__ = ("owner", "usage_count", "has_potential_usages", "name_usages",
                 "closure_usages", "is_escaped", "previous")

    @InstanceCounters.counted_init
    def __init__(self, owner, previous):
        self.owner = owner

        # Definite usage indicator.
        self.usage_count = 0

        # Potential usages indicator that an assignment value may be used.
        self.has_potential_usages = False

        # If 0, this indicates, the variable name needs to be assigned as name.
        self.name_usages = 0

        self.closure_usages = False

        # If False, this indicates that the value is not yet escaped.
        self.is_escaped = False

        # Previous trace this is replacing.
        self.previous = previous

    __del__ = InstanceCounters.counted_del()

    def getOwner(self):
        return self.owner

    def addClosureUsage(self):
        self.addUsage()
        self.closure_usages = True

    def addUsage(self):
        self.usage_count += 1

    def addPotentialUsage(self):
        self.has_potential_usages = True

    def addNameUsage(self):
        self.usage_count += 1
        self.name_usages += 1

    def onValueEscape(self):
        self.is_escaped = True

    def isEscaped(self):
        return self.is_escaped

    def hasDefiniteUsages(self):
        return self.usage_count > 0

    def getDefiniteUsages(self):
        return self.usage_count

    def hasPotentialUsages(self):
        return self.has_potential_usages

    def getNameUsageCount(self):
        return self.name_usages

    def getPrevious(self):
        return self.previous

    @staticmethod
    def isAssignTrace():
        return False

    @staticmethod
    def isUninitTrace():
        return False

    @staticmethod
    def isInitTrace():
        return False

    @staticmethod
    def isUnknownTrace():
        return False

    @staticmethod
    def isMergeTrace():
        return False

    def mustHaveValue(self):
        # Merge traces have this overloaded.

        return self.isInitTrace() or self.isAssignTrace()

    @staticmethod
    def mustNotHaveValue():
        return False

    def getReplacementNode(self, usage):
        # Virtual method, pylint: disable=no-self-use,unused-argument

        return None

    def hasShapeDictionaryExact(self):
        # Virtual method, pylint: disable=no-self-use
        return False
Exemplo n.º 7
0
class Variable(getMetaClassBase("Variable")):

    # We will need all of these attributes, since we track the global
    # state and cache some decisions as attributes. TODO: But in some
    # cases, part of the these might be moved to the outside.
    __slots__ = (
        "variable_name",
        "owner",
        "version_number",
        "shared_users",
        "traces",
        "users",
        "writers",
    )

    @InstanceCounters.counted_init
    def __init__(self, owner, variable_name):
        assert type(variable_name) is str, variable_name
        assert type(owner) not in (tuple, list), owner

        self.variable_name = variable_name
        self.owner = owner

        self.version_number = 0

        self.shared_users = False

        self.traces = set()

        # Derived from all traces.
        self.users = None
        self.writers = None

    __del__ = InstanceCounters.counted_del()

    def finalize(self):
        del self.users
        del self.writers
        del self.traces
        del self.owner

    def __repr__(self):
        return "<%s '%s' of '%s'>" % (
            self.__class__.__name__,
            self.variable_name,
            self.owner.getName(),
        )

    @abstractmethod
    def getVariableType(self):
        pass

    def getDescription(self):
        return "variable '%s'" % self.variable_name

    def getName(self):
        return self.variable_name

    def getOwner(self):
        return self.owner

    def getEntryPoint(self):
        return self.owner.getEntryPoint()

    def getCodeName(self):
        var_name = self.variable_name
        var_name = var_name.replace(".", "$")
        var_name = Utils.encodeNonAscii(var_name)

        return var_name

    def allocateTargetNumber(self):
        self.version_number += 1

        return self.version_number

    @staticmethod
    def isLocalVariable():
        return False

    @staticmethod
    def isParameterVariable():
        return False

    @staticmethod
    def isModuleVariable():
        return False

    @staticmethod
    def isIncompleteModuleVariable():
        return False

    @staticmethod
    def isTempVariable():
        return False

    @staticmethod
    def isTempVariableBool():
        return False

    @staticmethod
    def isLocalsDictVariable():
        return False

    def addVariableUser(self, user):
        # Update the shared scopes flag.
        if user is not self.owner:
            self.shared_users = True

            # These are not really scopes, just shared uses.
            if (user.isExpressionGeneratorObjectBody()
                    or user.isExpressionCoroutineObjectBody()
                    or user.isExpressionAsyncgenObjectBody()):
                if self.owner is user.getParentVariableProvider():
                    return

            _variables_in_shared_scopes.add(self)

    def isSharedTechnically(self):
        if not self.shared_users:
            return False

        if not self.users:
            return False

        owner = self.owner.getEntryPoint()

        for user in self.users:
            user = user.getEntryPoint()

            while user is not owner and (
                (user.isExpressionFunctionBody() and not user.needsCreation())
                    or user.isExpressionClassBody()):
                user = user.getParentVariableProvider()

            if user is not owner:
                return True

        return False

    def addTrace(self, variable_trace):
        self.traces.add(variable_trace)

    def removeTrace(self, variable_trace):
        self.traces.remove(variable_trace)

    def updateUsageState(self):
        writers = set()
        users = set()

        for trace in self.traces:
            owner = trace.owner
            users.add(owner)

            if trace.isAssignTrace():
                writers.add(owner)
            elif trace.isDeletedTrace() and owner is not self.owner:
                writers.add(owner)

        self.writers = writers
        self.users = users

    def hasAccessesOutsideOf(self, provider):
        if not self.owner.locals_scope.complete:
            return None
        elif self.users is None:
            return False
        elif provider in self.users:
            return len(self.users) > 1
        else:
            return bool(self.users)

    def getMatchingAssignTrace(self, assign_node):
        for trace in self.traces:
            if trace.isAssignTrace() and trace.getAssignNode() is assign_node:
                return trace

        return None

    def getMatchingDelTrace(self, del_node):
        for trace in self.traces:
            if trace.isDeletedTrace() and trace.getDelNode() is del_node:
                return trace

        return None

    def getTypeShapes(self):
        result = set()

        for trace in self.traces:
            if trace.isAssignTrace():
                result.add(trace.getAssignNode().getTypeShape())
            elif trace.isUnknownTrace():
                result.add(tshape_unknown)
            elif trace.isInitTrace():
                result.add(tshape_unknown)
            elif trace.isUnassignedTrace():
                pass
            elif trace.isMergeTrace():
                pass
            # TODO: Remove this and be not unknown.
            elif trace.isLoopTrace():
                trace.getTypeShape().emitAlternatives(result.add)
            else:
                assert False, trace

        return result
Exemplo n.º 8
0
class Variable(object):

    # We will need all of these attributes, since we track the global
    # state and cache some decisions as attributes, pylint: disable=too-many-instance-attributes
    __slots__ = ("variable_name", "owner", "version_number", "shared_users",
                 "shared_scopes", "traces", "users", "writers")

    @InstanceCounters.counted_init
    def __init__(self, owner, variable_name):
        assert type(variable_name) is str, variable_name
        assert type(owner) not in (tuple, list), owner

        self.variable_name = variable_name
        self.owner = owner

        self.version_number = 0

        self.shared_users = False
        self.shared_scopes = False

        self.traces = set()

        # Derived from all traces.
        self.users = None
        self.writers = None

    __del__ = InstanceCounters.counted_del()

    def getDescription(self):
        return "variable '%s'" % self.variable_name

    def getName(self):
        return self.variable_name

    def getOwner(self):
        return self.owner

    def getEntryPoint(self):
        return self.owner.getEntryPoint()

    def getCodeName(self):
        var_name = self.variable_name
        var_name = var_name.replace('.', '$')
        var_name = Utils.encodeNonAscii(var_name)

        return var_name

    def allocateTargetNumber(self):
        self.version_number += 1

        return self.version_number

    # pylint: disable=no-self-use
    def isLocalVariable(self):
        return False

    def isParameterVariable(self):
        return False

    def isModuleVariable(self):
        return False

    def isTempVariable(self):
        return False

    # pylint: enable=R0201

    def addVariableUser(self, user):
        # Update the shared scopes flag.
        if user is not self.owner:
            # These are not really scopes.
            self.shared_users = True

            if user.isExpressionGeneratorObjectBody() or \
               user.isExpressionCoroutineObjectBody() or \
               user.isExpressionAsyncgenObjectBody():
                if self.owner is user.getParentVariableProvider():
                    return

            self.shared_scopes = True

    def isSharedAmongScopes(self):
        return self.shared_scopes

    def isSharedTechnically(self):
        if not self.shared_users:
            return False

        if not complete:
            return None

        if not self.users:
            return False

        owner = self.owner.getEntryPoint()

        for user in self.users:
            user = user.getEntryPoint()

            while user is not owner and \
                  (
                   (user.isExpressionFunctionBody() and not user.needsCreation()) or \
                   user.isExpressionClassBody()
                  ):
                user = user.getParentVariableProvider()

            if user is not owner:
                return True

        return False

    def addTrace(self, variable_trace):
        self.traces.add(variable_trace)

    def removeTrace(self, variable_trace):
        # Make it unusable, and break GC cycles while at it.
        variable_trace.previous = None

        self.traces.remove(variable_trace)

    def updateUsageState(self):
        writers = set()
        users = set()

        for trace in self.traces:
            owner = trace.owner
            users.add(owner)

            if trace.isAssignTrace():
                writers.add(owner)

        self.writers = writers
        self.users = users

    def hasWritesOutsideOf(self, user):
        if not complete:
            return None
        elif user in self.writers:
            return len(self.writers) > 1
        else:
            return bool(self.writers)

    def hasAccessesOutsideOf(self, provider):
        if not complete:
            return None
        elif self.users is None:
            return False
        elif provider in self.users:
            return len(self.users) > 1
        else:
            return bool(self.users)

    def hasDefiniteWrites(self):
        if not complete:
            return None
        else:
            return bool(self.writers)

    def getMatchingAssignTrace(self, assign_node):
        for trace in self.traces:
            if trace.isAssignTrace() and trace.getAssignNode() is assign_node:
                return trace

        return None

    def getTypeShapes(self):
        result = set()

        for trace in self.traces:
            if trace.isAssignTrace():
                result.add(
                    trace.getAssignNode().getAssignSource().getTypeShape())
            elif trace.isUnknownTrace():
                result.add(ShapeUnknown)
            elif trace.isUninitTrace():
                if trace.hasDefiniteUsages() or trace.hasPotentialUsages():
                    result.add(ShapeUnknown)
            elif trace.isInitTrace():
                result.add(ShapeUnknown)
            elif trace.isMergeTrace():
                pass
            else:
                assert False, trace

        return result
Exemplo n.º 9
0
class Variable:
    @InstanceCounters.counted_init
    def __init__(self, owner, variable_name):
        assert type(variable_name) is str, variable_name
        assert type(owner) not in (tuple, list), owner
        assert owner.getFullName

        self.variable_name = variable_name
        self.owner = owner

        self.read_only_indicator = None

        self.version_number = 0

    __del__ = InstanceCounters.counted_del()

    def getName(self):
        return self.variable_name

    def getCodeName(self):
        var_name = self.variable_name
        var_name = var_name.replace('.', '$')
        var_name = Utils.encodeNonAscii(var_name)

        return var_name

    def getOwner(self):
        return self.owner

    def getReadOnlyIndicator(self):
        return self.read_only_indicator

    def setReadOnlyIndicator(self, value):
        assert value in (True, False)

        self.read_only_indicator = value

    def allocateTargetNumber(self):
        self.version_number += 1

        return self.version_number

    # pylint: disable=R0201
    def isLocalVariable(self):
        return False

    def isMaybeLocalVariable(self):
        return False

    def isParameterVariable(self):
        return False

    def isNestedParameterVariable(self):
        return False

    def isModuleVariable(self):
        return False

    def isTempVariable(self):
        return False

    # pylint: enable=R0201

    def isSharedTechnically(self):
        from nuitka.VariableRegistry import isSharedTechnically
        return isSharedTechnically(self)

    def getDeclarationTypeCode(self):
        # Abstract method, pylint: disable=R0201
        assert False
Exemplo n.º 10
0
class VariableTraceBase:
    # We are going to have many instance attributes, pylint: disable=R0902

    @InstanceCounters.counted_init
    def __init__(self, variable, version, previous):
        self.variable = variable
        self.version = version

        # Definite usage indicator.
        self.usage_count = 0

        # Potential usages indicator that an assignment value may be used.
        self.has_potential_usages = False

        # If False, this indicates the trace has no explicit releases.
        self.has_releases = False

        # If False, this indicates, the variable name needs to be assigned.
        self.has_name_usages = False

        # If False, this indicates that the value is not yet escaped.
        self.is_escaped = False

        # Previous trace this is replacing.
        self.previous = previous

    __del__ = InstanceCounters.counted_del()

    def getVariable(self):
        return self.variable

    def getVersion(self):
        return self.version

    def addUsage(self):
        self.usage_count += 1

    def addPotentialUsage(self):
        self.has_potential_usages = True

    def addRelease(self):
        self.has_releases = True

    def addNameUsage(self):
        self.usage_count += 1
        self.has_name_usages = True

    def onValueEscape(self):
        self.is_escaped = True

    def isEscaped(self):
        return self.is_escaped

    def hasDefiniteUsages(self):
        return self.usage_count > 0

    def getDefiniteUsages(self):
        return self.usage_count

    def hasPotentialUsages(self):
        return self.has_potential_usages

    def hasNameUsages(self):
        return self.has_name_usages

    def getPrevious(self):
        return self.previous

    @staticmethod
    def isAssignTrace():
        return False

    @staticmethod
    def isUninitTrace():
        return False

    @staticmethod
    def isInitTrace():
        return False

    @staticmethod
    def isUnknownTrace():
        return False

    @staticmethod
    def isMergeTrace():
        return False

    def mustHaveValue(self):
        # TODO: Temporarily disable far reaching of assumptions, until value
        # escaping can be trusted.
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically():
            return False

        # Merge traces have this overloaded.

        return self.isInitTrace() or self.isAssignTrace()

    def mustNotHaveValue(self):
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically():
            return False

        return self.isUninitTrace()

    def getReplacementNode(self, usage):
        # Virtual method, pylint: disable=R0201,W0613

        return None
Exemplo n.º 11
0
class VariableTraceBase:
    @InstanceCounters.counted_init
    def __init__(self, variable, version, previous):
        self.variable = variable
        self.version = version

        # List of references.
        self.usages = []

        # List of releases of the node.
        self.releases = []

        # If not None, this indicates the last usage, where the value was not
        # yet escaped. If it is 0, it escaped immediately. Escaping is a one
        # time action.
        self.escaped_at = None

        # Previous trace this is replacing.
        self.previous = previous

    __del__ = InstanceCounters.counted_del()

    def getVariable(self):
        return self.variable

    def getVersion(self):
        return self.version

    def addUsage(self, ref_node):
        self.usages.append(ref_node)

    def addRelease(self, release_node):
        self.releases.append(release_node)

    def onValueEscape(self):
        self.escaped_at = len(self.usages)

    def isEscaped(self):
        return self.escaped_at is not None

    def getDefiniteUsages(self):
        return self.usages

    def getPrevious(self):
        return self.previous

    def getReleases(self):
        return self.releases

    @staticmethod
    def isAssignTrace():
        return False

    @staticmethod
    def isUninitTrace():
        return False

    @staticmethod
    def isInitTrace():
        return False

    @staticmethod
    def isUnknownTrace():
        return False

    @staticmethod
    def isMergeTrace():
        return False

    def mustHaveValue(self):
        # TODO: Temporarily disable far reaching of assumptions, until value
        # escaping can be trusted.
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically():
            return False

        # Merge traces have this overloaded.

        return self.isInitTrace() or self.isAssignTrace()

    def mustNotHaveValue(self):
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically():
            return False

        return self.isUninitTrace()
Exemplo n.º 12
0
class Variable:
    @InstanceCounters.counted_init
    def __init__(self, owner, variable_name):
        assert type(variable_name) is str, variable_name
        assert type(owner) not in (tuple, list), owner
        assert owner.getFullName

        self.variable_name = variable_name
        self.owner = owner

        self.version_number = 0

        self.global_trace = None

    __del__ = InstanceCounters.counted_del()

    def getName(self):
        return self.variable_name

    def getOwner(self):
        return self.owner

    def getGlobalVariableTrace(self):
        # Monkey patched later to then use it, pylint: disable=R0201
        return None

    def _getGlobalVariableTrace(self):
        return self.global_trace

    def setGlobalVariableTrace(self, global_trace):
        self.global_trace = global_trace

    def getCodeName(self):
        var_name = self.variable_name
        var_name = var_name.replace('.', '$')
        var_name = Utils.encodeNonAscii(var_name)

        return var_name

    def allocateTargetNumber(self):
        self.version_number += 1

        return self.version_number

    # pylint: disable=R0201
    def isLocalVariable(self):
        return False

    def isMaybeLocalVariable(self):
        return False

    def isParameterVariable(self):
        return False

    def isModuleVariable(self):
        return False

    def isTempVariable(self):
        return False

    # pylint: enable=R0201

    def isSharedTechnically(self):
        from nuitka.VariableRegistry import isSharedTechnically
        return isSharedTechnically(self)
Exemplo n.º 13
0
class VariableTraceBase(object):
    # We are going to have many instance attributes, pylint: disable=too-many-instance-attributes

    __slots__ = ("owner", "variable", "version", "usage_count",
                 "has_potential_usages", "name_usages", "closure_usages",
                 "is_escaped", "previous")

    @InstanceCounters.counted_init
    def __init__(self, owner, variable, version, previous):
        self.owner = owner
        self.variable = variable
        self.version = version

        # Definite usage indicator.
        self.usage_count = 0

        # Potential usages indicator that an assignment value may be used.
        self.has_potential_usages = False

        # If 0, this indicates, the variable name needs to be assigned as name.
        self.name_usages = 0

        self.closure_usages = False

        # If False, this indicates that the value is not yet escaped.
        self.is_escaped = False

        # Previous trace this is replacing.
        self.previous = previous

    __del__ = InstanceCounters.counted_del()

    def getVariable(self):
        return self.variable

    def getOwner(self):
        return self.owner

    def getVersion(self):
        return self.version

    def addClosureUsage(self):
        self.addUsage()
        self.closure_usages = True

    def addUsage(self):
        self.usage_count += 1

    def addPotentialUsage(self):
        self.has_potential_usages = True

    def addNameUsage(self):
        self.usage_count += 1
        self.name_usages += 1

    def onValueEscape(self):
        self.is_escaped = True

    def isEscaped(self):
        return self.is_escaped

    def hasDefiniteUsages(self):
        return self.usage_count > 0

    def getDefiniteUsages(self):
        return self.usage_count

    def hasPotentialUsages(self):
        return self.has_potential_usages

    def getNameUsageCount(self):
        return self.name_usages

    def getPrevious(self):
        return self.previous

    def getPickedCType(self, context):
        """ Return type to use for specific context. """

        user = context.getEntryPoint()
        owner = self.variable.getEntryPoint()

        if owner is user:
            if self.variable.isSharedTechnically():
                result = CTypeCellObject
            else:
                if enable_bool_ctype:
                    shapes = self.variable.getTypeShapes()

                    if len(shapes) > 1:
                        return CTypePyObjectPtr
                    else:
                        assert shapes, self
                        return shapes.pop().getCType()
                else:
                    return CTypePyObjectPtr
        elif context.isForDirectCall():
            if self.variable.isSharedTechnically():
                result = CTypeCellObject
            else:
                result = CTypePyObjectPtrPtr
        else:
            result = CTypeCellObject

        return result

    @staticmethod
    def isAssignTrace():
        return False

    @staticmethod
    def isUninitTrace():
        return False

    @staticmethod
    def isInitTrace():
        return False

    @staticmethod
    def isUnknownTrace():
        return False

    @staticmethod
    def isMergeTrace():
        return False

    def mustHaveValue(self):
        # TODO: Temporarily disable far reaching of assumptions, until value
        # escaping can be trusted.
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically() is not False:
            return False

        # Merge traces have this overloaded.

        return self.isInitTrace() or self.isAssignTrace()

    def mustNotHaveValue(self):
        if self.variable.isModuleVariable() or \
           self.variable.isSharedTechnically() is not False:
            return False

        return self.isUninitTrace()

    def getReplacementNode(self, usage):
        # Virtual method, pylint: disable=no-self-use,unused-argument

        return None

    def hasShapeDictionaryExact(self):
        # Virtual method, pylint: disable=no-self-use
        return False