From 55331e9c5407cd22e858ed325a38dd85dadb9c31 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Fri, 9 Feb 2018 13:35:59 +0000 Subject: [PATCH] Statics are always writeable. Statics are always meaningful. --- src/sixtypical/analyzer.py | 14 +++++++++++++- src/sixtypical/model.py | 2 +- src/sixtypical/parser.py | 19 +++++++++++++------ tests/SixtyPical Analysis.md | 26 ++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index b63ff59..74466f4 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -53,6 +53,12 @@ class IncompatibleConstraintsError(ConstraintsError): pass +def routine_has_static(routine, ref): + if not hasattr(routine, 'statics'): + return False + return ref in [static.location for static in routine.statics] + + class Context(object): """ A location is touched if it was changed (or even potentially @@ -112,6 +118,9 @@ class Context(object): def assert_meaningful(self, *refs, **kwargs): exception_class = kwargs.get('exception_class', UnmeaningfulReadError) for ref in refs: + # statics are always meaningful + if routine_has_static(self.routine, ref): + continue if ref.is_constant() or ref in self.routines: pass elif isinstance(ref, LocationRef): @@ -129,6 +138,9 @@ class Context(object): def assert_writeable(self, *refs, **kwargs): exception_class = kwargs.get('exception_class', ForbiddenWriteError) for ref in refs: + # statics are always writeable + if routine_has_static(self.routine, ref): + continue if ref not in self._writeable: message = '%s in %s' % (ref.name, self.routine.name) if kwargs.get('message'): @@ -231,7 +243,7 @@ class Analyzer(object): for ref in type_.outputs: context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError) for ref in context.each_touched(): - if ref not in type_.outputs and ref not in type_.trashes: + if ref not in type_.outputs and ref not in type_.trashes and not routine_has_static(routine, ref): message = '%s in %s' % (ref.name, routine.name) raise ForbiddenWriteError(message) self.current_routine = None diff --git a/src/sixtypical/model.py b/src/sixtypical/model.py index 64e9880..3cc7f94 100644 --- a/src/sixtypical/model.py +++ b/src/sixtypical/model.py @@ -145,7 +145,7 @@ class LocationRef(Ref): # just to be sure. equal = isinstance(other, self.__class__) and other.name == self.name if equal: - assert other.type == self.type + assert other.type == self.type, repr((self, other)) return equal def __hash__(self): diff --git a/src/sixtypical/parser.py b/src/sixtypical/parser.py index 4da156c..f9423de 100644 --- a/src/sixtypical/parser.py +++ b/src/sixtypical/parser.py @@ -14,6 +14,9 @@ class SymEntry(object): self.ast_node = ast_node self.model = model + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model) + class Parser(object): def __init__(self, text): @@ -221,12 +224,7 @@ class Parser(object): else: statics = self.statics() - self.current_statics = {} - for defn in statics: - name = defn.name - if name in self.symbols or name in self.current_statics: - raise SyntaxError('Symbol "%s" already declared' % name) - self.current_statics[name] = SymEntry(defn, defn.location) + self.current_statics = self.compose_statics_dict(statics) block = self.block() self.current_statics = {} @@ -237,6 +235,15 @@ class Parser(object): location=location, statics=statics ) + def compose_statics_dict(self, statics): + c = {} + for defn in statics: + name = defn.name + if name in self.symbols or name in self.current_statics: + raise SyntaxError('Symbol "%s" already declared' % name) + c[name] = SymEntry(defn, defn.location) + return c + def labels(self): accum = [] accum.append(self.label()) diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index 641628a..05c556f 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -2283,3 +2283,29 @@ The new style routine definitions support typedefs. | copy foo, vec | } = ok + +### static ### + +When memory locations are defined static to a routine, they cannot be +directly input, nor directly output; and since they are always initialized, +they cannot be trashed. Thus, they really don't participate in the analysis. + + | define foo routine + | inputs x + | outputs x + | trashes z, n + | static byte t : 0 + | { + | st x, t + | inc t + | ld x, t + | } + | + | define main routine + | trashes a, x, z, n + | static byte t : 0 + | { + | ld x, t + | call foo + | } + = ok