Files
nuitka-mirror/nuitka/SourceCodeReferences.py
Kay Hayen 47332da901 Cleanup, syntax errors always improved.
* Always output the best syntax error format, and do away with compatible
  syntax errors. Instead make the comparison restricted to the message
  of error only.

* This reduces tedious code and tried to mimic the various Python versions
  errors for no good reasons.
2017-01-14 16:25:46 +01:00

150 lines
4.0 KiB
Python

# Copyright 2017, Kay Hayen, mailto:kay.hayen@gmail.com
#
# Part of "Nuitka", an optimizing Python compiler that is compatible and
# integrates with CPython, but also works on its own.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
""" Source code reference record.
All the information to lookup line and file of a code location, together with
the future flags in use there.
"""
from nuitka.nodes.FutureSpecs import FutureSpec
from nuitka.utils.InstanceCounters import counted_del, counted_init
class SourceCodeReference(object):
# TODO: Measure the access speed impact of slots. The memory savings is
# not worth it (only a few percent).
__slots__ = ["filename", "line", "column", "future_spec", "internal"]
@classmethod
def fromFilenameAndLine(cls, filename, line, future_spec):
result = cls()
result.filename = filename
result.line = line
result.future_spec = future_spec
return result
__del__ = counted_del()
@counted_init
def __init__(self):
self.filename = None
self.line = None
self.column = None
self.future_spec = None
self.internal = False
def __repr__(self):
return "<%s to %s:%s>" % (self.__class__.__name__, self.filename, self.line)
def __cmp__(self, other):
if other is None:
return -1
assert isinstance(other, SourceCodeReference), other
result = cmp(self.filename, other.filename)
if result == 0:
result = cmp(self.line, other.line)
if result == 0:
result = cmp(self.internal, other.internal)
return result
def _clone(self, line):
""" Make a copy it itself.
"""
result = SourceCodeReference.fromFilenameAndLine(
filename = self.filename,
line = line,
future_spec = self.future_spec
)
result.internal = self.internal
return result
def atInternal(self):
""" Make a copy it itself but mark as internal code.
Avoids useless copies, by returning an internal object again if
it is already internal.
"""
if not self.internal:
result = self._clone(self.line)
result.internal = True
return result
else:
return self
def atLineNumber(self, line):
""" Make a reference to the same file, but different line.
Avoids useless copies, by returning same object if the line is
the same.
"""
assert type(line) is int, line
if self.line != line:
return self._clone(line)
else:
return self
def atColumnNumber(self, column):
assert type(column) is int, column
if self.column != column:
result = self._clone(self.line)
result.column = column
return result
else:
return self
def getLineNumber(self):
return self.line
def getColumnNumber(self):
return self.column
def getFilename(self):
return self.filename
def getFutureSpec(self):
return self.future_spec
def getAsString(self):
return "%s:%s" % (self.filename, self.line)
def isInternal(self):
return self.internal
def fromFilename(filename):
return SourceCodeReference.fromFilenameAndLine(
filename = filename,
line = 1,
future_spec = FutureSpec(),
)