From cf679b293a4b27153a1b591a121e45e3367a7402 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Thu, 7 Dec 2017 11:49:15 +0000 Subject: [PATCH] Ability to --debug analysis. Make 16-bit addition test pass. --- bin/sixtypical | 2 +- eg/add-word.60p | 9 +++++++++ src/sixtypical/analyzer.py | 24 +++++++++++++++++++++++- tests/SixtyPical Analysis.md | 4 ++-- 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 eg/add-word.60p diff --git a/bin/sixtypical b/bin/sixtypical index cee196f..64d065d 100755 --- a/bin/sixtypical +++ b/bin/sixtypical @@ -56,7 +56,7 @@ if __name__ == '__main__': if options.analyze: try: - analyzer = Analyzer() + analyzer = Analyzer(debug=options.debug) analyzer.analyze_program(program) except Exception as e: if options.traceback: diff --git a/eg/add-word.60p b/eg/add-word.60p new file mode 100644 index 0000000..6cce2b5 --- /dev/null +++ b/eg/add-word.60p @@ -0,0 +1,9 @@ +word score +routine main + inputs score + outputs score + trashes c, z, v, n +{ + st off, c + add score, 1999 +} diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index f74c318..cd04653 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -88,6 +88,20 @@ class Context(object): raise InconsistentConstraintsError('%s in %s' % (ref.name, routine.name)) self._writeable.add(ref) + def __str__(self): + def locstr(loc): + if isinstance(loc, LocationRef): + return "{}:{}".format(loc.name, loc.type) + else: + return str(loc) + + def locsetstr(s): + return '{' + ', '.join([locstr(loc) for loc in list(s)]) + '}' + + return "Context(\n _touched={},\n _meaningful={},\n _writeable={}\n)".format( + locsetstr(self._touched), locsetstr(self._meaningful), locsetstr(self._writeable) + ) + def clone(self): c = Context(self.routines, self.routine, [], [], []) c._touched = set(self._touched) @@ -157,10 +171,11 @@ class Context(object): class Analyzer(object): - def __init__(self): + def __init__(self, debug=False): self.current_routine = None self.has_encountered_goto = False self.routines = {} + self.debug = debug def assert_type(self, type, *locations): for location in locations: @@ -184,7 +199,13 @@ class Analyzer(object): return type = routine.location.type context = Context(self.routines, routine, type.inputs, type.outputs, type.trashes) + if self.debug: + print "at start of routine `{}`:".format(routine.name) + print context self.analyze_block(routine.block, context) + if self.debug: + print "at end of routine `{}`:".format(routine.name) + print context if not self.has_encountered_goto: for ref in type.outputs: context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError) @@ -242,6 +263,7 @@ class Analyzer(object): self.assert_type(TYPE_WORD, src, dest) context.assert_meaningful(src, dest, FLAG_C) context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) + context.set_touched(REG_A) context.set_unmeaningful(REG_A) elif opcode == 'sub': self.assert_type(TYPE_BYTE, src, dest) diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index 9e7c753..c1afc13 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -399,7 +399,7 @@ You can `add` a word constant to a word memory location. | } ? UnmeaningfulOutputError: a in main -Not sure why this doesn't also raise an error? `a` is trashed... +To be sure, `add`ing a word constant to a word memory location trashes `a`. | word score | routine main @@ -410,7 +410,7 @@ Not sure why this doesn't also raise an error? `a` is trashed... | st off, c | add score, 1999 | } - ? UnmeaningfulOutputError: a in main + ? ForbiddenWriteError: a in main ### sub ###