mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-04-06 17:39:38 +00:00
Vector and routine types are constructors with constraints now.
This commit is contained in:
parent
f0b8942aa1
commit
98524e931a
@ -33,7 +33,8 @@ TODO
|
||||
|
||||
For 0.6:
|
||||
|
||||
* declared `inputs` `outputs` `trashes` on the `vector` type.
|
||||
* declared `inputs` `outputs` `trashes` on the `vector` type...
|
||||
* we need to get these 3 things onto the type, and also onto routine types
|
||||
* `goto` (tail call) a routine or a vector.
|
||||
* A more involved demo for the C64 — one that sets up an interrupt.
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR,
|
||||
TYPE_BYTE, TYPE_BYTE_TABLE,
|
||||
RoutineType, VectorType,
|
||||
ConstantRef, LocationRef,
|
||||
REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
@ -224,7 +225,7 @@ def analyze_instr(instr, context, routines):
|
||||
elif opcode == 'copy':
|
||||
if src.type == dest.type:
|
||||
pass
|
||||
elif src.type == TYPE_ROUTINE and dest.type == TYPE_VECTOR:
|
||||
elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType):
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
|
@ -3,7 +3,8 @@
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
ConstantRef, LocationRef,
|
||||
TYPE_BIT, TYPE_ROUTINE, TYPE_VECTOR,
|
||||
TYPE_BIT,
|
||||
RoutineType, VectorType,
|
||||
REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
from sixtypical.emitter import Byte, Label, Offset
|
||||
@ -242,7 +243,8 @@ class Compiler(object):
|
||||
self.compile_block(instr.block)
|
||||
self.emitter.emit(CLI())
|
||||
elif opcode == 'copy':
|
||||
if src.type in (TYPE_ROUTINE, TYPE_VECTOR) and dest.type == TYPE_VECTOR:
|
||||
if isinstance(src.type, (RoutineType, VectorType)) and \
|
||||
isinstance(dest.type, VectorType):
|
||||
src_label = self.labels[src.name]
|
||||
dest_label = self.labels[dest.name]
|
||||
self.emitter.emit(LDA(Absolute(src_label)))
|
||||
|
@ -17,8 +17,43 @@ class Type(object):
|
||||
TYPE_BIT = Type('bit')
|
||||
TYPE_BYTE = Type('byte')
|
||||
TYPE_BYTE_TABLE = Type('byte table')
|
||||
TYPE_ROUTINE = Type('routine')
|
||||
TYPE_VECTOR = Type('vector') # the mem loc contains an address of a routine
|
||||
|
||||
|
||||
class InteractionConstrainedType(Type):
|
||||
"""Used for routines and vectors."""
|
||||
def __init__(self, name, inputs=None, outputs=None, trashes=None):
|
||||
self.name = name
|
||||
self.inputs = inputs or []
|
||||
self.outputs = outputs or []
|
||||
self.trashes = trashes or []
|
||||
|
||||
def __repr__(self):
|
||||
return 'RoutineType(%r, inputs=%r, outputs=%r, trashes=%r)' % (
|
||||
self.name, self.inputs, self.outputs, self.trashes
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, RoutineType) and (
|
||||
other.name == self.name and
|
||||
other.inputs == self.inputs and
|
||||
other.outputs == self.outputs and
|
||||
other.trashes == self.trashes
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name) ^ hash(self.inputs) ^ hash(self.outputs) ^ hash(self.trashes)
|
||||
|
||||
|
||||
class RoutineType(InteractionConstrainedType):
|
||||
"""This memory location contains the code for a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(RoutineType, self).__init__('routine', **kwargs)
|
||||
|
||||
|
||||
class VectorType(InteractionConstrainedType):
|
||||
"""This memory location contains the address of a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(VectorType, self).__init__('vector', **kwargs)
|
||||
|
||||
|
||||
class Ref(object):
|
||||
|
@ -4,7 +4,8 @@ import re
|
||||
|
||||
from sixtypical.ast import Program, Defn, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR,
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE,
|
||||
RoutineType, VectorType,
|
||||
LocationRef, ConstantRef
|
||||
)
|
||||
|
||||
@ -115,7 +116,13 @@ class Parser(object):
|
||||
name = routine.name
|
||||
if name in self.symbols:
|
||||
raise SyntaxError(name)
|
||||
self.symbols[name] = SymEntry(routine, LocationRef(TYPE_ROUTINE, name))
|
||||
ref = LocationRef(
|
||||
RoutineType(inputs=routine.inputs,
|
||||
outputs=routine.outputs,
|
||||
trashes=routine.trashes
|
||||
), name
|
||||
)
|
||||
self.symbols[name] = SymEntry(routine, ref)
|
||||
routines.append(routine)
|
||||
self.scanner.check_type('EOF')
|
||||
return Program(defns=defns, routines=routines)
|
||||
@ -128,13 +135,15 @@ class Parser(object):
|
||||
type = TYPE_BYTE_TABLE
|
||||
else:
|
||||
self.scanner.expect('vector')
|
||||
type = TYPE_VECTOR
|
||||
type = 'vector'
|
||||
self.scanner.check_type('identifier')
|
||||
name = self.scanner.token
|
||||
self.scanner.scan()
|
||||
|
||||
(inputs, outputs, trashes) = self.constraints()
|
||||
if type != TYPE_VECTOR and (inputs or outputs or trashes):
|
||||
if type == 'vector':
|
||||
type = VectorType(inputs=inputs, outputs=outputs, trashes=trashes)
|
||||
elif inputs or outputs or trashes:
|
||||
raise SyntaxError("Cannot apply constraints to non-vector type")
|
||||
|
||||
addr = None
|
||||
@ -260,7 +269,7 @@ class Parser(object):
|
||||
self.scanner.scan()
|
||||
if name not in self.symbols:
|
||||
raise SyntaxError('Undefined routine "%s"' % name)
|
||||
if self.symbols[name].model.type != TYPE_ROUTINE:
|
||||
if not isinstance(self.symbols[name].model.type, RoutineType):
|
||||
raise SyntaxError('Illegal call of non-routine "%s"' % name)
|
||||
return Instr(opcode=opcode, name=name, dest=None, src=None)
|
||||
elif self.scanner.token in ("copy",):
|
||||
|
Loading…
x
Reference in New Issue
Block a user