1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-29 18:49:22 +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 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, SixtyPical is a very low-level programming language, similar to 6502 assembly,
with static analysis through abstract interpretation. with static analysis through abstract interpretation.

View File

@ -127,6 +127,9 @@ class Context(object):
if kwargs.get('message'): if kwargs.get('message'):
message += ' (%s)' % kwargs['message'] message += ' (%s)' % kwargs['message']
raise exception_class(message) raise exception_class(message)
elif isinstance(ref, IndexedRef):
self.assert_meaningful(ref.ref, **kwargs)
self.assert_meaningful(ref.index, **kwargs)
else: else:
raise NotImplementedError(ref) raise NotImplementedError(ref)
@ -236,14 +239,16 @@ class Analyzer(object):
src = instr.src src = instr.src
if opcode == 'ld': if opcode == 'ld':
if instr.index: if isinstance(src, IndexedRef):
if TableType.is_a_table_type(src.type, TYPE_BYTE) and dest.type == TYPE_BYTE: if TableType.is_a_table_type(src.ref.type, TYPE_BYTE) and dest.type == TYPE_BYTE:
pass pass
else: else:
raise TypeMismatchError('%s and %s in %s' % 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: elif src.type != dest.type:
raise TypeMismatchError('%s and %s in %s' % raise TypeMismatchError('%s and %s in %s' %
(src.name, dest.name, self.current_routine.name) (src.name, dest.name, self.current_routine.name)
@ -352,6 +357,9 @@ class Analyzer(object):
context.assert_meaningful(src) context.assert_meaningful(src)
elif opcode == 'copy': 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 # 1. check that their types are compatible
if isinstance(src, AddressRef) and isinstance(dest, LocationRef): if isinstance(src, AddressRef) and isinstance(dest, LocationRef):

View File

@ -131,9 +131,9 @@ class Compiler(object):
self.emitter.emit(TYA()) self.emitter.emit(TYA())
elif isinstance(src, ConstantRef): elif isinstance(src, ConstantRef):
self.emitter.emit(LDA(Immediate(Byte(src.value)))) 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]))) 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]))) self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
else: else:
self.emitter.emit(LDA(Absolute(self.labels[src.name]))) self.emitter.emit(LDA(Absolute(self.labels[src.name])))
@ -142,7 +142,7 @@ class Compiler(object):
self.emitter.emit(TAX()) self.emitter.emit(TAX())
elif isinstance(src, ConstantRef): elif isinstance(src, ConstantRef):
self.emitter.emit(LDX(Immediate(Byte(src.value)))) 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]))) self.emitter.emit(LDX(AbsoluteY(self.labels[src.name])))
else: else:
self.emitter.emit(LDX(Absolute(self.labels[src.name]))) self.emitter.emit(LDX(Absolute(self.labels[src.name])))
@ -151,7 +151,7 @@ class Compiler(object):
self.emitter.emit(TAY()) self.emitter.emit(TAY())
elif isinstance(src, ConstantRef): elif isinstance(src, ConstantRef):
self.emitter.emit(LDY(Immediate(Byte(src.value)))) 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]))) self.emitter.emit(LDY(AbsoluteX(self.labels[src.name])))
else: else:
self.emitter.emit(LDY(Absolute(self.labels[src.name]))) self.emitter.emit(LDY(Absolute(self.labels[src.name])))

View File

@ -202,7 +202,8 @@ class IndexedRef(Ref):
@property @property
def name(self): 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): def is_constant(self):
return False return False

View File

@ -316,7 +316,15 @@ class Parser(object):
self.scanner.expect('forever') self.scanner.expect('forever')
return Instr(opcode='repeat', dest=None, src=src, return Instr(opcode='repeat', dest=None, src=src,
block=block, inverted=inverted) 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 opcode = self.scanner.token
self.scanner.scan() self.scanner.scan()
dest = self.locexpr() dest = self.locexpr()

View File

@ -1462,6 +1462,21 @@ Can `copy` from a `byte` to a `byte`.
| } | }
= ok = 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`. Can `copy` from a `word` to a `word`.
| word source : 0 | word source : 0
@ -1504,9 +1519,7 @@ Can't `copy` from a `word` to a `byte`.
| } | }
? TypeMismatchError ? 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 Note that `^buf` is a constant value, so it by itself does not require `buf` to be
listed in any input/output sets. listed in any input/output sets.
@ -1588,6 +1601,24 @@ Read through a pointer.
| } | }
= ok = 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 ###
Routines are constants. You need not, and in fact cannot, specify a constant 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 | ld y, 0
| copy ^buf, ptr | copy ^buf, ptr
| copy [ptr] + y, foo | copy [ptr] + y, foo
| copy [ptr] + y, a | ld a, [ptr] + y
| } | }
= $080D LDY #$00 = $080D LDY #$00
= $080F LDA #$1F = $080F LDA #$1F