mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-10 08:30:38 +00:00
Refine the AST classes even more.
This commit is contained in:
parent
2fdba72959
commit
9ad34ed34f
@ -1,6 +1,6 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, BlockOp, IfOp
|
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, If, Repeat, WithInterruptsOff
|
||||||
from sixtypical.model import (
|
from sixtypical.model import (
|
||||||
TYPE_BYTE, TYPE_WORD,
|
TYPE_BYTE, TYPE_WORD,
|
||||||
TableType, BufferType, PointerType, VectorType, RoutineType,
|
TableType, BufferType, PointerType, VectorType, RoutineType,
|
||||||
@ -313,11 +313,13 @@ class Analyzer(object):
|
|||||||
|
|
||||||
def analyze_instr(self, instr, context):
|
def analyze_instr(self, instr, context):
|
||||||
if isinstance(instr, SingleOp):
|
if isinstance(instr, SingleOp):
|
||||||
return self.analyze_single_op(instr, context)
|
self.analyze_single_op(instr, context)
|
||||||
elif isinstance(instr, BlockOp):
|
elif isinstance(instr, If):
|
||||||
return self.analyze_block_op(instr, context)
|
self.analyze_if(instr, context)
|
||||||
elif isinstance(instr, IfOp):
|
elif isinstance(instr, Repeat):
|
||||||
return self.analyze_if_op(instr, context)
|
self.analyze_repeat(instr, context)
|
||||||
|
elif isinstance(instr, WithInterruptsOff):
|
||||||
|
self.analyze_block(instr.block, context)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -547,7 +549,7 @@ class Analyzer(object):
|
|||||||
else:
|
else:
|
||||||
raise NotImplementedError(opcode)
|
raise NotImplementedError(opcode)
|
||||||
|
|
||||||
def analyze_if_op(self, instr, context):
|
def analyze_if(self, instr, context):
|
||||||
incoming_meaningful = set(context.each_meaningful())
|
incoming_meaningful = set(context.each_meaningful())
|
||||||
|
|
||||||
context1 = context.clone()
|
context1 = context.clone()
|
||||||
@ -586,20 +588,15 @@ class Analyzer(object):
|
|||||||
context.set_touched(ref)
|
context.set_touched(ref)
|
||||||
context.set_unmeaningful(ref)
|
context.set_unmeaningful(ref)
|
||||||
|
|
||||||
def analyze_block_op(self, instr, context):
|
def analyze_repeat(self, instr, context):
|
||||||
if instr.opcode == 'repeat':
|
# it will always be executed at least once, so analyze it having
|
||||||
# it will always be executed at least once, so analyze it having
|
# been executed the first time.
|
||||||
# been executed the first time.
|
self.analyze_block(instr.block, context)
|
||||||
self.analyze_block(instr.block, context)
|
if instr.src is not None: # None indicates 'repeat forever'
|
||||||
if instr.src is not None: # None indicates 'repeat forever'
|
context.assert_meaningful(instr.src)
|
||||||
context.assert_meaningful(instr.src)
|
|
||||||
|
|
||||||
# now analyze it having been executed a second time, with the context
|
# now analyze it having been executed a second time, with the context
|
||||||
# of it having already been executed.
|
# of it having already been executed.
|
||||||
self.analyze_block(instr.block, context)
|
self.analyze_block(instr.block, context)
|
||||||
if instr.src is not None:
|
if instr.src is not None:
|
||||||
context.assert_meaningful(instr.src)
|
context.assert_meaningful(instr.src)
|
||||||
elif instr.opcode == 'with-sei':
|
|
||||||
self.analyze_block(instr.block, context)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(opcode)
|
|
||||||
|
@ -72,11 +72,15 @@ class SingleOp(Instr):
|
|||||||
value_attrs = ('opcode', 'dest', 'src', 'location',)
|
value_attrs = ('opcode', 'dest', 'src', 'location',)
|
||||||
|
|
||||||
|
|
||||||
class BlockOp(Instr):
|
class If(Instr):
|
||||||
value_attrs = ('opcode', 'src', 'inverted')
|
value_attrs = ('src', 'inverted')
|
||||||
|
child_attrs = ('block1', 'block2',)
|
||||||
|
|
||||||
|
|
||||||
|
class Repeat(Instr):
|
||||||
|
value_attrs = ('src', 'inverted')
|
||||||
child_attrs = ('block',)
|
child_attrs = ('block',)
|
||||||
|
|
||||||
|
|
||||||
class IfOp(Instr):
|
class WithInterruptsOff(Instr):
|
||||||
value_attrs = ('src', 'inverted')
|
child_attrs = ('block',)
|
||||||
child_attrs = ('block1', 'block2',)
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, BlockOp, IfOp
|
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, If, Repeat, WithInterruptsOff
|
||||||
from sixtypical.model import (
|
from sixtypical.model import (
|
||||||
ConstantRef, LocationRef, IndexedRef, IndirectRef, AddressRef,
|
ConstantRef, LocationRef, IndexedRef, IndirectRef, AddressRef,
|
||||||
TYPE_BIT, TYPE_BYTE, TYPE_WORD,
|
TYPE_BIT, TYPE_BYTE, TYPE_WORD,
|
||||||
@ -144,10 +144,12 @@ class Compiler(object):
|
|||||||
def compile_instr(self, instr):
|
def compile_instr(self, instr):
|
||||||
if isinstance(instr, SingleOp):
|
if isinstance(instr, SingleOp):
|
||||||
return self.compile_single_op(instr)
|
return self.compile_single_op(instr)
|
||||||
elif isinstance(instr, BlockOp):
|
elif isinstance(instr, If):
|
||||||
return self.compile_block_op(instr)
|
return self.compile_if(instr)
|
||||||
elif isinstance(instr, IfOp):
|
elif isinstance(instr, Repeat):
|
||||||
return self.compile_if_op(instr)
|
return self.compile_repeat(instr)
|
||||||
|
elif isinstance(instr, WithInterruptsOff):
|
||||||
|
return self.compile_with_interrupts_off(instr)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -493,7 +495,7 @@ class Compiler(object):
|
|||||||
else:
|
else:
|
||||||
raise NotImplementedError(src.type)
|
raise NotImplementedError(src.type)
|
||||||
|
|
||||||
def compile_if_op(self, instr):
|
def compile_if(self, instr):
|
||||||
cls = {
|
cls = {
|
||||||
False: {
|
False: {
|
||||||
'c': BCC,
|
'c': BCC,
|
||||||
@ -518,29 +520,27 @@ class Compiler(object):
|
|||||||
else:
|
else:
|
||||||
self.emitter.resolve_label(else_label)
|
self.emitter.resolve_label(else_label)
|
||||||
|
|
||||||
def compile_block_op(self, instr):
|
def compile_repeat(self, instr):
|
||||||
if instr.opcode == 'repeat':
|
top_label = self.emitter.make_label()
|
||||||
top_label = self.emitter.make_label()
|
self.compile_block(instr.block)
|
||||||
self.compile_block(instr.block)
|
if instr.src is None: # indicates 'repeat forever'
|
||||||
if instr.src is None: # indicates 'repeat forever'
|
self.emitter.emit(JMP(Absolute(top_label)))
|
||||||
self.emitter.emit(JMP(Absolute(top_label)))
|
|
||||||
else:
|
|
||||||
cls = {
|
|
||||||
False: {
|
|
||||||
'c': BCC,
|
|
||||||
'z': BNE,
|
|
||||||
},
|
|
||||||
True: {
|
|
||||||
'c': BCS,
|
|
||||||
'z': BEQ,
|
|
||||||
},
|
|
||||||
}[instr.inverted].get(instr.src.name)
|
|
||||||
if cls is None:
|
|
||||||
raise UnsupportedOpcodeError(instr)
|
|
||||||
self.emitter.emit(cls(Relative(top_label)))
|
|
||||||
elif instr.opcode == 'with-sei':
|
|
||||||
self.emitter.emit(SEI())
|
|
||||||
self.compile_block(instr.block)
|
|
||||||
self.emitter.emit(CLI())
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(opcode)
|
cls = {
|
||||||
|
False: {
|
||||||
|
'c': BCC,
|
||||||
|
'z': BNE,
|
||||||
|
},
|
||||||
|
True: {
|
||||||
|
'c': BCS,
|
||||||
|
'z': BEQ,
|
||||||
|
},
|
||||||
|
}[instr.inverted].get(instr.src.name)
|
||||||
|
if cls is None:
|
||||||
|
raise UnsupportedOpcodeError(instr)
|
||||||
|
self.emitter.emit(cls(Relative(top_label)))
|
||||||
|
|
||||||
|
def compile_with_interrupts_off(self, instr):
|
||||||
|
self.emitter.emit(SEI())
|
||||||
|
self.compile_block(instr.block)
|
||||||
|
self.emitter.emit(CLI())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
from sixtypical.ast import Program, Defn, Routine, Block, SingleOp, BlockOp, IfOp
|
from sixtypical.ast import Program, Defn, Routine, Block, SingleOp, If, Repeat, WithInterruptsOff
|
||||||
from sixtypical.model import (
|
from sixtypical.model import (
|
||||||
TYPE_BIT, TYPE_BYTE, TYPE_WORD,
|
TYPE_BIT, TYPE_BYTE, TYPE_WORD,
|
||||||
RoutineType, VectorType, TableType, BufferType, PointerType,
|
RoutineType, VectorType, TableType, BufferType, PointerType,
|
||||||
@ -355,7 +355,7 @@ class Parser(object):
|
|||||||
block2 = None
|
block2 = None
|
||||||
if self.scanner.consume('else'):
|
if self.scanner.consume('else'):
|
||||||
block2 = self.block()
|
block2 = self.block()
|
||||||
return IfOp(src=src, block1=block1, block2=block2, inverted=inverted)
|
return If(src=src, block1=block1, block2=block2, inverted=inverted)
|
||||||
elif self.scanner.consume('repeat'):
|
elif self.scanner.consume('repeat'):
|
||||||
inverted = False
|
inverted = False
|
||||||
src = None
|
src = None
|
||||||
@ -366,7 +366,7 @@ class Parser(object):
|
|||||||
src = self.locexpr()
|
src = self.locexpr()
|
||||||
else:
|
else:
|
||||||
self.scanner.expect('forever')
|
self.scanner.expect('forever')
|
||||||
return BlockOp(opcode='repeat', src=src, block=block, inverted=inverted)
|
return Repeat(src=src, block=block, inverted=inverted)
|
||||||
elif self.scanner.token in ("ld",):
|
elif self.scanner.token in ("ld",):
|
||||||
# the same as add, sub, cmp etc below, except supports an indlocexpr for the src
|
# the same as add, sub, cmp etc below, except supports an indlocexpr for the src
|
||||||
opcode = self.scanner.token
|
opcode = self.scanner.token
|
||||||
@ -415,7 +415,7 @@ class Parser(object):
|
|||||||
self.scanner.expect("interrupts")
|
self.scanner.expect("interrupts")
|
||||||
self.scanner.expect("off")
|
self.scanner.expect("off")
|
||||||
block = self.block()
|
block = self.block()
|
||||||
return BlockOp(opcode='with-sei', src=None, block=block)
|
return WithInterruptsOff(block=block)
|
||||||
elif self.scanner.consume("trash"):
|
elif self.scanner.consume("trash"):
|
||||||
dest = self.locexpr()
|
dest = self.locexpr()
|
||||||
return SingleOp(opcode='trash', src=None, dest=dest)
|
return SingleOp(opcode='trash', src=None, dest=dest)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user