From 3a4c2e46c10cddaad35f690e27a5f58c78f41902 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Tue, 11 Dec 2018 17:35:01 +0000 Subject: [PATCH] `inc` and `dec` on a known range usually keeps it known, now. --- HISTORY.md | 2 ++ eg/rudiments/vector-table.60p | 8 ------- src/sixtypical/analyzer.py | 15 +++++++++++- tests/SixtyPical Analysis.md | 43 +++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index c15b971..dda7e4c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -7,6 +7,8 @@ History of SixtyPical * Syntactically, `goto` may only appear at the end of a block. It need no longer be the final instruction in a routine, as long as the type context is consistent at every exit. +* When the range of a location is known, `inc` and `dec` + on it will usually shift the known instead of invalidating it. * `cmp` instruction can now perform a 16-bit unsigned comparison of `word` memory locations (at the cost of trashing `a`.) * Fixed pathological memory use in the lexical scanner - should diff --git a/eg/rudiments/vector-table.60p b/eg/rudiments/vector-table.60p index b6cce2a..6d6e98a 100644 --- a/eg/rudiments/vector-table.60p +++ b/eg/rudiments/vector-table.60p @@ -3,14 +3,6 @@ // Prints "AABAB". // -// TODO: this doesn't pass the analyzer currently, which suggests a bug. -// -// RangeExceededError: Possible range of x:byte (0, 255) exceeds -// acceptable range of vectors:vector table[32] (0, 31) (in main, line 57) -// -// (despite various attempts to work around by calling a setup routine, etc.) -// It should really be able to figure out that the range of x is 0..4 there. - vector routine trashes a, z, n print diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index cabff6d..9837424 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -597,7 +597,20 @@ class Analyzer(object): else: self.assert_type(TYPE_BYTE, dest) context.set_written(dest, FLAG_Z, FLAG_N) - context.invalidate_range(dest) + bottom = context.get_bottom_of_range(dest) + top = context.get_top_of_range(dest) + if opcode == 'inc': + if bottom == top and top < 255: + context.set_range(dest, bottom + 1, top + 1) + else: + context.invalidate_range(dest) + elif opcode == 'dec': + if bottom == top and bottom > 0: + context.set_range(dest, bottom - 1, top - 1) + else: + context.invalidate_range(dest) + else: + raise NotImplementedError elif opcode in ('shl', 'shr'): context.assert_meaningful(dest, FLAG_C) if isinstance(dest, IndexedRef): diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index 071553b..0331e7e 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -762,6 +762,49 @@ no longer be guaranteed. | } ? RangeExceededError +When the range of a location is known, incrementing or +decrementing that location's value will shift the known +range. It will not invalidate it unless the known range +is at the limits of the possible ranges for the type. + + | vector routine + | trashes a, z, n + | print + | + | vector (routine + | trashes a, z, n) + | table[32] vectors + | + | define main routine + | inputs vectors, print + | outputs vectors + | trashes print, a, x, z, n, c + | { + | ld x, 0 + | inc x + | copy print, vectors + x + | } + = ok + + | vector routine + | trashes a, z, n + | print + | + | vector (routine + | trashes a, z, n) + | table[32] vectors + | + | define main routine + | inputs vectors, print + | outputs vectors + | trashes print, a, x, z, n, c + | { + | ld x, 32 + | dec x + | copy print, vectors + x + | } + = ok + ### add ### Can't `add` from or to a memory location that isn't initialized.