87 | 87 |
raise InconsistentConstraintsError('%s in %s' % (ref.name, routine.name))
|
88 | 88 |
self._writeable.add(ref)
|
89 | 89 |
|
|
90 |
def __str__(self):
|
|
91 |
def locstr(loc):
|
|
92 |
if isinstance(loc, LocationRef):
|
|
93 |
return "{}:{}".format(loc.name, loc.type)
|
|
94 |
else:
|
|
95 |
return str(loc)
|
|
96 |
|
|
97 |
def locsetstr(s):
|
|
98 |
return '{' + ', '.join([locstr(loc) for loc in list(s)]) + '}'
|
|
99 |
|
|
100 |
return "Context(\n _touched={},\n _meaningful={},\n _writeable={}\n)".format(
|
|
101 |
locsetstr(self._touched), locsetstr(self._meaningful), locsetstr(self._writeable)
|
|
102 |
)
|
|
103 |
|
90 | 104 |
def clone(self):
|
91 | 105 |
c = Context(self.routines, self.routine, [], [], [])
|
92 | 106 |
c._touched = set(self._touched)
|
|
156 | 170 |
|
157 | 171 |
class Analyzer(object):
|
158 | 172 |
|
159 | |
def __init__(self):
|
|
173 |
def __init__(self, debug=False):
|
160 | 174 |
self.current_routine = None
|
161 | 175 |
self.has_encountered_goto = False
|
162 | 176 |
self.routines = {}
|
|
177 |
self.debug = debug
|
163 | 178 |
|
164 | 179 |
def assert_type(self, type, *locations):
|
165 | 180 |
for location in locations:
|
|
183 | 198 |
return
|
184 | 199 |
type = routine.location.type
|
185 | 200 |
context = Context(self.routines, routine, type.inputs, type.outputs, type.trashes)
|
|
201 |
if self.debug:
|
|
202 |
print "at start of routine `{}`:".format(routine.name)
|
|
203 |
print context
|
186 | 204 |
self.analyze_block(routine.block, context)
|
|
205 |
if self.debug:
|
|
206 |
print "at end of routine `{}`:".format(routine.name)
|
|
207 |
print context
|
187 | 208 |
if not self.has_encountered_goto:
|
188 | 209 |
for ref in type.outputs:
|
189 | 210 |
context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError)
|
|
241 | 262 |
self.assert_type(TYPE_WORD, src, dest)
|
242 | 263 |
context.assert_meaningful(src, dest, FLAG_C)
|
243 | 264 |
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
|
265 |
context.set_touched(REG_A)
|
244 | 266 |
context.set_unmeaningful(REG_A)
|
245 | 267 |
elif opcode == 'sub':
|
246 | 268 |
self.assert_type(TYPE_BYTE, src, dest)
|