1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-25 23:49:17 +00:00

Make ld parse to a IndexedRef or IndirectRef (latter still todo.)

This commit is contained in:
Chris Pressey 2018-02-08 11:04:11 +00:00
parent f87c07e52a
commit 34daad0e56
7 changed files with 63 additions and 15 deletions

View File

@ -1,7 +1,7 @@
SixtyPical
==========
_Version 0.11. Work-in-progress, everything is subject to change._
_Version 0.12. Work-in-progress, everything is subject to change._
SixtyPical is a very low-level programming language, similar to 6502 assembly,
with static analysis through abstract interpretation.

View File

@ -127,6 +127,9 @@ class Context(object):
if kwargs.get('message'):
message += ' (%s)' % kwargs['message']
raise exception_class(message)
elif isinstance(ref, IndexedRef):
self.assert_meaningful(ref.ref, **kwargs)
self.assert_meaningful(ref.index, **kwargs)
else:
raise NotImplementedError(ref)
@ -236,14 +239,16 @@ class Analyzer(object):
src = instr.src
if opcode == 'ld':
if instr.index:
if TableType.is_a_table_type(src.type, TYPE_BYTE) and dest.type == TYPE_BYTE:
if isinstance(src, IndexedRef):
if TableType.is_a_table_type(src.ref.type, TYPE_BYTE) and dest.type == TYPE_BYTE:
pass
else:
raise TypeMismatchError('%s and %s in %s' %
(src.name, dest.name, self.current_routine.name)
(src.ref.name, dest.name, self.current_routine.name)
)
context.assert_meaningful(instr.index)
context.assert_meaningful(src.index)
elif isinstance(src, IndirectRef):
raise NotImplementedError
elif src.type != dest.type:
raise TypeMismatchError('%s and %s in %s' %
(src.name, dest.name, self.current_routine.name)
@ -352,6 +357,9 @@ class Analyzer(object):
context.assert_meaningful(src)
elif opcode == 'copy':
if dest == REG_A:
raise ForbiddenWriteError("{} cannot be used as destination for copy".format(dest))
# 1. check that their types are compatible
if isinstance(src, AddressRef) and isinstance(dest, LocationRef):

View File

@ -131,9 +131,9 @@ class Compiler(object):
self.emitter.emit(TYA())
elif isinstance(src, ConstantRef):
self.emitter.emit(LDA(Immediate(Byte(src.value))))
elif instr.index == REG_X:
elif isinstance(src, IndexedRef) and src.index == REG_X:
self.emitter.emit(LDA(AbsoluteX(self.labels[src.name])))
elif instr.index == REG_Y:
elif isinstance(src, IndexedRef) and src.index == REG_Y:
self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
else:
self.emitter.emit(LDA(Absolute(self.labels[src.name])))
@ -142,7 +142,7 @@ class Compiler(object):
self.emitter.emit(TAX())
elif isinstance(src, ConstantRef):
self.emitter.emit(LDX(Immediate(Byte(src.value))))
elif instr.index == REG_Y:
elif isinstance(src, IndexedRef) and src.index == REG_Y:
self.emitter.emit(LDX(AbsoluteY(self.labels[src.name])))
else:
self.emitter.emit(LDX(Absolute(self.labels[src.name])))
@ -151,7 +151,7 @@ class Compiler(object):
self.emitter.emit(TAY())
elif isinstance(src, ConstantRef):
self.emitter.emit(LDY(Immediate(Byte(src.value))))
elif instr.index == REG_X:
elif isinstance(src, IndexedRef) and src.index == REG_X:
self.emitter.emit(LDY(AbsoluteX(self.labels[src.name])))
else:
self.emitter.emit(LDY(Absolute(self.labels[src.name])))

View File

@ -202,7 +202,8 @@ class IndexedRef(Ref):
@property
def name(self):
return '{}+{}'.format(self.ref.name, self.index.name)
return self.ref.name
#return '{}+{}'.format(self.ref.name, self.index.name)
def is_constant(self):
return False

View File

@ -316,7 +316,15 @@ class Parser(object):
self.scanner.expect('forever')
return Instr(opcode='repeat', dest=None, src=src,
block=block, inverted=inverted)
elif self.scanner.token in ("ld", "add", "sub", "cmp", "and", "or", "xor"):
elif self.scanner.token in ("ld",):
# the same as add, sub, cmp etc below, except supports an indlocexpr for the src
opcode = self.scanner.token
self.scanner.scan()
dest = self.locexpr()
self.scanner.expect(',')
src = self.indlocexpr()
return Instr(opcode=opcode, dest=dest, src=src, index=None)
elif self.scanner.token in ("add", "sub", "cmp", "and", "or", "xor"):
opcode = self.scanner.token
self.scanner.scan()
dest = self.locexpr()

View File

@ -1462,6 +1462,21 @@ Can `copy` from a `byte` to a `byte`.
| }
= ok
The understanding is that, because `copy` trashes `a`, `a` cannot be used
as the destination of a `copy`.
| byte source : 0
| byte dest
|
| routine main
| inputs source
| outputs dest
| trashes a, z, n
| {
| copy source, a
| }
? ForbiddenWriteError
Can `copy` from a `word` to a `word`.
| word source : 0
@ -1504,9 +1519,7 @@ Can't `copy` from a `word` to a `byte`.
| }
? TypeMismatchError
### copy[] ###
Buffers and pointers.
### Buffers and pointers ###
Note that `^buf` is a constant value, so it by itself does not require `buf` to be
listed in any input/output sets.
@ -1588,6 +1601,24 @@ Read through a pointer.
| }
= ok
Read through a pointer to the `a` register. Note that
this is done with `ld`, not `copy`.
| buffer[2048] buf
| pointer ptr
| byte foo
|
| routine main
| inputs buf
| outputs foo
| trashes a, y, z, n, ptr
| {
| ld y, 0
| copy ^buf, ptr
| ld a, [ptr] + y
| }
= ok
### routines ###
Routines are constants. You need not, and in fact cannot, specify a constant

View File

@ -846,7 +846,7 @@ Read through a pointer, into a byte storage location, or the `a` register.
| ld y, 0
| copy ^buf, ptr
| copy [ptr] + y, foo
| copy [ptr] + y, a
| ld a, [ptr] + y
| }
= $080D LDY #$00
= $080F LDA #$1F