diff options
| author | 2015-05-20 11:03:22 +0100 | |
|---|---|---|
| committer | 2015-05-20 11:42:16 +0100 | |
| commit | c4de9436bbfe3a9c9adf48085b9344ad9a37c14b (patch) | |
| tree | bd2dca0a52db40fd1afb4acf991652a5bde07a81 | |
| parent | 27e542bd3c5430e4bf6fe265eb7e15eb4e401b77 (diff) | |
ART: Immutable `variables` dictionary in Checker
Python's lack of read-only references makes passing state information
to other functions unsafe. This patch adds an immutable dictionary
class to Checker and uses it when passing around current values of
variables.
Change-Id: I54f2eac54d4d59e16daa74364e6d91a6cc953f6f
| -rw-r--r-- | tools/checker/match/file.py | 3 | ||||
| -rw-r--r-- | tools/checker/match/line.py | 14 | ||||
| -rw-r--r-- | tools/checker/match/test.py | 5 |
3 files changed, 11 insertions, 11 deletions
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py index 2ed4aa7bc3..116fe9a764 100644 --- a/tools/checker/match/file.py +++ b/tools/checker/match/file.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from common.immutables import ImmutableDict from common.logger import Logger from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass from file_format.checker.struct import CheckerFile, TestCase, TestAssertion @@ -112,7 +113,7 @@ def __matchGroups(checkGroup, outputGroup): responsible for running the checks in the right order and scope, and for propagating the variable state between the check lines. """ - varState = {} + varState = ImmutableDict() checkLines = checkGroup.assertions outputLines = outputGroup.body startLineNo = outputGroup.startLineNo diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py index 20974301f2..711d814b10 100644 --- a/tools/checker/match/line.py +++ b/tools/checker/match/line.py @@ -32,20 +32,16 @@ def splitAtSeparators(expressions): return splitExpressions def matchWords(checkerWord, stringWord, variables, pos): - """ Attempts to match a list of RegexExpressions against a string. + """ Attempts to match a list of RegexExpressions against a string. Returns updated variable dictionary if successful and None otherwise. """ - # Create own copy of the variable dictionary, otherwise updates would change - # the caller's state. - variables = dict(variables) - for expression in checkerWord: # If `expression` is a variable reference, replace it with the value. if expression.variant == RegexExpression.Variant.VarRef: if expression.name in variables: pattern = re.escape(variables[expression.name]) else: - Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name), + Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name), pos.fileName, pos.lineNo) else: pattern = expression.pattern @@ -59,9 +55,9 @@ def matchWords(checkerWord, stringWord, variables, pos): # If `expression` was a variable definition, set the variable's value. if expression.variant == RegexExpression.Variant.VarDef: if expression.name not in variables: - variables[expression.name] = stringWord[:match.end()] + variables = variables.copyWith(expression.name, stringWord[:match.end()]) else: - Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name), + Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name), pos.fileName, pos.lineNo) # Move cursor by deleting the matched characters. @@ -70,7 +66,7 @@ def matchWords(checkerWord, stringWord, variables, pos): # Make sure the entire word matched, i.e. `stringWord` is empty. if stringWord: return None - + return variables def MatchLines(checkerLine, stringLine, variables): diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py index 0215f5023f..97725ad810 100644 --- a/tools/checker/match/test.py +++ b/tools/checker/match/test.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from common.immutables import ImmutableDict from common.testing import ToUnicode from file_format.c1visualizer.parser import ParseC1visualizerStream from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass @@ -33,7 +34,9 @@ class MatchLines_Test(unittest.TestCase): return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0) def tryMatch(self, checkerString, c1String, varState={}): - return MatchLines(self.createTestAssertion(checkerString), ToUnicode(c1String), varState) + return MatchLines(self.createTestAssertion(checkerString), + ToUnicode(c1String), + ImmutableDict(varState)) def matches(self, checkerString, c1String, varState={}): return self.tryMatch(checkerString, c1String, varState) is not None |