git @ Cat's Eye Technologies SixtyPical / 82e33ab
Improve error messaging when constraints are exceeded. Chris Pressey 3 years ago
2 changed file(s) with 25 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
77 * Add word to pointer (unchecked for now).
88 * Added `word table` type.
99 * Can `copy` from word storage location to word table and back.
10 * A `vector` can name itself in its `inputs` and `outputs` or `trashes` sets.
1011 * Implementation: `--debug` shows some extra info during analysis.
1112 * Fixed bug where `copy`ing literal word into word storage used wrong endianness.
1213 * Fixed bug where every memory location was allocated 2 bytes of storage, regardless of type.
182182 raise TypeMismatchError('%s in %s' %
183183 (location.name, self.current_routine.name)
184184 )
185
186 def assert_affected_within(self, name, affected, limited_to):
187
188 def format(loc):
189 assert isinstance(loc, LocationRef)
190 return loc.name
191
192 if affected <= limited_to:
193 return
194 overage = affected - limited_to
195 overage_s = ', '.join(sorted([format(loc) for loc in overage]))
196 message = 'affected beyond %s: {%s} in %s' % (name, overage_s, self.current_routine.name)
197 raise IncompatibleConstraintsError(message)
185198
186199 def analyze_program(self, program):
187200 assert isinstance(program, Program)
363376 elif isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, LocationRef):
364377 if src.type == dest.type:
365378 pass
366 elif isinstance(src.type, ExecutableType) and \
367 isinstance(dest.type, VectorType):
368 # if dealing with routines and vectors,
369 # check that they're not incompatible
370 if not (src.type.inputs <= dest.type.inputs):
371 raise IncompatibleConstraintsError(src.type.inputs - dest.type.inputs)
372 if not (src.type.outputs <= dest.type.outputs):
373 raise IncompatibleConstraintsError(src.type.outputs - dest.type.outputs)
374 if not (src.type.trashes <= dest.type.trashes):
375 raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
379 elif isinstance(src.type, ExecutableType) and isinstance(dest.type, VectorType):
380 self.assert_affected_within('inputs', src.type.inputs, dest.type.inputs)
381 self.assert_affected_within('outputs', src.type.outputs, dest.type.outputs)
382 self.assert_affected_within('trashes', src.type.trashes, dest.type.trashes)
376383 else:
377384 raise TypeMismatchError((src, dest))
378385 else:
408415 self.analyze_block(instr.block, context)
409416 elif opcode == 'goto':
410417 location = instr.location
411 type = location.type
412
413 if not isinstance(type, ExecutableType):
418 type_ = location.type
419
420 if not isinstance(type_, ExecutableType):
414421 raise TypeMismatchError(location)
415422
416423 # assert that the dest routine's inputs are all initialized
417 for ref in type.inputs:
424 for ref in type_.inputs:
418425 context.assert_meaningful(ref)
419426
420427 # and that this routine's trashes and output constraints are a
421428 # superset of the called routine's
422429 current_type = self.current_routine.location.type
423 if not (type.outputs <= current_type.outputs):
424 raise IncompatibleConstraintsError(type.outputs - current_type.outputs)
425 if not (type.trashes <= current_type.trashes):
426 raise IncompatibleConstraintsError(type.trashes - current_type.trashes)
430 self.assert_affected_within('outputs', type_.outputs, current_type.outputs)
431 self.assert_affected_within('trashes', type_.trashes, current_type.trashes)
432
427433 self.has_encountered_goto = True
428434 else:
429435 raise NotImplementedError(opcode)