got rid of 16-bit register pair variables (AX, AY, XY) they were complicating things too much

This commit is contained in:
Irmen de Jong 2018-11-02 22:06:57 +01:00
parent 54e52a910a
commit d6432df90d
14 changed files with 872 additions and 1411 deletions

View File

@ -148,7 +148,7 @@ expression :
arrayindexed :
(identifier | scoped_identifier | register) arrayspec
(identifier | scoped_identifier ) arrayspec
;
@ -176,7 +176,7 @@ identifier : NAME ;
scoped_identifier : NAME ('.' NAME)+ ;
register : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ;
register : 'A' | 'X' | 'Y' ;
statusregister : 'Pc' | 'Pz' | 'Pn' | 'Pv' ;

View File

@ -355,40 +355,12 @@ byte_assignment_to_bytearray:
; all possible assignments to a UWORD VARIABLE (not array)
uword_assignment_to_registerpair:
AY = 42
AY = 42.w
AY = 42555
AY = X
AY = XY
AY = ub2
AY = mubyte2
AY = string[4]
AY = ubarr1[2]
;AY = uwarr1[X] ; todo via evaluation
;AY = string[X] ; todo via evaluation
;AY = string[b] ; todo via evaluation
;AY = string[ub] ; todo via evaluation
;AY = string[mbyte2] ; todo via evaluation
;AY = string[mubyte2] ; todo via evaluation
;AY = ubarr1[X] ; todo via evaluation
;AY = ubarr1[b] ; todo via evaluation
;AY = ubarr1[ub] ; todo via evaluation
;AY = ubarr1[mbyte2] ; todo via evaluation
;AY = ubarr1[mubyte2] ; todo via evaluation
;AY = uwarr1[X] ; todo via evaluation
;AY = uwarr1[b] ; todo via evaluation
;AY = uwarr1[ub] ; todo via evaluation
;AY = uwarr1[mbyte2] ; todo via evaluation
;AY = uwarr1[mubyte2] ; todo via evaluation
uword_assignment_to_uwordvar:
uw = 42
uw = 42.w
uw = 42555
uw = X
uw = XY
uw = ub2
uw = uw2
uw = mubyte2
@ -418,7 +390,6 @@ uword_assignment_to_uwordmem:
muword = 42.w
muword = 42555
muword = X
muword = XY
muword = ub2
muword = uw2
muword = mubyte2
@ -448,7 +419,6 @@ uword_assignment_to_uwordarray:
uwarr1[2] = 42.w
uwarr1[2] = 42555
uwarr1[2] = X
uwarr1[2] = XY
uwarr1[2] = ub2
uwarr1[2] = uw2
uwarr1[2] = mubyte2
@ -461,7 +431,6 @@ uword_assignment_to_uwordarray:
uwarr1[Y] = 42.w
uwarr1[Y] = 42555
uwarr1[Y] = X
uwarr1[Y] = XY
uwarr1[Y] = ub2
uwarr1[Y] = uw2
uwarr1[Y] = mubyte2
@ -474,7 +443,6 @@ uword_assignment_to_uwordarray:
uwarr1[b] = 42.w
uwarr1[b] = 42555
uwarr1[b] = X
uwarr1[b] = XY
uwarr1[b] = ub2
uwarr1[b] = uw2
uwarr1[b] = mubyte2
@ -487,7 +455,6 @@ uword_assignment_to_uwordarray:
uwarr1[ub] = 42.w
uwarr1[ub] = 42555
uwarr1[ub] = X
uwarr1[ub] = XY
uwarr1[ub] = ub2
uwarr1[ub] = uw2
uwarr1[ub] = mubyte2
@ -500,7 +467,6 @@ uword_assignment_to_uwordarray:
uwarr1[mbyte2] = 42.w
uwarr1[mbyte2] = 42555
uwarr1[mbyte2] = X
uwarr1[mbyte2] = XY
uwarr1[mbyte2] = ub2
uwarr1[mbyte2] = uw2
uwarr1[mbyte2] = mubyte2
@ -513,7 +479,6 @@ uword_assignment_to_uwordarray:
uwarr1[mubyte2] = 42.w
uwarr1[mubyte2] = 42555
uwarr1[mubyte2] = X
uwarr1[mubyte2] = XY
uwarr1[mubyte2] = ub2
uwarr1[mubyte2] = uw2
uwarr1[mubyte2] = mubyte2
@ -622,7 +587,6 @@ float_assignment_to_floatvar:
fl1 = 34555.w
fl1 = 3.33e22
fl1 = X
fl1 = AY
fl1 = b2
fl1 = ub2
fl1 = w2
@ -667,7 +631,6 @@ float_assignment_to_floatmem:
mfloat = 34555.w
mfloat = 3.33e22
mfloat = X
mfloat = AY
mfloat = b2
mfloat = ub2
mfloat = w2

View File

@ -36,10 +36,7 @@ enum class DataType {
enum class Register {
A,
X,
Y,
AX,
AY,
XY
Y
}
enum class Statusflag {
@ -684,10 +681,7 @@ data class AssignTarget(val register: Register?,
fun determineDatatype(namespace: INameScope, heap: HeapValues, stmt: IStatement): DataType? {
if(register!=null)
return when(register){
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
return DataType.UBYTE
if(identifier!=null) {
val symbol = namespace.lookup(identifier.nameInSource, stmt) ?: return null
@ -875,7 +869,6 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
}
class ArrayIndexedExpression(val identifier: IdentifierReference?,
val register: Register?,
var arrayspec: ArraySpec,
override val position: Position) : IExpression {
override lateinit var parent: Node
@ -891,8 +884,6 @@ class ArrayIndexedExpression(val identifier: IdentifierReference?,
override fun referencesIdentifier(name: String) = identifier?.referencesIdentifier(name) ?: false
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? {
if (register != null)
return DataType.UBYTE
val target = identifier?.targetStatement(namespace)
if (target is VarDecl) {
return when (target.datatype) {
@ -910,7 +901,7 @@ class ArrayIndexedExpression(val identifier: IdentifierReference?,
}
override fun toString(): String {
return "ArrayIndexed(ident=$identifier, reg=$register, arrayspec=$arrayspec; pos=$position)"
return "ArrayIndexed(ident=$identifier, arrayspec=$arrayspec; pos=$position)"
}
}
@ -1230,12 +1221,7 @@ class RegisterExpr(val register: Register, override val position: Position) : IE
return "RegisterExpr(register=$register, pos=$position)"
}
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? {
return when(register){
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
}
override fun resultingDatatype(namespace: INameScope, heap: HeapValues) = DataType.UBYTE
}
@ -1957,7 +1943,6 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
private fun prog8Parser.ArrayindexedContext.toAst(): ArrayIndexedExpression {
return ArrayIndexedExpression(identifier()?.toAst() ?: scoped_identifier()?.toAst(),
register()?.toAst(),
arrayspec().toAst(),
toPosition())
}

View File

@ -119,17 +119,8 @@ class AstChecker(private val namespace: INameScope,
if (forLoop.loopRegister != null) {
printWarning("using a register as loop variable is risky (it could get clobbered in the body)", forLoop.position)
// loop register
when (forLoop.loopRegister) {
Register.A, Register.X, Register.Y -> {
if (iterableDt != DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt !in StringDatatypes)
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
}
Register.AX, Register.AY, Register.XY -> {
if (iterableDt != DataType.UWORD && iterableDt != DataType.UBYTE && iterableDt !in StringDatatypes &&
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW)
checkResult.add(ExpressionError("register pair can only loop over bytes or words", forLoop.position))
}
}
if (iterableDt != DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt !in StringDatatypes)
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
} else {
// loop variable
val loopvar = forLoop.loopVar!!.targetStatement(namespace) as? VarDecl
@ -239,29 +230,16 @@ class AstChecker(private val namespace: INameScope,
if(subroutine.asmReturnvaluesRegisters.size != subroutine.returntypes.size)
err("number of return registers is not the same as number of return values")
for(param in subroutine.parameters.zip(subroutine.asmParameterRegisters)) {
if(param.second.register==Register.A || param.second.register==Register.X ||
param.second.register==Register.Y || param.second.statusflag!=null) {
if(param.second.register!=null || param.second.statusflag!=null) {
if(param.first.type!=DataType.UBYTE)
err("parameter '${param.first.name}' should be ubyte")
}
if(param.second.register==Register.AX || param.second.register==Register.AY ||
param.second.register==Register.XY) {
if(param.first.type!=DataType.UWORD && param.first.type !in StringDatatypes && param.first.type !in ArrayDatatypes)
err("parameter '${param.first.name}' should be uword/str/arrayspec")
}
}
for(ret in subroutine.returntypes.withIndex().zip(subroutine.asmReturnvaluesRegisters)) {
if(ret.second.register==Register.A || ret.second.register==Register.X ||
ret.second.register==Register.Y || ret.second.statusflag!=null) {
if(ret.second.register!=null || ret.second.statusflag!=null) {
if(ret.first.value!=DataType.UBYTE)
err("return value #${ret.first.index+1} should be ubyte")
}
if(ret.second.register==Register.AX || ret.second.register==Register.AY ||
ret.second.register==Register.XY) {
if(ret.first.value!=DataType.UWORD && ret.first.value != DataType.UBYTE &&
ret.first.value !in StringDatatypes && ret.first.value !in ArrayDatatypes)
err("return value #${ret.first.index+1} should be uword/ubyte/string/arrayspec")
}
}
val regCounts = mutableMapOf<Register, Int>().withDefault { 0 }
@ -270,23 +248,8 @@ class AstChecker(private val namespace: INameScope,
regCounts.clear()
statusflagCounts.clear()
for(p in from) {
if (p.register != null) {
when(p.register) {
Register.A, Register.X, Register.Y -> regCounts[p.register] = regCounts.getValue(p.register) + 1
Register.AX -> {
regCounts[Register.A] = regCounts.getValue(Register.A) + 1
regCounts[Register.X] = regCounts.getValue(Register.X) + 1
}
Register.AY -> {
regCounts[Register.A] = regCounts.getValue(Register.A) + 1
regCounts[Register.Y] = regCounts.getValue(Register.Y) + 1
}
Register.XY -> {
regCounts[Register.X] = regCounts.getValue(Register.X) + 1
regCounts[Register.Y] = regCounts.getValue(Register.Y) + 1
}
}
}
if (p.register != null)
regCounts[p.register] = regCounts.getValue(p.register) + 1
else if(p.statusflag!=null)
statusflagCounts[p.statusflag] = statusflagCounts.getValue(p.statusflag) + 1
}
@ -330,12 +293,6 @@ class AstChecker(private val namespace: INameScope,
return super.process(assignment)
}
}
} else if(assignment.target.arrayindexed!=null) {
if(assignment.target.arrayindexed!!.register!=null) {
val value = assignment.value
if (value is ArrayIndexedExpression && value.register in setOf(Register.AX, Register.AY, Register.XY))
checkResult.add(SyntaxError("reading AND writing from registerpair arrays not supported due to register overlap", assignment.position))
}
}
// it is not possible to assign a new arrayspec to something.
@ -696,56 +653,43 @@ class AstChecker(private val namespace: INameScope,
}
}
} else if(postIncrDecr.target.arrayindexed!=null) {
val indexedRegister = postIncrDecr.target.arrayindexed?.register
if(indexedRegister!=null) {
if(indexedRegister==Register.A || indexedRegister==Register.X || indexedRegister==Register.Y)
checkResult.add(SyntaxError("indexing on registers requires register pair variable", postIncrDecr.position))
} else {
val target = postIncrDecr.target.arrayindexed?.identifier?.targetStatement(namespace)
if(target==null) {
checkResult.add(SyntaxError("undefined symbol", postIncrDecr.position))
}
else {
val dt = (target as VarDecl).datatype
if(dt !in NumericDatatypes)
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
}
val target = postIncrDecr.target.arrayindexed?.identifier?.targetStatement(namespace)
if(target==null) {
checkResult.add(SyntaxError("undefined symbol", postIncrDecr.position))
}
else {
val dt = (target as VarDecl).datatype
if(dt !in NumericDatatypes)
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
}
}
return super.process(postIncrDecr)
}
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
val reg=arrayIndexedExpression.register
if(reg==null) {
val target = arrayIndexedExpression.identifier!!.targetStatement(namespace)
if(target is VarDecl) {
if(target.datatype !in IterableDatatypes)
checkResult.add(SyntaxError("indexing requires an iterable variable", arrayIndexedExpression.position))
val arraysize = target.arrayspec?.size()
if(arraysize!=null) {
// check out of bounds
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=arraysize))
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
} else if(target.datatype in StringDatatypes) {
// check string lengths
val heapId = (target.value as LiteralValue).heapId!!
val stringLen = heap.get(heapId).str!!.length
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=stringLen))
checkResult.add(ExpressionError("index out of bounds", arrayIndexedExpression.arrayspec.position))
}
} else
checkResult.add(SyntaxError("indexing requires a variable to act upon", arrayIndexedExpression.position))
val target = arrayIndexedExpression.identifier!!.targetStatement(namespace)
if(target is VarDecl) {
if(target.datatype !in IterableDatatypes)
checkResult.add(SyntaxError("indexing requires an iterable variable", arrayIndexedExpression.position))
val arraysize = target.arrayspec?.size()
if(arraysize!=null) {
// check out of bounds
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=arraysize))
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
} else if(target.datatype in StringDatatypes) {
// check string lengths
val heapId = (target.value as LiteralValue).heapId!!
val stringLen = heap.get(heapId).str!!.length
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=stringLen))
checkResult.add(ExpressionError("index out of bounds", arrayIndexedExpression.arrayspec.position))
}
} else
checkResult.add(SyntaxError("indexing on register variable is not possible, use a regular array variable instead", arrayIndexedExpression.position))
checkResult.add(SyntaxError("indexing requires a variable to act upon", arrayIndexedExpression.position))
// check index value 0..255
val regx = (arrayIndexedExpression.arrayspec.x as? RegisterExpr)?.register
if((regx in setOf(Register.AX, Register.AY, Register.XY))) {
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))
}
val dtx = arrayIndexedExpression.arrayspec.x.resultingDatatype(namespace, heap)
if(dtx!=DataType.UBYTE && dtx!=DataType.BYTE)
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))

View File

@ -125,8 +125,8 @@ class AstIdentifiersChecker : IAstProcessor {
if(forLoop.loopRegister!=null) {
if(forLoop.decltype!=null)
checkResult.add(SyntaxError("register loop variables cannot be explicitly declared with a datatype", forLoop.position))
if(forLoop.loopRegister == Register.X || forLoop.loopRegister==Register.XY || forLoop.loopRegister==Register.AX)
printWarning("possible problem writing to the X register, because it's used as an internal pointer", forLoop.position)
if(forLoop.loopRegister == Register.X)
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
} else if(forLoop.loopVar!=null) {
val varName = forLoop.loopVar.nameInSource.last()
when (forLoop.decltype) {
@ -147,8 +147,8 @@ class AstIdentifiersChecker : IAstProcessor {
}
override fun process(assignTarget: AssignTarget): AssignTarget {
if(assignTarget.register==Register.X || assignTarget.register==Register.AX || assignTarget.register==Register.XY)
printWarning("possible problem writing to the X register, because it's used as an internal pointer", assignTarget.position)
if(assignTarget.register==Register.X)
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", assignTarget.position)
return super.process(assignTarget)
}
}

View File

@ -292,20 +292,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun opcodePushvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.PUSH_VAR_BYTE
Register.AX, Register.AY, Register.XY -> Opcode.PUSH_VAR_WORD
}
}
private fun opcodePopvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.POP_VAR_BYTE
Register.AX, Register.AY, Register.XY -> Opcode.POP_VAR_WORD
}
}
private fun opcodeReadindexedvar(dt: DataType): Opcode {
return when (dt) {
DataType.ARRAY_UB, DataType.ARRAY_B -> Opcode.READ_INDEXED_VAR_BYTE
@ -361,20 +347,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun opcodeDecvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.DEC_VAR_UB
Register.AX, Register.AY, Register.XY -> Opcode.DEC_VAR_UW
}
}
private fun opcodeIncvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.INC_VAR_UB
Register.AX, Register.AY, Register.XY -> Opcode.INC_VAR_UW
}
}
private fun opcodeDecvar(dt: DataType): Opcode {
return when(dt) {
DataType.UBYTE -> Opcode.DEC_VAR_UB
@ -577,8 +549,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translate(expr: IExpression) {
when(expr) {
is RegisterExpr -> {
val opcode = opcodePushvar(expr.register)
prog.instr(opcode, callLabel = expr.register.toString())
prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = expr.register.toString())
}
is PrefixExpression -> {
translate(expr.expression)
@ -1040,30 +1011,12 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
private fun translate(arrayindexed: ArrayIndexedExpression, write: Boolean) {
val variable = arrayindexed.identifier?.targetStatement(namespace) as? VarDecl
val variableName =
if(arrayindexed.register!=null) {
val reg=arrayindexed.register
if(reg==Register.A || reg==Register.X || reg==Register.Y)
throw CompilerException("requires register pair")
reg.toString()
} else {
variable!!.scopedname
}
val variable = arrayindexed.identifier?.targetStatement(namespace) as VarDecl
translate(arrayindexed.arrayspec.x)
if(variable!=null) {
if (write)
prog.instr(opcodeWriteindexedvar(variable.datatype), callLabel = variableName)
else
prog.instr(opcodeReadindexedvar(variable.datatype), callLabel = variableName)
} else {
// register indexed
if (write)
prog.instr(opcodeWriteindexedvar(DataType.ARRAY_UB), callLabel = arrayindexed.register!!.toString())
else
prog.instr(opcodeReadindexedvar(DataType.ARRAY_UB), callLabel = arrayindexed.register!!.toString())
}
if (write)
prog.instr(opcodeWriteindexedvar(variable.datatype), callLabel = variable.scopedname)
else
prog.instr(opcodeReadindexedvar(variable.datatype), callLabel = variable.scopedname)
}
private fun createSyscall(funcname: String) {
@ -1101,8 +1054,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.line(stmt.position)
when {
stmt.target.register!=null -> when(stmt.operator) {
"++" -> prog.instr(opcodeIncvar(stmt.target.register!!), callLabel = stmt.target.register.toString())
"--" -> prog.instr(opcodeDecvar(stmt.target.register!!), callLabel = stmt.target.register.toString())
"++" -> prog.instr(Opcode.INC_VAR_UB, callLabel = stmt.target.register.toString())
"--" -> prog.instr(Opcode.DEC_VAR_UB, callLabel = stmt.target.register.toString())
}
stmt.target.identifier!=null -> {
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
@ -1181,10 +1134,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
else -> throw CompilerException("invalid assignment target type ${target::class}")
}
}
stmt.target.register!=null -> {
val opcode= opcodePushvar(stmt.target.register!!)
prog.instr(opcode, callLabel = stmt.target.register.toString())
}
stmt.target.register!=null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = stmt.target.register.toString())
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, false)
}
@ -1215,10 +1165,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
} else throw CompilerException("invalid assignment target type ${target::class}")
}
assignTarget.register != null -> {
val opcode = opcodePopvar(assignTarget.register)
prog.instr(opcode, callLabel = assignTarget.register.toString())
}
assignTarget.register != null -> prog.instr(Opcode.POP_VAR_BYTE, callLabel = assignTarget.register.toString())
assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, true) // write value to it
}
}
@ -1326,10 +1273,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
if(loop.loopRegister!=null) {
val reg = loop.loopRegister
loopVarName = reg.toString()
loopVarDt = when (reg) {
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
loopVarDt = DataType.UBYTE
} else {
val loopvar = (loop.loopVar!!.targetStatement(namespace) as VarDecl)
loopVarName = loopvar.scopedname
@ -1395,7 +1339,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
else if(loopvarDt==DataType.FLOAT && iterableValue.type != DataType.ARRAY_F)
throw CompilerException("loop variable type doesn't match iterableValue type")
val numElements: Int
val indexVar: String
when(iterableValue.type) {
DataType.UBYTE, DataType.BYTE,
DataType.UWORD, DataType.WORD,
@ -1405,23 +1348,21 @@ private class StatementTranslator(private val prog: IntermediateProgram,
DataType.STR_S,
DataType.STR_PS -> {
numElements = iterableValue.strvalue?.length ?: heap.get(iterableValue.heapId!!).str!!.length
indexVar = if(numElements>255) "XY" else "X"
if(numElements>255) throw CompilerException("string length > 255")
}
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W -> {
numElements = iterableValue.arrayvalue?.size ?: heap.get(iterableValue.heapId!!).arraysize
indexVar = if(numElements>255) "XY" else "X"
if(numElements>255) throw CompilerException("string length > 255")
}
DataType.ARRAY_F -> {
numElements = iterableValue.arrayvalue?.size ?: heap.get(iterableValue.heapId!!).arraysize
indexVar = if(numElements>255) "XY" else "X"
if(numElements>255) throw CompilerException("string length > 255")
}
}
if(indexVar=="X" && loop.loopRegister!=null && loop.loopRegister in setOf(Register.X, Register.AX, Register.XY))
if(loop.loopRegister!=null && loop.loopRegister==Register.X)
throw CompilerException("loopVar cannot use X register because it is needed as internal index")
if(indexVar=="XY" && loop.loopRegister!=null && loop.loopRegister in setOf(Register.X, Register.AX, Register.Y, Register.AY, Register.XY))
throw CompilerException("loopVar cannot use X and Y registers because they are needed as internal index")
/**
* indexVar = 0
@ -1446,23 +1387,23 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val zero = Value(if (numElements <= 255) DataType.UBYTE else DataType.UWORD, 0)
prog.instr(opcodePush(zero.type), zero)
prog.instr(opcodePopvar(zero.type), callLabel = indexVar)
prog.instr(opcodePopvar(zero.type), callLabel = "X")
prog.label(loopLabel)
val assignTarget = if(loop.loopRegister!=null)
AssignTarget(loop.loopRegister, null, null, loop.position)
else
AssignTarget(null, loop.loopVar!!.copy(), null, loop.position)
val arrayspec = ArraySpec(RegisterExpr(Register.valueOf(indexVar), loop.position), loop.position)
val assignLv = Assignment(assignTarget, null, ArrayIndexedExpression((loop.iterable as IdentifierReference).copy(), null, arrayspec, loop.position), loop.position)
val arrayspec = ArraySpec(RegisterExpr(Register.X, loop.position), loop.position)
val assignLv = Assignment(assignTarget, null, ArrayIndexedExpression((loop.iterable as IdentifierReference).copy(), arrayspec, loop.position), loop.position)
assignLv.linkParents(loop.body)
translate(assignLv)
translate(loop.body)
prog.label(continueLabel)
prog.instr(opcodeIncvar(zero.type), callLabel = indexVar)
prog.instr(opcodeIncvar(zero.type), callLabel = "X")
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value.
prog.instr(opcodePush(zero.type), Value(zero.type, numElements))
prog.instr(opcodePushvar(zero.type), callLabel = indexVar)
prog.instr(opcodePushvar(zero.type), callLabel = "X")
prog.instr(opcodeSub(zero.type))
prog.instr(Opcode.TEST)
prog.instr(Opcode.BNZ, callLabel = loopLabel)
@ -1638,7 +1579,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
postIncr.linkParents(range.parent)
translate(postIncr)
if(lvTarget.register!=null)
prog.instr(opcodePushvar(lvTarget.register), callLabel =lvTarget.register.toString())
prog.instr(Opcode.PUSH_VAR_BYTE, callLabel =lvTarget.register.toString())
else {
val opcode = opcodePushvar(targetStatement!!.datatype)
prog.instr(opcode, callLabel = targetStatement.scopedname)

View File

@ -444,12 +444,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// }
// }
// Opcode.PUSH_VAR_WORD -> {
// when (ins.callLabel) {
// "AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
// "XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
// "AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
// else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
// }
// " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
// }
// Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
// Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
@ -511,12 +506,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.POP_VAR_WORD -> {
when (ins.callLabel) {
"AX" -> throw CompilerException("makes no sense to pop X, it's used as a stack pointer itself")
"XY" -> throw CompilerException("makes no sense to pop X, it's used as a stack pointer itself")
"AY" -> " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x"
else -> " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x | sta ${ins.callLabel} | sty ${ins.callLabel}+1"
}
" inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x | sta ${ins.callLabel} | sty ${ins.callLabel}+1"
}
Opcode.POP_VAR_FLOAT -> {
" lda #<${ins.callLabel} | ldy #>${ins.callLabel} | jsr prog8_lib.pop_var_float"
@ -531,12 +521,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.INC_VAR_UW -> {
when (ins.callLabel) {
"AX" -> " clc | adc #1 | bne + | inx |+"
"AY" -> " clc | adc #1 | bne + | iny |+"
"XY" -> " inx | bne + | iny |+"
else -> " inc ${ins.callLabel} | bne + | inc ${ins.callLabel}+1 |+"
}
" inc ${ins.callLabel} | bne + | inc ${ins.callLabel}+1 |+"
}
Opcode.INC_VAR_F -> {
"""
@ -554,12 +539,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.DEC_VAR_UW -> {
when (ins.callLabel) {
"AX" -> " cmp #0 | bne + | dex |+ | sec | sbc #1"
"AY" -> " cmp #0 | bne + | dey |+ | sec | sbc #1"
"XY" -> " txa | bne + | dey |+ | dex"
else -> " lda ${ins.callLabel} | bne + | dec ${ins.callLabel}+1 |+ | dec ${ins.callLabel}"
}
" lda ${ins.callLabel} | bne + | dec ${ins.callLabel}+1 |+ | dec ${ins.callLabel}"
}
Opcode.DEC_VAR_F -> {
"""
@ -798,7 +778,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
loadX = " tax |"
loadXWord = " asl a | tax |"
}
"AX", "AY", "XY" -> throw AssemblyError("cannot index with word/registerpair")
else -> {
// the indexvar is a real variable, not a register
loadX = " ldx $indexVar |"
@ -862,20 +841,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.SHL_WORD -> {
when(variable) {
"AX" -> AsmFragment(" asl a | tay | txa | rol a | tax | tya ", 10)
"AY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1.toHex()} | asl a | rol ${C64Zeropage.SCRATCH_B1.toHex()} | ldy ${C64Zeropage.SCRATCH_B1.toHex()} ", 10)
"XY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1.toHex()} | txa | asl a | rol ${C64Zeropage.SCRATCH_B1.toHex()} | ldy ${C64Zeropage.SCRATCH_B1.toHex()} | tax", 10)
else -> AsmFragment(" asl $variable | rol $variable+1", 10)
}
AsmFragment(" asl $variable | rol $variable+1", 10)
}
Opcode.SHR_WORD -> {
when(variable) {
"AX" -> AsmFragment(" tay | txa | lsr a | tax | tya | ror a", 10)
"AY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1.toHex()} | lsr ${C64Zeropage.SCRATCH_B1.toHex()} | ror a | ldy ${C64Zeropage.SCRATCH_B1.toHex()} ", 10)
"XY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1.toHex()} | lsr ${C64Zeropage.SCRATCH_B1.toHex()} | txa | ror a | tax | ldy ${C64Zeropage.SCRATCH_B1.toHex()}", 10)
else -> AsmFragment(" lsr $variable+1 | ror $variable", 10)
}
AsmFragment(" lsr $variable+1 | ror $variable", 10)
}
Opcode.ROL_BYTE -> {
when (variable) {
@ -894,20 +863,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.ROL_WORD -> {
when(variable) {
"AX" -> AsmFragment(" rol a | tay | txa | rol a | tax | tya ", 10)
"AY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | rol a | rol ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} ", 10)
"XY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | txa | rol a | rol ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} | tax", 10)
else -> AsmFragment(" rol $variable | rol $variable+1", 10)
}
AsmFragment(" rol $variable | rol $variable+1", 10)
}
Opcode.ROR_WORD -> {
when(variable) {
"AX" -> AsmFragment(" tay | txa | ror a | tax | tya | ror a", 10)
"AY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | ror ${C64Zeropage.SCRATCH_B1} | ror a | ldy ${C64Zeropage.SCRATCH_B1} ", 10)
"XY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | ror ${C64Zeropage.SCRATCH_B1} | txa | ror a | tax | ldy ${C64Zeropage.SCRATCH_B1}", 10)
else -> AsmFragment(" ror $variable+1 | ror $variable", 10)
}
AsmFragment(" ror $variable+1 | ror $variable", 10)
}
Opcode.ROL2_BYTE -> { // 8-bit rol
when (variable) {
@ -926,21 +885,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
Opcode.ROL2_WORD -> {
when(variable) {
"AX" -> AsmFragment(" cmp #\$80 | rol a | tay | txa | rol a | tax | tya", 10)
"AY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | cmp #\$80 | rol a | rol ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} ", 10)
"XY" -> AsmFragment(" sty ${C64Zeropage.SCRATCH_B1} | txa | cmp #\$80 | rol a | rol ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} | tax", 10)
else -> AsmFragment(" lda $variable | cmp #\$80 | rol $variable | rol $variable+1", 10)
}
AsmFragment(" lda $variable | cmp #\$80 | rol $variable | rol $variable+1", 10)
}
Opcode.ROR2_WORD -> {
// todo: ror2_word is very slow; it requires a library routine
when(variable) {
"AX" -> AsmFragment(" sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | lda ${C64Zeropage.SCRATCH_W1} | ldx ${C64Zeropage.SCRATCH_W1+1}", 20)
"AY" -> AsmFragment(" sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | lda ${C64Zeropage.SCRATCH_W1} | ldy ${C64Zeropage.SCRATCH_W1+1}", 20)
"XY" -> AsmFragment(" stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | ldx ${C64Zeropage.SCRATCH_W1} | ldy ${C64Zeropage.SCRATCH_W1+1}", 20)
else -> AsmFragment(" lda $variable | sta ${C64Zeropage.SCRATCH_W1} | lda $variable+1 | sta ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | lda ${C64Zeropage.SCRATCH_W1} | sta $variable | lda ${C64Zeropage.SCRATCH_W1+1} | sta $variable+1", 30)
}
AsmFragment(" lda $variable | sta ${C64Zeropage.SCRATCH_W1} | lda $variable+1 | sta ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | lda ${C64Zeropage.SCRATCH_W1} | sta $variable | lda ${C64Zeropage.SCRATCH_W1+1} | sta $variable+1", 30)
}
// Opcode.SYSCALL -> {
// TODO("optimize SYSCALL $ins in-place on variable $variable")
@ -1286,133 +1235,55 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// var = wordvalue
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD)) { segment ->
val number = segment[0].arg!!.integerValue().toHex()
when (segment[1].callLabel) {
"AX" -> " lda #<$number | ldx #>$number"
"AY" -> " lda #<$number | ldy #>$number"
"XY" -> " ldx #<$number | ldy #>$number"
else ->
"""
lda #<${segment[0].arg!!.integerValue().toHex()}
sta ${segment[1].callLabel}
lda #>${segment[0].arg!!.integerValue().toHex()}
sta ${segment[1].callLabel}+1
"""
}
"""
lda #<$number
sta ${segment[1].callLabel}
lda #>$number
sta ${segment[1].callLabel}+1
"""
},
// var = ubytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
when(segment[0].callLabel) {
"A" -> when(segment[2].callLabel) {
"AX" -> " ldx #0"
"AY" -> " ldy #0"
"XY" -> " tax | ldy #0"
else -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
"X" -> when(segment[2].callLabel) {
"AX" -> " txa | ldx #0"
"AY" -> " txa | ldy #0"
"XY" -> " ldy #0"
else -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
"Y" -> when(segment[2].callLabel) {
"AX" -> " tya | ldx #0"
"AY" -> " tya | ldy #0"
"XY" -> " tya | tax | ldy #0"
else -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
else ->
when(segment[2].callLabel) {
"AX" -> " lda ${segment[0].callLabel} | ldx #0"
"AY" -> " lda ${segment[0].callLabel} | ldy #0"
"XY" -> " ldx ${segment[0].callLabel} | ldy #0"
else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
"A" -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
"X" -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
"Y" -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
},
// var = other var
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_VAR_WORD)) { segment ->
when(segment[1].callLabel) {
"AX" ->
when(segment[0].callLabel) {
"AX" -> null
"AY" -> " stx ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1}"
"XY" -> " stx ${C64Zeropage.SCRATCH_B1} | tax | ldy ${C64Zeropage.SCRATCH_B1}"
else -> " lda ${segment[0].callLabel} | ldx ${segment[0].callLabel}+1"
}
"AY" ->
when(segment[0].callLabel) {
"AX" -> " sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}"
"AY" -> null
"XY" -> " tax"
else -> " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1"
}
"XY" ->
when(segment[0].callLabel) {
"AX" -> " txa | sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}"
"AY" -> " txa"
"XY" -> null
else -> " ldx ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1"
}
else ->
when(segment[0].callLabel) {
"AX" -> " sta ${segment[1].callLabel} | stx ${segment[1].callLabel}+1"
"AY" -> " sta ${segment[1].callLabel} | sty ${segment[1].callLabel}+1"
"XY" -> " stx ${segment[1].callLabel} | sty ${segment[1].callLabel}+1"
else ->
"""
lda ${segment[0].callLabel}
ldy ${segment[0].callLabel}+1
sta ${segment[1].callLabel}
sty ${segment[1].callLabel}+1
"""
}
}
"""
lda ${segment[0].callLabel}
ldy ${segment[0].callLabel}+1
sta ${segment[1].callLabel}
sty ${segment[1].callLabel}+1
"""
},
// var = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
when(segment[2].callLabel) {
"AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx #0"
"AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy #0"
"XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy #0"
else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
}
" lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
},
// var = mem (u)word
AsmPattern(
listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD),
listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment ->
when(segment[1].callLabel) {
"AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx ${(segment[0].arg!!.integerValue()+1).toHex()}"
"AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
"XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
else ->
"""
lda ${segment[0].arg!!.integerValue().toHex()}
sta ${segment[1].callLabel}
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
sta ${segment[1].callLabel}+1
"""
}
"""
lda ${segment[0].arg!!.integerValue().toHex()}
sta ${segment[1].callLabel}
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
sta ${segment[1].callLabel}+1
"""
},
// var = ubytearray[index_byte]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
val index = segment[0].arg!!.integerValue().toHex()
when(segment[3].callLabel) {
"AX" -> " lda ${segment[1].callLabel}+$index | ldx #0"
"AY" -> " lda ${segment[1].callLabel}+$index | ldy #0"
"XY" -> " ldx ${segment[1].callLabel}+$index | ldy #0"
else -> " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1"
}
" lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1"
},
// var = (u)wordarray[index_byte]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment ->
val index = segment[0].arg!!.integerValue()*2
when(segment[2].callLabel) {
"AX" -> " lda ${segment[1].callLabel}+$index | ldx ${segment[1].callLabel}+${index+1}"
"AY" -> " lda ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}"
"XY" -> " ldx ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}"
else -> " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index+1} | sta ${segment[2].callLabel}+1"
}
" lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index+1} | sta ${segment[2].callLabel}+1"
},
// mem = (u)word value
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_WORD)) { segment ->
@ -1443,12 +1314,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// mem uword = uword var
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_WORD)) { segment ->
when(segment[0].callLabel) {
"AX" -> " sta ${segment[1].arg!!.integerValue().toHex()} | stx ${(segment[1].arg!!.integerValue()+1).toHex()}"
"AY" -> " sta ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}"
"XY" -> " stx ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}"
else -> " lda ${segment[0].callLabel} || sta ${segment[1].arg!!.integerValue().toHex()} | lda ${segment[0].callLabel}+1 | sta ${(segment[1].arg!!.integerValue()+1).toHex()}"
}
" lda ${segment[0].callLabel} || sta ${segment[1].arg!!.integerValue().toHex()} | lda ${segment[0].callLabel}+1 | sta ${(segment[1].arg!!.integerValue()+1).toHex()}"
},
// mem (u)word = mem (u)word
AsmPattern(
@ -1464,96 +1330,24 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// mem uword = ubytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
val index = segment[0].arg!!.integerValue()
when(segment[1].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
lda #0
sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
lda #0
sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
lda #0
sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
else ->
"""
lda ${segment[1].callLabel}+$index
sta ${segment[3].arg!!.integerValue().toHex()}
lda #0
sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
}
"""
lda ${segment[1].callLabel}+$index
sta ${segment[3].arg!!.integerValue().toHex()}
lda #0
sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
},
// mem uword = bytearray[index] (sign extended)
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
val index = segment[0].arg!!.integerValue()
when(segment[1].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
ora #${'$'}7f
bmi +
lda #0
+ sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
ora #${'$'}7f
bmi +
lda #0
+ sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #$index
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${segment[3].arg!!.integerValue().toHex()}
ora #${'$'}7f
bmi +
lda #0
+ sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
else ->
"""
lda ${segment[1].callLabel}+$index
sta ${segment[3].arg!!.integerValue().toHex()}
ora #${'$'}7f
bmi +
lda #0
+ sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
}
"""
lda ${segment[1].callLabel}+$index
sta ${segment[3].arg!!.integerValue().toHex()}
ora #${'$'}7f
bmi +
lda #0
+ sta ${(segment[3].arg!!.integerValue()+1).toHex()}
"""
},
// mem uword = (u)wordarray[indexvalue]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment ->
@ -1658,12 +1452,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// uwordarray[index] = (u)wordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val index = segment[1].arg!!.integerValue()*2
when(segment[0].callLabel) {
"AX" -> " sta ${segment[2].callLabel}+$index | stx ${segment[2].callLabel}+${index+1}"
"AY" -> " sta ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+${index+1}"
"XY" -> " stx ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+${index+1}"
else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+${index+1}"
}
" lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+${index+1}"
},
// uwordarray[index] = mem uword
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
@ -1739,42 +1528,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// floatvar = uwordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
when (segment[0].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.uw2float
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.uw2float
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.uw2float
"""
else ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.uw2float
"""
}
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.uw2float
"""
},
// floatvar = bytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
@ -1794,42 +1556,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// floatvar = wordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
when (segment[0].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.w2float
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.w2float
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.w2float
"""
else ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.w2float
"""
}
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].callLabel}
ldy #>${segment[2].callLabel}
jsr prog8_lib.w2float
"""
},
// floatvar = float value
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
@ -2018,42 +1753,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// memfloat = uwordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
when (segment[0].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.uw2float
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.uw2float
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.uw2float
"""
else ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.uw2float
"""
}
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.uw2float
"""
},
// memfloat = bytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
@ -2073,42 +1781,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// memfloat = wordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
when (segment[0].callLabel) {
"AX" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
stx ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.w2float
"""
"AY" ->
"""
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.w2float
"""
"XY" ->
"""
stx ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.w2float
"""
else ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.w2float
"""
}
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
lda ${segment[0].callLabel}+1
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<${segment[2].arg!!.integerValue().toHex()}
ldy #>${segment[2].arg!!.integerValue().toHex()}
jsr prog8_lib.w2float
"""
},
// memfloat = mem byte
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->

View File

@ -1,4 +1,4 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
// Generated from ../antlr/prog8.g4 by ANTLR 4.7.1
package prog8.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
@ -11,7 +11,7 @@ import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Lexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
@ -31,10 +31,9 @@ public class prog8Lexer extends Lexer {
T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87,
T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94,
T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101,
T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107,
LINECOMMENT=108, COMMENT=109, WS=110, EOL=111, NAME=112, DEC_INTEGER=113,
HEX_INTEGER=114, BIN_INTEGER=115, FLOAT_NUMBER=116, STRING=117, INLINEASMBLOCK=118,
SINGLECHAR=119;
T__101=102, T__102=103, T__103=104, LINECOMMENT=105, COMMENT=106, WS=107,
EOL=108, NAME=109, DEC_INTEGER=110, HEX_INTEGER=111, BIN_INTEGER=112,
FLOAT_NUMBER=113, STRING=114, INLINEASMBLOCK=115, SINGLECHAR=116;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@ -56,10 +55,10 @@ public class prog8Lexer extends Lexer {
"T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80",
"T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88",
"T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96",
"T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104",
"T__105", "T__106", "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER",
"HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ",
"STRING", "INLINEASMBLOCK", "SINGLECHAR"
"T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "LINECOMMENT",
"COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER",
"FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK",
"SINGLECHAR"
};
private static final String[] _LITERAL_NAMES = {
@ -71,12 +70,12 @@ public class prog8Lexer extends Lexer {
"'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'",
"'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='",
"'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'",
"'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'",
"'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'",
"'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'",
"'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'",
"'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'",
"'for'", "'in'", "'while'", "'repeat'", "'until'"
"'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'Pc'",
"'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", "'%asm'", "'sub'",
"'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'", "'if'", "'else'",
"'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", "'if_nz'", "'if_pl'",
"'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'",
"'while'", "'repeat'", "'until'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -87,9 +86,9 @@ public class prog8Lexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
"LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER",
"BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK", "SINGLECHAR"
null, null, null, null, null, null, null, null, null, "LINECOMMENT", "COMMENT",
"WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER",
"STRING", "INLINEASMBLOCK", "SINGLECHAR"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@ -151,13 +150,13 @@ public class prog8Lexer extends Lexer {
@Override
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
switch (ruleIndex) {
case 118:
case 115:
STRING_action((RuleContext)_localctx, actionIndex);
break;
case 119:
case 116:
INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex);
break;
case 120:
case 117:
SINGLECHAR_action((RuleContext)_localctx, actionIndex);
break;
}
@ -197,7 +196,7 @@ public class prog8Lexer extends Lexer {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2y\u0350\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2v\u0341\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@ -210,51 +209,50 @@ public class prog8Lexer extends Lexer {
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+
"k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv\4"+
"w\tw\4x\tx\4y\ty\4z\tz\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5"+
"\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3"+
"\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+
"\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3"+
"\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f"+
"\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3"+
"\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3"+
"\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3"+
"\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3"+
"\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3"+
"\27\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3"+
"\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35\3\35\3"+
"\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!\3!\3\"\3\"\3\"\3#\3#\3"+
"#\3#\3$\3$\3$\3%\3%\3%\3&\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3"+
"+\3,\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3"+
"\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\38"+
"\39\39\3:\3:\3;\3;\3;\3<\3<\3<\3<\3<\3=\3=\3=\3=\3>\3>\3>\3?\3?\3?\3?"+
"\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C"+
"\3C\3C\3C\3D\3D\3E\3E\3F\3F\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K"+
"\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O\3O\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q"+
"\3R\3R\3R\3R\3R\3S\3S\3S\3S\3T\3T\3T\3U\3U\3V\3V\3W\3W\3W\3W\3W\3W\3W"+
"\3X\3X\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3Z\3Z\3Z\3[\3[\3[\3[\3[\3\\\3\\\3\\"+
"\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3_\3_\3_\3_\3_\3`\3`"+
"\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\3c"+
"\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e\3e\3f\3f\3f\3f\3f\3f\3g\3g\3g\3g"+
"\3g\3g\3h\3h\3h\3h\3i\3i\3i\3j\3j\3j\3j\3j\3j\3k\3k\3k\3k\3k\3k\3k\3l"+
"\3l\3l\3l\3l\3l\3m\3m\7m\u02df\nm\fm\16m\u02e2\13m\3m\3m\3m\3m\3n\3n\7"+
"n\u02ea\nn\fn\16n\u02ed\13n\3n\3n\3o\3o\3o\3o\3p\6p\u02f6\np\rp\16p\u02f7"+
"\3q\3q\7q\u02fc\nq\fq\16q\u02ff\13q\3r\3r\3r\6r\u0304\nr\rr\16r\u0305"+
"\5r\u0308\nr\3s\3s\6s\u030c\ns\rs\16s\u030d\3t\3t\6t\u0312\nt\rt\16t\u0313"+
"\3u\3u\3u\5u\u0319\nu\3u\5u\u031c\nu\3v\6v\u031f\nv\rv\16v\u0320\3v\3"+
"v\6v\u0325\nv\rv\16v\u0326\5v\u0329\nv\3w\3w\3w\3w\5w\u032f\nw\3x\3x\3"+
"x\7x\u0334\nx\fx\16x\u0337\13x\3x\3x\3x\3y\3y\3y\3y\6y\u0340\ny\ry\16"+
"y\u0341\3y\3y\3y\3y\3y\3z\3z\3z\5z\u034c\nz\3z\3z\3z\3\u0341\2{\3\3\5"+
"\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21"+
"!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!"+
"A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s"+
";u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008f"+
"I\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3"+
"S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7"+
"]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cb"+
"g\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00ddp\u00df"+
"q\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00eb\2\u00ed\2\u00efw\u00f1x\u00f3"+
"y\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;"+
"CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u035f\2\3\3\2\2\2\2\5\3\2\2\2"+
"w\tw\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
"\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7"+
"\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3"+
"\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3"+
"\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3"+
"\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+
"\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21"+
"\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23"+
"\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25"+
"\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30"+
"\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\33"+
"\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3\36\3\37"+
"\3\37\3\37\3 \3 \3 \3!\3!\3!\3!\3\"\3\"\3\"\3#\3#\3#\3#\3$\3$\3$\3%\3"+
"%\3%\3&\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,\3-\3-\3-\3"+
".\3.\3/\3/\3\60\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3\63\3\64\3\64\3\64"+
"\3\65\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\38\39\39\3:\3:\3;\3;"+
"\3;\3<\3<\3<\3<\3<\3=\3=\3=\3=\3>\3>\3>\3?\3?\3?\3?\3@\3@\3@\3@\3A\3A"+
"\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3C\3C\3C\3D\3D\3E"+
"\3E\3F\3F\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M"+
"\3M\3M\3N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\3Q\3Q\3Q\3R\3R\3S"+
"\3S\3T\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3U\3U\3U\3V\3V\3W\3W\3W\3X"+
"\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3\\"+
"\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3_\3_\3_\3_\3_\3"+
"_\3`\3`\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3b\3c\3c\3"+
"c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3f\3f\3f\3g\3g\3g\3g\3g\3g\3"+
"h\3h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3j\3j\7j\u02d0\nj\fj\16j\u02d3\13"+
"j\3j\3j\3j\3j\3k\3k\7k\u02db\nk\fk\16k\u02de\13k\3k\3k\3l\3l\3l\3l\3m"+
"\6m\u02e7\nm\rm\16m\u02e8\3n\3n\7n\u02ed\nn\fn\16n\u02f0\13n\3o\3o\3o"+
"\6o\u02f5\no\ro\16o\u02f6\5o\u02f9\no\3p\3p\6p\u02fd\np\rp\16p\u02fe\3"+
"q\3q\6q\u0303\nq\rq\16q\u0304\3r\3r\3r\5r\u030a\nr\3r\5r\u030d\nr\3s\6"+
"s\u0310\ns\rs\16s\u0311\3s\3s\6s\u0316\ns\rs\16s\u0317\5s\u031a\ns\3t"+
"\3t\3t\3t\5t\u0320\nt\3u\3u\3u\7u\u0325\nu\fu\16u\u0328\13u\3u\3u\3u\3"+
"v\3v\3v\3v\6v\u0331\nv\rv\16v\u0332\3v\3v\3v\3v\3v\3w\3w\3w\5w\u033d\n"+
"w\3w\3w\3w\3\u0332\2x\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27"+
"\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33"+
"\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63"+
"e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089"+
"F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009d"+
"P\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1"+
"Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5"+
"d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9"+
"n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5\2\u00e7\2\u00e9t\u00ebu\u00ed"+
"v\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;"+
"CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u0350\2\3\3\2\2\2\2\5\3\2\2\2"+
"\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3"+
"\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2"+
"\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2"+
@ -276,208 +274,204 @@ public class prog8Lexer extends Lexer {
"\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2"+
"\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9"+
"\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\3\2\2"+
"\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00ef"+
"\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2\2\3\u00f5\3\2\2\2\5\u00f7\3\2\2"+
"\2\7\u00f9\3\2\2\2\t\u00fe\3\2\2\2\13\u0106\3\2\2\2\r\u0110\3\2\2\2\17"+
"\u011a\3\2\2\2\21\u0126\3\2\2\2\23\u012f\3\2\2\2\25\u0137\3\2\2\2\27\u0143"+
"\3\2\2\2\31\u014f\3\2\2\2\33\u015a\3\2\2\2\35\u0162\3\2\2\2\37\u0164\3"+
"\2\2\2!\u0166\3\2\2\2#\u016c\3\2\2\2%\u0173\3\2\2\2\'\u0179\3\2\2\2)\u017e"+
"\3\2\2\2+\u0184\3\2\2\2-\u0189\3\2\2\2/\u018f\3\2\2\2\61\u0193\3\2\2\2"+
"\63\u0199\3\2\2\2\65\u019f\3\2\2\2\67\u01a6\3\2\2\29\u01a8\3\2\2\2;\u01aa"+
"\3\2\2\2=\u01ad\3\2\2\2?\u01b0\3\2\2\2A\u01b3\3\2\2\2C\u01b7\3\2\2\2E"+
"\u01ba\3\2\2\2G\u01be\3\2\2\2I\u01c1\3\2\2\2K\u01c4\3\2\2\2M\u01c7\3\2"+
"\2\2O\u01ca\3\2\2\2Q\u01cd\3\2\2\2S\u01cf\3\2\2\2U\u01d1\3\2\2\2W\u01d3"+
"\3\2\2\2Y\u01d5\3\2\2\2[\u01d8\3\2\2\2]\u01da\3\2\2\2_\u01dc\3\2\2\2a"+
"\u01df\3\2\2\2c\u01e1\3\2\2\2e\u01e3\3\2\2\2g\u01e5\3\2\2\2i\u01e8\3\2"+
"\2\2k\u01eb\3\2\2\2m\u01ee\3\2\2\2o\u01f1\3\2\2\2q\u01f3\3\2\2\2s\u01f5"+
"\3\2\2\2u\u01f7\3\2\2\2w\u01fa\3\2\2\2y\u01ff\3\2\2\2{\u0203\3\2\2\2}"+
"\u0206\3\2\2\2\177\u020a\3\2\2\2\u0081\u020e\3\2\2\2\u0083\u0215\3\2\2"+
"\2\u0085\u021b\3\2\2\2\u0087\u0224\3\2\2\2\u0089\u0226\3\2\2\2\u008b\u0228"+
"\3\2\2\2\u008d\u022a\3\2\2\2\u008f\u022c\3\2\2\2\u0091\u022f\3\2\2\2\u0093"+
"\u0232\3\2\2\2\u0095\u0235\3\2\2\2\u0097\u0238\3\2\2\2\u0099\u023b\3\2"+
"\2\2\u009b\u023e\3\2\2\2\u009d\u0241\3\2\2\2\u009f\u0244\3\2\2\2\u00a1"+
"\u0249\3\2\2\2\u00a3\u024f\3\2\2\2\u00a5\u0254\3\2\2\2\u00a7\u0258\3\2"+
"\2\2\u00a9\u025b\3\2\2\2\u00ab\u025d\3\2\2\2\u00ad\u025f\3\2\2\2\u00af"+
"\u0266\3\2\2\2\u00b1\u026f\3\2\2\2\u00b3\u0271\3\2\2\2\u00b5\u0274\3\2"+
"\2\2\u00b7\u0279\3\2\2\2\u00b9\u027f\3\2\2\2\u00bb\u0285\3\2\2\2\u00bd"+
"\u028b\3\2\2\2\u00bf\u0290\3\2\2\2\u00c1\u0296\3\2\2\2\u00c3\u029c\3\2"+
"\2\2\u00c5\u02a2\3\2\2\2\u00c7\u02a9\3\2\2\2\u00c9\u02af\3\2\2\2\u00cb"+
"\u02b6\3\2\2\2\u00cd\u02bc\3\2\2\2\u00cf\u02c2\3\2\2\2\u00d1\u02c6\3\2"+
"\2\2\u00d3\u02c9\3\2\2\2\u00d5\u02cf\3\2\2\2\u00d7\u02d6\3\2\2\2\u00d9"+
"\u02dc\3\2\2\2\u00db\u02e7\3\2\2\2\u00dd\u02f0\3\2\2\2\u00df\u02f5\3\2"+
"\2\2\u00e1\u02f9\3\2\2\2\u00e3\u0307\3\2\2\2\u00e5\u0309\3\2\2\2\u00e7"+
"\u030f\3\2\2\2\u00e9\u0315\3\2\2\2\u00eb\u031e\3\2\2\2\u00ed\u032e\3\2"+
"\2\2\u00ef\u0330\3\2\2\2\u00f1\u033b\3\2\2\2\u00f3\u0348\3\2\2\2\u00f5"+
"\u00f6\7\u0080\2\2\u00f6\4\3\2\2\2\u00f7\u00f8\7<\2\2\u00f8\6\3\2\2\2"+
"\u00f9\u00fa\7i\2\2\u00fa\u00fb\7q\2\2\u00fb\u00fc\7v\2\2\u00fc\u00fd"+
"\7q\2\2\u00fd\b\3\2\2\2\u00fe\u00ff\7\'\2\2\u00ff\u0100\7q\2\2\u0100\u0101"+
"\7w\2\2\u0101\u0102\7v\2\2\u0102\u0103\7r\2\2\u0103\u0104\7w\2\2\u0104"+
"\u0105\7v\2\2\u0105\n\3\2\2\2\u0106\u0107\7\'\2\2\u0107\u0108\7n\2\2\u0108"+
"\u0109\7c\2\2\u0109\u010a\7w\2\2\u010a\u010b\7p\2\2\u010b\u010c\7e\2\2"+
"\u010c\u010d\7j\2\2\u010d\u010e\7g\2\2\u010e\u010f\7t\2\2\u010f\f\3\2"+
"\2\2\u0110\u0111\7\'\2\2\u0111\u0112\7|\2\2\u0112\u0113\7g\2\2\u0113\u0114"+
"\7t\2\2\u0114\u0115\7q\2\2\u0115\u0116\7r\2\2\u0116\u0117\7c\2\2\u0117"+
"\u0118\7i\2\2\u0118\u0119\7g\2\2\u0119\16\3\2\2\2\u011a\u011b\7\'\2\2"+
"\u011b\u011c\7|\2\2\u011c\u011d\7r\2\2\u011d\u011e\7t\2\2\u011e\u011f"+
"\7g\2\2\u011f\u0120\7u\2\2\u0120\u0121\7g\2\2\u0121\u0122\7t\2\2\u0122"+
"\u0123\7x\2\2\u0123\u0124\7g\2\2\u0124\u0125\7f\2\2\u0125\20\3\2\2\2\u0126"+
"\u0127\7\'\2\2\u0127\u0128\7c\2\2\u0128\u0129\7f\2\2\u0129\u012a\7f\2"+
"\2\u012a\u012b\7t\2\2\u012b\u012c\7g\2\2\u012c\u012d\7u\2\2\u012d\u012e"+
"\7u\2\2\u012e\22\3\2\2\2\u012f\u0130\7\'\2\2\u0130\u0131\7k\2\2\u0131"+
"\u0132\7o\2\2\u0132\u0133\7r\2\2\u0133\u0134\7q\2\2\u0134\u0135\7t\2\2"+
"\u0135\u0136\7v\2\2\u0136\24\3\2\2\2\u0137\u0138\7\'\2\2\u0138\u0139\7"+
"d\2\2\u0139\u013a\7t\2\2\u013a\u013b\7g\2\2\u013b\u013c\7c\2\2\u013c\u013d"+
"\7m\2\2\u013d\u013e\7r\2\2\u013e\u013f\7q\2\2\u013f\u0140\7k\2\2\u0140"+
"\u0141\7p\2\2\u0141\u0142\7v\2\2\u0142\26\3\2\2\2\u0143\u0144\7\'\2\2"+
"\u0144\u0145\7c\2\2\u0145\u0146\7u\2\2\u0146\u0147\7o\2\2\u0147\u0148"+
"\7k\2\2\u0148\u0149\7p\2\2\u0149\u014a\7e\2\2\u014a\u014b\7n\2\2\u014b"+
"\u014c\7w\2\2\u014c\u014d\7f\2\2\u014d\u014e\7g\2\2\u014e\30\3\2\2\2\u014f"+
"\u0150\7\'\2\2\u0150\u0151\7c\2\2\u0151\u0152\7u\2\2\u0152\u0153\7o\2"+
"\2\u0153\u0154\7d\2\2\u0154\u0155\7k\2\2\u0155\u0156\7p\2\2\u0156\u0157"+
"\7c\2\2\u0157\u0158\7t\2\2\u0158\u0159\7{\2\2\u0159\32\3\2\2\2\u015a\u015b"+
"\7\'\2\2\u015b\u015c\7q\2\2\u015c\u015d\7r\2\2\u015d\u015e\7v\2\2\u015e"+
"\u015f\7k\2\2\u015f\u0160\7q\2\2\u0160\u0161\7p\2\2\u0161\34\3\2\2\2\u0162"+
"\u0163\7.\2\2\u0163\36\3\2\2\2\u0164\u0165\7?\2\2\u0165 \3\2\2\2\u0166"+
"\u0167\7e\2\2\u0167\u0168\7q\2\2\u0168\u0169\7p\2\2\u0169\u016a\7u\2\2"+
"\u016a\u016b\7v\2\2\u016b\"\3\2\2\2\u016c\u016d\7o\2\2\u016d\u016e\7g"+
"\2\2\u016e\u016f\7o\2\2\u016f\u0170\7q\2\2\u0170\u0171\7t\2\2\u0171\u0172"+
"\7{\2\2\u0172$\3\2\2\2\u0173\u0174\7w\2\2\u0174\u0175\7d\2\2\u0175\u0176"+
"\7{\2\2\u0176\u0177\7v\2\2\u0177\u0178\7g\2\2\u0178&\3\2\2\2\u0179\u017a"+
"\7d\2\2\u017a\u017b\7{\2\2\u017b\u017c\7v\2\2\u017c\u017d\7g\2\2\u017d"+
"(\3\2\2\2\u017e\u017f\7w\2\2\u017f\u0180\7y\2\2\u0180\u0181\7q\2\2\u0181"+
"\u0182\7t\2\2\u0182\u0183\7f\2\2\u0183*\3\2\2\2\u0184\u0185\7y\2\2\u0185"+
"\u0186\7q\2\2\u0186\u0187\7t\2\2\u0187\u0188\7f\2\2\u0188,\3\2\2\2\u0189"+
"\u018a\7h\2\2\u018a\u018b\7n\2\2\u018b\u018c\7q\2\2\u018c\u018d\7c\2\2"+
"\u018d\u018e\7v\2\2\u018e.\3\2\2\2\u018f\u0190\7u\2\2\u0190\u0191\7v\2"+
"\2\u0191\u0192\7t\2\2\u0192\60\3\2\2\2\u0193\u0194\7u\2\2\u0194\u0195"+
"\7v\2\2\u0195\u0196\7t\2\2\u0196\u0197\7a\2\2\u0197\u0198\7r\2\2\u0198"+
"\62\3\2\2\2\u0199\u019a\7u\2\2\u019a\u019b\7v\2\2\u019b\u019c\7t\2\2\u019c"+
"\u019d\7a\2\2\u019d\u019e\7u\2\2\u019e\64\3\2\2\2\u019f\u01a0\7u\2\2\u01a0"+
"\u01a1\7v\2\2\u01a1\u01a2\7t\2\2\u01a2\u01a3\7a\2\2\u01a3\u01a4\7r\2\2"+
"\u01a4\u01a5\7u\2\2\u01a5\66\3\2\2\2\u01a6\u01a7\7]\2\2\u01a78\3\2\2\2"+
"\u01a8\u01a9\7_\2\2\u01a9:\3\2\2\2\u01aa\u01ab\7-\2\2\u01ab\u01ac\7?\2"+
"\2\u01ac<\3\2\2\2\u01ad\u01ae\7/\2\2\u01ae\u01af\7?\2\2\u01af>\3\2\2\2"+
"\u01b0\u01b1\7\61\2\2\u01b1\u01b2\7?\2\2\u01b2@\3\2\2\2\u01b3\u01b4\7"+
"\61\2\2\u01b4\u01b5\7\61\2\2\u01b5\u01b6\7?\2\2\u01b6B\3\2\2\2\u01b7\u01b8"+
"\7,\2\2\u01b8\u01b9\7?\2\2\u01b9D\3\2\2\2\u01ba\u01bb\7,\2\2\u01bb\u01bc"+
"\7,\2\2\u01bc\u01bd\7?\2\2\u01bdF\3\2\2\2\u01be\u01bf\7(\2\2\u01bf\u01c0"+
"\7?\2\2\u01c0H\3\2\2\2\u01c1\u01c2\7~\2\2\u01c2\u01c3\7?\2\2\u01c3J\3"+
"\2\2\2\u01c4\u01c5\7`\2\2\u01c5\u01c6\7?\2\2\u01c6L\3\2\2\2\u01c7\u01c8"+
"\7-\2\2\u01c8\u01c9\7-\2\2\u01c9N\3\2\2\2\u01ca\u01cb\7/\2\2\u01cb\u01cc"+
"\7/\2\2\u01ccP\3\2\2\2\u01cd\u01ce\7*\2\2\u01ceR\3\2\2\2\u01cf\u01d0\7"+
"+\2\2\u01d0T\3\2\2\2\u01d1\u01d2\7-\2\2\u01d2V\3\2\2\2\u01d3\u01d4\7/"+
"\2\2\u01d4X\3\2\2\2\u01d5\u01d6\7,\2\2\u01d6\u01d7\7,\2\2\u01d7Z\3\2\2"+
"\2\u01d8\u01d9\7,\2\2\u01d9\\\3\2\2\2\u01da\u01db\7\61\2\2\u01db^\3\2"+
"\2\2\u01dc\u01dd\7\61\2\2\u01dd\u01de\7\61\2\2\u01de`\3\2\2\2\u01df\u01e0"+
"\7\'\2\2\u01e0b\3\2\2\2\u01e1\u01e2\7>\2\2\u01e2d\3\2\2\2\u01e3\u01e4"+
"\7@\2\2\u01e4f\3\2\2\2\u01e5\u01e6\7>\2\2\u01e6\u01e7\7?\2\2\u01e7h\3"+
"\2\2\2\u01e8\u01e9\7@\2\2\u01e9\u01ea\7?\2\2\u01eaj\3\2\2\2\u01eb\u01ec"+
"\7?\2\2\u01ec\u01ed\7?\2\2\u01edl\3\2\2\2\u01ee\u01ef\7#\2\2\u01ef\u01f0"+
"\7?\2\2\u01f0n\3\2\2\2\u01f1\u01f2\7(\2\2\u01f2p\3\2\2\2\u01f3\u01f4\7"+
"`\2\2\u01f4r\3\2\2\2\u01f5\u01f6\7~\2\2\u01f6t\3\2\2\2\u01f7\u01f8\7v"+
"\2\2\u01f8\u01f9\7q\2\2\u01f9v\3\2\2\2\u01fa\u01fb\7u\2\2\u01fb\u01fc"+
"\7v\2\2\u01fc\u01fd\7g\2\2\u01fd\u01fe\7r\2\2\u01fex\3\2\2\2\u01ff\u0200"+
"\7c\2\2\u0200\u0201\7p\2\2\u0201\u0202\7f\2\2\u0202z\3\2\2\2\u0203\u0204"+
"\7q\2\2\u0204\u0205\7t\2\2\u0205|\3\2\2\2\u0206\u0207\7z\2\2\u0207\u0208"+
"\7q\2\2\u0208\u0209\7t\2\2\u0209~\3\2\2\2\u020a\u020b\7p\2\2\u020b\u020c"+
"\7q\2\2\u020c\u020d\7v\2\2\u020d\u0080\3\2\2\2\u020e\u020f\7t\2\2\u020f"+
"\u0210\7g\2\2\u0210\u0211\7v\2\2\u0211\u0212\7w\2\2\u0212\u0213\7t\2\2"+
"\u0213\u0214\7p\2\2\u0214\u0082\3\2\2\2\u0215\u0216\7d\2\2\u0216\u0217"+
"\7t\2\2\u0217\u0218\7g\2\2\u0218\u0219\7c\2\2\u0219\u021a\7m\2\2\u021a"+
"\u0084\3\2\2\2\u021b\u021c\7e\2\2\u021c\u021d\7q\2\2\u021d\u021e\7p\2"+
"\2\u021e\u021f\7v\2\2\u021f\u0220\7k\2\2\u0220\u0221\7p\2\2\u0221\u0222"+
"\7w\2\2\u0222\u0223\7g\2\2\u0223\u0086\3\2\2\2\u0224\u0225\7\60\2\2\u0225"+
"\u0088\3\2\2\2\u0226\u0227\7C\2\2\u0227\u008a\3\2\2\2\u0228\u0229\7Z\2"+
"\2\u0229\u008c\3\2\2\2\u022a\u022b\7[\2\2\u022b\u008e\3\2\2\2\u022c\u022d"+
"\7C\2\2\u022d\u022e\7Z\2\2\u022e\u0090\3\2\2\2\u022f\u0230\7C\2\2\u0230"+
"\u0231\7[\2\2\u0231\u0092\3\2\2\2\u0232\u0233\7Z\2\2\u0233\u0234\7[\2"+
"\2\u0234\u0094\3\2\2\2\u0235\u0236\7R\2\2\u0236\u0237\7e\2\2\u0237\u0096"+
"\3\2\2\2\u0238\u0239\7R\2\2\u0239\u023a\7|\2\2\u023a\u0098\3\2\2\2\u023b"+
"\u023c\7R\2\2\u023c\u023d\7p\2\2\u023d\u009a\3\2\2\2\u023e\u023f\7R\2"+
"\2\u023f\u0240\7x\2\2\u0240\u009c\3\2\2\2\u0241\u0242\7\60\2\2\u0242\u0243"+
"\7y\2\2\u0243\u009e\3\2\2\2\u0244\u0245\7v\2\2\u0245\u0246\7t\2\2\u0246"+
"\u0247\7w\2\2\u0247\u0248\7g\2\2\u0248\u00a0\3\2\2\2\u0249\u024a\7h\2"+
"\2\u024a\u024b\7c\2\2\u024b\u024c\7n\2\2\u024c\u024d\7u\2\2\u024d\u024e"+
"\7g\2\2\u024e\u00a2\3\2\2\2\u024f\u0250\7\'\2\2\u0250\u0251\7c\2\2\u0251"+
"\u0252\7u\2\2\u0252\u0253\7o\2\2\u0253\u00a4\3\2\2\2\u0254\u0255\7u\2"+
"\2\u0255\u0256\7w\2\2\u0256\u0257\7d\2\2\u0257\u00a6\3\2\2\2\u0258\u0259"+
"\7/\2\2\u0259\u025a\7@\2\2\u025a\u00a8\3\2\2\2\u025b\u025c\7}\2\2\u025c"+
"\u00aa\3\2\2\2\u025d\u025e\7\177\2\2\u025e\u00ac\3\2\2\2\u025f\u0260\7"+
"c\2\2\u0260\u0261\7u\2\2\u0261\u0262\7o\2\2\u0262\u0263\7u\2\2\u0263\u0264"+
"\7w\2\2\u0264\u0265\7d\2\2\u0265\u00ae\3\2\2\2\u0266\u0267\7e\2\2\u0267"+
"\u0268\7n\2\2\u0268\u0269\7q\2\2\u0269\u026a\7d\2\2\u026a\u026b\7d\2\2"+
"\u026b\u026c\7g\2\2\u026c\u026d\7t\2\2\u026d\u026e\7u\2\2\u026e\u00b0"+
"\3\2\2\2\u026f\u0270\7B\2\2\u0270\u00b2\3\2\2\2\u0271\u0272\7k\2\2\u0272"+
"\u0273\7h\2\2\u0273\u00b4\3\2\2\2\u0274\u0275\7g\2\2\u0275\u0276\7n\2"+
"\2\u0276\u0277\7u\2\2\u0277\u0278\7g\2\2\u0278\u00b6\3\2\2\2\u0279\u027a"+
"\7k\2\2\u027a\u027b\7h\2\2\u027b\u027c\7a\2\2\u027c\u027d\7e\2\2\u027d"+
"\u027e\7u\2\2\u027e\u00b8\3\2\2\2\u027f\u0280\7k\2\2\u0280\u0281\7h\2"+
"\2\u0281\u0282\7a\2\2\u0282\u0283\7e\2\2\u0283\u0284\7e\2\2\u0284\u00ba"+
"\3\2\2\2\u0285\u0286\7k\2\2\u0286\u0287\7h\2\2\u0287\u0288\7a\2\2\u0288"+
"\u0289\7g\2\2\u0289\u028a\7s\2\2\u028a\u00bc\3\2\2\2\u028b\u028c\7k\2"+
"\2\u028c\u028d\7h\2\2\u028d\u028e\7a\2\2\u028e\u028f\7|\2\2\u028f\u00be"+
"\3\2\2\2\u0290\u0291\7k\2\2\u0291\u0292\7h\2\2\u0292\u0293\7a\2\2\u0293"+
"\u0294\7p\2\2\u0294\u0295\7g\2\2\u0295\u00c0\3\2\2\2\u0296\u0297\7k\2"+
"\2\u0297\u0298\7h\2\2\u0298\u0299\7a\2\2\u0299\u029a\7p\2\2\u029a\u029b"+
"\7|\2\2\u029b\u00c2\3\2\2\2\u029c\u029d\7k\2\2\u029d\u029e\7h\2\2\u029e"+
"\u029f\7a\2\2\u029f\u02a0\7r\2\2\u02a0\u02a1\7n\2\2\u02a1\u00c4\3\2\2"+
"\2\u02a2\u02a3\7k\2\2\u02a3\u02a4\7h\2\2\u02a4\u02a5\7a\2\2\u02a5\u02a6"+
"\7r\2\2\u02a6\u02a7\7q\2\2\u02a7\u02a8\7u\2\2\u02a8\u00c6\3\2\2\2\u02a9"+
"\u02aa\7k\2\2\u02aa\u02ab\7h\2\2\u02ab\u02ac\7a\2\2\u02ac\u02ad\7o\2\2"+
"\u02ad\u02ae\7k\2\2\u02ae\u00c8\3\2\2\2\u02af\u02b0\7k\2\2\u02b0\u02b1"+
"\7h\2\2\u02b1\u02b2\7a\2\2\u02b2\u02b3\7p\2\2\u02b3\u02b4\7g\2\2\u02b4"+
"\u02b5\7i\2\2\u02b5\u00ca\3\2\2\2\u02b6\u02b7\7k\2\2\u02b7\u02b8\7h\2"+
"\2\u02b8\u02b9\7a\2\2\u02b9\u02ba\7x\2\2\u02ba\u02bb\7u\2\2\u02bb\u00cc"+
"\3\2\2\2\u02bc\u02bd\7k\2\2\u02bd\u02be\7h\2\2\u02be\u02bf\7a\2\2\u02bf"+
"\u02c0\7x\2\2\u02c0\u02c1\7e\2\2\u02c1\u00ce\3\2\2\2\u02c2\u02c3\7h\2"+
"\2\u02c3\u02c4\7q\2\2\u02c4\u02c5\7t\2\2\u02c5\u00d0\3\2\2\2\u02c6\u02c7"+
"\7k\2\2\u02c7\u02c8\7p\2\2\u02c8\u00d2\3\2\2\2\u02c9\u02ca\7y\2\2\u02ca"+
"\u02cb\7j\2\2\u02cb\u02cc\7k\2\2\u02cc\u02cd\7n\2\2\u02cd\u02ce\7g\2\2"+
"\u02ce\u00d4\3\2\2\2\u02cf\u02d0\7t\2\2\u02d0\u02d1\7g\2\2\u02d1\u02d2"+
"\7r\2\2\u02d2\u02d3\7g\2\2\u02d3\u02d4\7c\2\2\u02d4\u02d5\7v\2\2\u02d5"+
"\u00d6\3\2\2\2\u02d6\u02d7\7w\2\2\u02d7\u02d8\7p\2\2\u02d8\u02d9\7v\2"+
"\2\u02d9\u02da\7k\2\2\u02da\u02db\7n\2\2\u02db\u00d8\3\2\2\2\u02dc\u02e0"+
"\t\2\2\2\u02dd\u02df\t\3\2\2\u02de\u02dd\3\2\2\2\u02df\u02e2\3\2\2\2\u02e0"+
"\u02de\3\2\2\2\u02e0\u02e1\3\2\2\2\u02e1\u02e3\3\2\2\2\u02e2\u02e0\3\2"+
"\2\2\u02e3\u02e4\5\u00dbn\2\u02e4\u02e5\3\2\2\2\u02e5\u02e6\bm\2\2\u02e6"+
"\u00da\3\2\2\2\u02e7\u02eb\7=\2\2\u02e8\u02ea\n\2\2\2\u02e9\u02e8\3\2"+
"\2\2\u02ea\u02ed\3\2\2\2\u02eb\u02e9\3\2\2\2\u02eb\u02ec\3\2\2\2\u02ec"+
"\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02ef\bn\2\2\u02ef\u00dc\3\2"+
"\2\2\u02f0\u02f1\t\3\2\2\u02f1\u02f2\3\2\2\2\u02f2\u02f3\bo\3\2\u02f3"+
"\u00de\3\2\2\2\u02f4\u02f6\t\2\2\2\u02f5\u02f4\3\2\2\2\u02f6\u02f7\3\2"+
"\2\2\u02f7\u02f5\3\2\2\2\u02f7\u02f8\3\2\2\2\u02f8\u00e0\3\2\2\2\u02f9"+
"\u02fd\t\4\2\2\u02fa\u02fc\t\5\2\2\u02fb\u02fa\3\2\2\2\u02fc\u02ff\3\2"+
"\2\2\u02fd\u02fb\3\2\2\2\u02fd\u02fe\3\2\2\2\u02fe\u00e2\3\2\2\2\u02ff"+
"\u02fd\3\2\2\2\u0300\u0308\4\62;\2\u0301\u0303\4\63;\2\u0302\u0304\4\62"+
";\2\u0303\u0302\3\2\2\2\u0304\u0305\3\2\2\2\u0305\u0303\3\2\2\2\u0305"+
"\u0306\3\2\2\2\u0306\u0308\3\2\2\2\u0307\u0300\3\2\2\2\u0307\u0301\3\2"+
"\2\2\u0308\u00e4\3\2\2\2\u0309\u030b\7&\2\2\u030a\u030c\t\6\2\2\u030b"+
"\u030a\3\2\2\2\u030c\u030d\3\2\2\2\u030d\u030b\3\2\2\2\u030d\u030e\3\2"+
"\2\2\u030e\u00e6\3\2\2\2\u030f\u0311\7\'\2\2\u0310\u0312\4\62\63\2\u0311"+
"\u0310\3\2\2\2\u0312\u0313\3\2\2\2\u0313\u0311\3\2\2\2\u0313\u0314\3\2"+
"\2\2\u0314\u00e8\3\2\2\2\u0315\u031b\5\u00ebv\2\u0316\u0318\t\7\2\2\u0317"+
"\u0319\t\b\2\2\u0318\u0317\3\2\2\2\u0318\u0319\3\2\2\2\u0319\u031a\3\2"+
"\2\2\u031a\u031c\5\u00ebv\2\u031b\u0316\3\2\2\2\u031b\u031c\3\2\2\2\u031c"+
"\u00ea\3\2\2\2\u031d\u031f\4\62;\2\u031e\u031d\3\2\2\2\u031f\u0320\3\2"+
"\2\2\u0320\u031e\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0328\3\2\2\2\u0322"+
"\u0324\7\60\2\2\u0323\u0325\4\62;\2\u0324\u0323\3\2\2\2\u0325\u0326\3"+
"\2\2\2\u0326\u0324\3\2\2\2\u0326\u0327\3\2\2\2\u0327\u0329\3\2\2\2\u0328"+
"\u0322\3\2\2\2\u0328\u0329\3\2\2\2\u0329\u00ec\3\2\2\2\u032a\u032b\7^"+
"\2\2\u032b\u032f\13\2\2\2\u032c\u032d\7^\2\2\u032d\u032f\5\u00dfp\2\u032e"+
"\u032a\3\2\2\2\u032e\u032c\3\2\2\2\u032f\u00ee\3\2\2\2\u0330\u0335\7$"+
"\2\2\u0331\u0334\5\u00edw\2\u0332\u0334\n\t\2\2\u0333\u0331\3\2\2\2\u0333"+
"\u0332\3\2\2\2\u0334\u0337\3\2\2\2\u0335\u0333\3\2\2\2\u0335\u0336\3\2"+
"\2\2\u0336\u0338\3\2\2\2\u0337\u0335\3\2\2\2\u0338\u0339\7$\2\2\u0339"+
"\u033a\bx\4\2\u033a\u00f0\3\2\2\2\u033b\u033c\7}\2\2\u033c\u033d\7}\2"+
"\2\u033d\u033f\3\2\2\2\u033e\u0340\13\2\2\2\u033f\u033e\3\2\2\2\u0340"+
"\u0341\3\2\2\2\u0341\u0342\3\2\2\2\u0341\u033f\3\2\2\2\u0342\u0343\3\2"+
"\2\2\u0343\u0344\7\177\2\2\u0344\u0345\7\177\2\2\u0345\u0346\3\2\2\2\u0346"+
"\u0347\by\5\2\u0347\u00f2\3\2\2\2\u0348\u034b\7)\2\2\u0349\u034c\5\u00ed"+
"w\2\u034a\u034c\n\t\2\2\u034b\u0349\3\2\2\2\u034b\u034a\3\2\2\2\u034c"+
"\u034d\3\2\2\2\u034d\u034e\7)\2\2\u034e\u034f\bz\6\2\u034f\u00f4\3\2\2"+
"\2\26\2\u02e0\u02eb\u02f7\u02fd\u0305\u0307\u030b\u030d\u0313\u0318\u031b"+
"\u0320\u0326\u0328\u032e\u0333\u0335\u0341\u034b\7\2\3\2\b\2\2\3x\2\3"+
"y\3\3z\4";
"\2\2\u00e3\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\3\u00ef"+
"\3\2\2\2\5\u00f1\3\2\2\2\7\u00f3\3\2\2\2\t\u00f8\3\2\2\2\13\u0100\3\2"+
"\2\2\r\u010a\3\2\2\2\17\u0114\3\2\2\2\21\u0120\3\2\2\2\23\u0129\3\2\2"+
"\2\25\u0131\3\2\2\2\27\u013d\3\2\2\2\31\u0149\3\2\2\2\33\u0154\3\2\2\2"+
"\35\u015c\3\2\2\2\37\u015e\3\2\2\2!\u0160\3\2\2\2#\u0166\3\2\2\2%\u016d"+
"\3\2\2\2\'\u0173\3\2\2\2)\u0178\3\2\2\2+\u017e\3\2\2\2-\u0183\3\2\2\2"+
"/\u0189\3\2\2\2\61\u018d\3\2\2\2\63\u0193\3\2\2\2\65\u0199\3\2\2\2\67"+
"\u01a0\3\2\2\29\u01a2\3\2\2\2;\u01a4\3\2\2\2=\u01a7\3\2\2\2?\u01aa\3\2"+
"\2\2A\u01ad\3\2\2\2C\u01b1\3\2\2\2E\u01b4\3\2\2\2G\u01b8\3\2\2\2I\u01bb"+
"\3\2\2\2K\u01be\3\2\2\2M\u01c1\3\2\2\2O\u01c4\3\2\2\2Q\u01c7\3\2\2\2S"+
"\u01c9\3\2\2\2U\u01cb\3\2\2\2W\u01cd\3\2\2\2Y\u01cf\3\2\2\2[\u01d2\3\2"+
"\2\2]\u01d4\3\2\2\2_\u01d6\3\2\2\2a\u01d9\3\2\2\2c\u01db\3\2\2\2e\u01dd"+
"\3\2\2\2g\u01df\3\2\2\2i\u01e2\3\2\2\2k\u01e5\3\2\2\2m\u01e8\3\2\2\2o"+
"\u01eb\3\2\2\2q\u01ed\3\2\2\2s\u01ef\3\2\2\2u\u01f1\3\2\2\2w\u01f4\3\2"+
"\2\2y\u01f9\3\2\2\2{\u01fd\3\2\2\2}\u0200\3\2\2\2\177\u0204\3\2\2\2\u0081"+
"\u0208\3\2\2\2\u0083\u020f\3\2\2\2\u0085\u0215\3\2\2\2\u0087\u021e\3\2"+
"\2\2\u0089\u0220\3\2\2\2\u008b\u0222\3\2\2\2\u008d\u0224\3\2\2\2\u008f"+
"\u0226\3\2\2\2\u0091\u0229\3\2\2\2\u0093\u022c\3\2\2\2\u0095\u022f\3\2"+
"\2\2\u0097\u0232\3\2\2\2\u0099\u0235\3\2\2\2\u009b\u023a\3\2\2\2\u009d"+
"\u0240\3\2\2\2\u009f\u0245\3\2\2\2\u00a1\u0249\3\2\2\2\u00a3\u024c\3\2"+
"\2\2\u00a5\u024e\3\2\2\2\u00a7\u0250\3\2\2\2\u00a9\u0257\3\2\2\2\u00ab"+
"\u0260\3\2\2\2\u00ad\u0262\3\2\2\2\u00af\u0265\3\2\2\2\u00b1\u026a\3\2"+
"\2\2\u00b3\u0270\3\2\2\2\u00b5\u0276\3\2\2\2\u00b7\u027c\3\2\2\2\u00b9"+
"\u0281\3\2\2\2\u00bb\u0287\3\2\2\2\u00bd\u028d\3\2\2\2\u00bf\u0293\3\2"+
"\2\2\u00c1\u029a\3\2\2\2\u00c3\u02a0\3\2\2\2\u00c5\u02a7\3\2\2\2\u00c7"+
"\u02ad\3\2\2\2\u00c9\u02b3\3\2\2\2\u00cb\u02b7\3\2\2\2\u00cd\u02ba\3\2"+
"\2\2\u00cf\u02c0\3\2\2\2\u00d1\u02c7\3\2\2\2\u00d3\u02cd\3\2\2\2\u00d5"+
"\u02d8\3\2\2\2\u00d7\u02e1\3\2\2\2\u00d9\u02e6\3\2\2\2\u00db\u02ea\3\2"+
"\2\2\u00dd\u02f8\3\2\2\2\u00df\u02fa\3\2\2\2\u00e1\u0300\3\2\2\2\u00e3"+
"\u0306\3\2\2\2\u00e5\u030f\3\2\2\2\u00e7\u031f\3\2\2\2\u00e9\u0321\3\2"+
"\2\2\u00eb\u032c\3\2\2\2\u00ed\u0339\3\2\2\2\u00ef\u00f0\7\u0080\2\2\u00f0"+
"\4\3\2\2\2\u00f1\u00f2\7<\2\2\u00f2\6\3\2\2\2\u00f3\u00f4\7i\2\2\u00f4"+
"\u00f5\7q\2\2\u00f5\u00f6\7v\2\2\u00f6\u00f7\7q\2\2\u00f7\b\3\2\2\2\u00f8"+
"\u00f9\7\'\2\2\u00f9\u00fa\7q\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7v\2"+
"\2\u00fc\u00fd\7r\2\2\u00fd\u00fe\7w\2\2\u00fe\u00ff\7v\2\2\u00ff\n\3"+
"\2\2\2\u0100\u0101\7\'\2\2\u0101\u0102\7n\2\2\u0102\u0103\7c\2\2\u0103"+
"\u0104\7w\2\2\u0104\u0105\7p\2\2\u0105\u0106\7e\2\2\u0106\u0107\7j\2\2"+
"\u0107\u0108\7g\2\2\u0108\u0109\7t\2\2\u0109\f\3\2\2\2\u010a\u010b\7\'"+
"\2\2\u010b\u010c\7|\2\2\u010c\u010d\7g\2\2\u010d\u010e\7t\2\2\u010e\u010f"+
"\7q\2\2\u010f\u0110\7r\2\2\u0110\u0111\7c\2\2\u0111\u0112\7i\2\2\u0112"+
"\u0113\7g\2\2\u0113\16\3\2\2\2\u0114\u0115\7\'\2\2\u0115\u0116\7|\2\2"+
"\u0116\u0117\7r\2\2\u0117\u0118\7t\2\2\u0118\u0119\7g\2\2\u0119\u011a"+
"\7u\2\2\u011a\u011b\7g\2\2\u011b\u011c\7t\2\2\u011c\u011d\7x\2\2\u011d"+
"\u011e\7g\2\2\u011e\u011f\7f\2\2\u011f\20\3\2\2\2\u0120\u0121\7\'\2\2"+
"\u0121\u0122\7c\2\2\u0122\u0123\7f\2\2\u0123\u0124\7f\2\2\u0124\u0125"+
"\7t\2\2\u0125\u0126\7g\2\2\u0126\u0127\7u\2\2\u0127\u0128\7u\2\2\u0128"+
"\22\3\2\2\2\u0129\u012a\7\'\2\2\u012a\u012b\7k\2\2\u012b\u012c\7o\2\2"+
"\u012c\u012d\7r\2\2\u012d\u012e\7q\2\2\u012e\u012f\7t\2\2\u012f\u0130"+
"\7v\2\2\u0130\24\3\2\2\2\u0131\u0132\7\'\2\2\u0132\u0133\7d\2\2\u0133"+
"\u0134\7t\2\2\u0134\u0135\7g\2\2\u0135\u0136\7c\2\2\u0136\u0137\7m\2\2"+
"\u0137\u0138\7r\2\2\u0138\u0139\7q\2\2\u0139\u013a\7k\2\2\u013a\u013b"+
"\7p\2\2\u013b\u013c\7v\2\2\u013c\26\3\2\2\2\u013d\u013e\7\'\2\2\u013e"+
"\u013f\7c\2\2\u013f\u0140\7u\2\2\u0140\u0141\7o\2\2\u0141\u0142\7k\2\2"+
"\u0142\u0143\7p\2\2\u0143\u0144\7e\2\2\u0144\u0145\7n\2\2\u0145\u0146"+
"\7w\2\2\u0146\u0147\7f\2\2\u0147\u0148\7g\2\2\u0148\30\3\2\2\2\u0149\u014a"+
"\7\'\2\2\u014a\u014b\7c\2\2\u014b\u014c\7u\2\2\u014c\u014d\7o\2\2\u014d"+
"\u014e\7d\2\2\u014e\u014f\7k\2\2\u014f\u0150\7p\2\2\u0150\u0151\7c\2\2"+
"\u0151\u0152\7t\2\2\u0152\u0153\7{\2\2\u0153\32\3\2\2\2\u0154\u0155\7"+
"\'\2\2\u0155\u0156\7q\2\2\u0156\u0157\7r\2\2\u0157\u0158\7v\2\2\u0158"+
"\u0159\7k\2\2\u0159\u015a\7q\2\2\u015a\u015b\7p\2\2\u015b\34\3\2\2\2\u015c"+
"\u015d\7.\2\2\u015d\36\3\2\2\2\u015e\u015f\7?\2\2\u015f \3\2\2\2\u0160"+
"\u0161\7e\2\2\u0161\u0162\7q\2\2\u0162\u0163\7p\2\2\u0163\u0164\7u\2\2"+
"\u0164\u0165\7v\2\2\u0165\"\3\2\2\2\u0166\u0167\7o\2\2\u0167\u0168\7g"+
"\2\2\u0168\u0169\7o\2\2\u0169\u016a\7q\2\2\u016a\u016b\7t\2\2\u016b\u016c"+
"\7{\2\2\u016c$\3\2\2\2\u016d\u016e\7w\2\2\u016e\u016f\7d\2\2\u016f\u0170"+
"\7{\2\2\u0170\u0171\7v\2\2\u0171\u0172\7g\2\2\u0172&\3\2\2\2\u0173\u0174"+
"\7d\2\2\u0174\u0175\7{\2\2\u0175\u0176\7v\2\2\u0176\u0177\7g\2\2\u0177"+
"(\3\2\2\2\u0178\u0179\7w\2\2\u0179\u017a\7y\2\2\u017a\u017b\7q\2\2\u017b"+
"\u017c\7t\2\2\u017c\u017d\7f\2\2\u017d*\3\2\2\2\u017e\u017f\7y\2\2\u017f"+
"\u0180\7q\2\2\u0180\u0181\7t\2\2\u0181\u0182\7f\2\2\u0182,\3\2\2\2\u0183"+
"\u0184\7h\2\2\u0184\u0185\7n\2\2\u0185\u0186\7q\2\2\u0186\u0187\7c\2\2"+
"\u0187\u0188\7v\2\2\u0188.\3\2\2\2\u0189\u018a\7u\2\2\u018a\u018b\7v\2"+
"\2\u018b\u018c\7t\2\2\u018c\60\3\2\2\2\u018d\u018e\7u\2\2\u018e\u018f"+
"\7v\2\2\u018f\u0190\7t\2\2\u0190\u0191\7a\2\2\u0191\u0192\7r\2\2\u0192"+
"\62\3\2\2\2\u0193\u0194\7u\2\2\u0194\u0195\7v\2\2\u0195\u0196\7t\2\2\u0196"+
"\u0197\7a\2\2\u0197\u0198\7u\2\2\u0198\64\3\2\2\2\u0199\u019a\7u\2\2\u019a"+
"\u019b\7v\2\2\u019b\u019c\7t\2\2\u019c\u019d\7a\2\2\u019d\u019e\7r\2\2"+
"\u019e\u019f\7u\2\2\u019f\66\3\2\2\2\u01a0\u01a1\7]\2\2\u01a18\3\2\2\2"+
"\u01a2\u01a3\7_\2\2\u01a3:\3\2\2\2\u01a4\u01a5\7-\2\2\u01a5\u01a6\7?\2"+
"\2\u01a6<\3\2\2\2\u01a7\u01a8\7/\2\2\u01a8\u01a9\7?\2\2\u01a9>\3\2\2\2"+
"\u01aa\u01ab\7\61\2\2\u01ab\u01ac\7?\2\2\u01ac@\3\2\2\2\u01ad\u01ae\7"+
"\61\2\2\u01ae\u01af\7\61\2\2\u01af\u01b0\7?\2\2\u01b0B\3\2\2\2\u01b1\u01b2"+
"\7,\2\2\u01b2\u01b3\7?\2\2\u01b3D\3\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6"+
"\7,\2\2\u01b6\u01b7\7?\2\2\u01b7F\3\2\2\2\u01b8\u01b9\7(\2\2\u01b9\u01ba"+
"\7?\2\2\u01baH\3\2\2\2\u01bb\u01bc\7~\2\2\u01bc\u01bd\7?\2\2\u01bdJ\3"+
"\2\2\2\u01be\u01bf\7`\2\2\u01bf\u01c0\7?\2\2\u01c0L\3\2\2\2\u01c1\u01c2"+
"\7-\2\2\u01c2\u01c3\7-\2\2\u01c3N\3\2\2\2\u01c4\u01c5\7/\2\2\u01c5\u01c6"+
"\7/\2\2\u01c6P\3\2\2\2\u01c7\u01c8\7*\2\2\u01c8R\3\2\2\2\u01c9\u01ca\7"+
"+\2\2\u01caT\3\2\2\2\u01cb\u01cc\7-\2\2\u01ccV\3\2\2\2\u01cd\u01ce\7/"+
"\2\2\u01ceX\3\2\2\2\u01cf\u01d0\7,\2\2\u01d0\u01d1\7,\2\2\u01d1Z\3\2\2"+
"\2\u01d2\u01d3\7,\2\2\u01d3\\\3\2\2\2\u01d4\u01d5\7\61\2\2\u01d5^\3\2"+
"\2\2\u01d6\u01d7\7\61\2\2\u01d7\u01d8\7\61\2\2\u01d8`\3\2\2\2\u01d9\u01da"+
"\7\'\2\2\u01dab\3\2\2\2\u01db\u01dc\7>\2\2\u01dcd\3\2\2\2\u01dd\u01de"+
"\7@\2\2\u01def\3\2\2\2\u01df\u01e0\7>\2\2\u01e0\u01e1\7?\2\2\u01e1h\3"+
"\2\2\2\u01e2\u01e3\7@\2\2\u01e3\u01e4\7?\2\2\u01e4j\3\2\2\2\u01e5\u01e6"+
"\7?\2\2\u01e6\u01e7\7?\2\2\u01e7l\3\2\2\2\u01e8\u01e9\7#\2\2\u01e9\u01ea"+
"\7?\2\2\u01ean\3\2\2\2\u01eb\u01ec\7(\2\2\u01ecp\3\2\2\2\u01ed\u01ee\7"+
"`\2\2\u01eer\3\2\2\2\u01ef\u01f0\7~\2\2\u01f0t\3\2\2\2\u01f1\u01f2\7v"+
"\2\2\u01f2\u01f3\7q\2\2\u01f3v\3\2\2\2\u01f4\u01f5\7u\2\2\u01f5\u01f6"+
"\7v\2\2\u01f6\u01f7\7g\2\2\u01f7\u01f8\7r\2\2\u01f8x\3\2\2\2\u01f9\u01fa"+
"\7c\2\2\u01fa\u01fb\7p\2\2\u01fb\u01fc\7f\2\2\u01fcz\3\2\2\2\u01fd\u01fe"+
"\7q\2\2\u01fe\u01ff\7t\2\2\u01ff|\3\2\2\2\u0200\u0201\7z\2\2\u0201\u0202"+
"\7q\2\2\u0202\u0203\7t\2\2\u0203~\3\2\2\2\u0204\u0205\7p\2\2\u0205\u0206"+
"\7q\2\2\u0206\u0207\7v\2\2\u0207\u0080\3\2\2\2\u0208\u0209\7t\2\2\u0209"+
"\u020a\7g\2\2\u020a\u020b\7v\2\2\u020b\u020c\7w\2\2\u020c\u020d\7t\2\2"+
"\u020d\u020e\7p\2\2\u020e\u0082\3\2\2\2\u020f\u0210\7d\2\2\u0210\u0211"+
"\7t\2\2\u0211\u0212\7g\2\2\u0212\u0213\7c\2\2\u0213\u0214\7m\2\2\u0214"+
"\u0084\3\2\2\2\u0215\u0216\7e\2\2\u0216\u0217\7q\2\2\u0217\u0218\7p\2"+
"\2\u0218\u0219\7v\2\2\u0219\u021a\7k\2\2\u021a\u021b\7p\2\2\u021b\u021c"+
"\7w\2\2\u021c\u021d\7g\2\2\u021d\u0086\3\2\2\2\u021e\u021f\7\60\2\2\u021f"+
"\u0088\3\2\2\2\u0220\u0221\7C\2\2\u0221\u008a\3\2\2\2\u0222\u0223\7Z\2"+
"\2\u0223\u008c\3\2\2\2\u0224\u0225\7[\2\2\u0225\u008e\3\2\2\2\u0226\u0227"+
"\7R\2\2\u0227\u0228\7e\2\2\u0228\u0090\3\2\2\2\u0229\u022a\7R\2\2\u022a"+
"\u022b\7|\2\2\u022b\u0092\3\2\2\2\u022c\u022d\7R\2\2\u022d\u022e\7p\2"+
"\2\u022e\u0094\3\2\2\2\u022f\u0230\7R\2\2\u0230\u0231\7x\2\2\u0231\u0096"+
"\3\2\2\2\u0232\u0233\7\60\2\2\u0233\u0234\7y\2\2\u0234\u0098\3\2\2\2\u0235"+
"\u0236\7v\2\2\u0236\u0237\7t\2\2\u0237\u0238\7w\2\2\u0238\u0239\7g\2\2"+
"\u0239\u009a\3\2\2\2\u023a\u023b\7h\2\2\u023b\u023c\7c\2\2\u023c\u023d"+
"\7n\2\2\u023d\u023e\7u\2\2\u023e\u023f\7g\2\2\u023f\u009c\3\2\2\2\u0240"+
"\u0241\7\'\2\2\u0241\u0242\7c\2\2\u0242\u0243\7u\2\2\u0243\u0244\7o\2"+
"\2\u0244\u009e\3\2\2\2\u0245\u0246\7u\2\2\u0246\u0247\7w\2\2\u0247\u0248"+
"\7d\2\2\u0248\u00a0\3\2\2\2\u0249\u024a\7/\2\2\u024a\u024b\7@\2\2\u024b"+
"\u00a2\3\2\2\2\u024c\u024d\7}\2\2\u024d\u00a4\3\2\2\2\u024e\u024f\7\177"+
"\2\2\u024f\u00a6\3\2\2\2\u0250\u0251\7c\2\2\u0251\u0252\7u\2\2\u0252\u0253"+
"\7o\2\2\u0253\u0254\7u\2\2\u0254\u0255\7w\2\2\u0255\u0256\7d\2\2\u0256"+
"\u00a8\3\2\2\2\u0257\u0258\7e\2\2\u0258\u0259\7n\2\2\u0259\u025a\7q\2"+
"\2\u025a\u025b\7d\2\2\u025b\u025c\7d\2\2\u025c\u025d\7g\2\2\u025d\u025e"+
"\7t\2\2\u025e\u025f\7u\2\2\u025f\u00aa\3\2\2\2\u0260\u0261\7B\2\2\u0261"+
"\u00ac\3\2\2\2\u0262\u0263\7k\2\2\u0263\u0264\7h\2\2\u0264\u00ae\3\2\2"+
"\2\u0265\u0266\7g\2\2\u0266\u0267\7n\2\2\u0267\u0268\7u\2\2\u0268\u0269"+
"\7g\2\2\u0269\u00b0\3\2\2\2\u026a\u026b\7k\2\2\u026b\u026c\7h\2\2\u026c"+
"\u026d\7a\2\2\u026d\u026e\7e\2\2\u026e\u026f\7u\2\2\u026f\u00b2\3\2\2"+
"\2\u0270\u0271\7k\2\2\u0271\u0272\7h\2\2\u0272\u0273\7a\2\2\u0273\u0274"+
"\7e\2\2\u0274\u0275\7e\2\2\u0275\u00b4\3\2\2\2\u0276\u0277\7k\2\2\u0277"+
"\u0278\7h\2\2\u0278\u0279\7a\2\2\u0279\u027a\7g\2\2\u027a\u027b\7s\2\2"+
"\u027b\u00b6\3\2\2\2\u027c\u027d\7k\2\2\u027d\u027e\7h\2\2\u027e\u027f"+
"\7a\2\2\u027f\u0280\7|\2\2\u0280\u00b8\3\2\2\2\u0281\u0282\7k\2\2\u0282"+
"\u0283\7h\2\2\u0283\u0284\7a\2\2\u0284\u0285\7p\2\2\u0285\u0286\7g\2\2"+
"\u0286\u00ba\3\2\2\2\u0287\u0288\7k\2\2\u0288\u0289\7h\2\2\u0289\u028a"+
"\7a\2\2\u028a\u028b\7p\2\2\u028b\u028c\7|\2\2\u028c\u00bc\3\2\2\2\u028d"+
"\u028e\7k\2\2\u028e\u028f\7h\2\2\u028f\u0290\7a\2\2\u0290\u0291\7r\2\2"+
"\u0291\u0292\7n\2\2\u0292\u00be\3\2\2\2\u0293\u0294\7k\2\2\u0294\u0295"+
"\7h\2\2\u0295\u0296\7a\2\2\u0296\u0297\7r\2\2\u0297\u0298\7q\2\2\u0298"+
"\u0299\7u\2\2\u0299\u00c0\3\2\2\2\u029a\u029b\7k\2\2\u029b\u029c\7h\2"+
"\2\u029c\u029d\7a\2\2\u029d\u029e\7o\2\2\u029e\u029f\7k\2\2\u029f\u00c2"+
"\3\2\2\2\u02a0\u02a1\7k\2\2\u02a1\u02a2\7h\2\2\u02a2\u02a3\7a\2\2\u02a3"+
"\u02a4\7p\2\2\u02a4\u02a5\7g\2\2\u02a5\u02a6\7i\2\2\u02a6\u00c4\3\2\2"+
"\2\u02a7\u02a8\7k\2\2\u02a8\u02a9\7h\2\2\u02a9\u02aa\7a\2\2\u02aa\u02ab"+
"\7x\2\2\u02ab\u02ac\7u\2\2\u02ac\u00c6\3\2\2\2\u02ad\u02ae\7k\2\2\u02ae"+
"\u02af\7h\2\2\u02af\u02b0\7a\2\2\u02b0\u02b1\7x\2\2\u02b1\u02b2\7e\2\2"+
"\u02b2\u00c8\3\2\2\2\u02b3\u02b4\7h\2\2\u02b4\u02b5\7q\2\2\u02b5\u02b6"+
"\7t\2\2\u02b6\u00ca\3\2\2\2\u02b7\u02b8\7k\2\2\u02b8\u02b9\7p\2\2\u02b9"+
"\u00cc\3\2\2\2\u02ba\u02bb\7y\2\2\u02bb\u02bc\7j\2\2\u02bc\u02bd\7k\2"+
"\2\u02bd\u02be\7n\2\2\u02be\u02bf\7g\2\2\u02bf\u00ce\3\2\2\2\u02c0\u02c1"+
"\7t\2\2\u02c1\u02c2\7g\2\2\u02c2\u02c3\7r\2\2\u02c3\u02c4\7g\2\2\u02c4"+
"\u02c5\7c\2\2\u02c5\u02c6\7v\2\2\u02c6\u00d0\3\2\2\2\u02c7\u02c8\7w\2"+
"\2\u02c8\u02c9\7p\2\2\u02c9\u02ca\7v\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc"+
"\7n\2\2\u02cc\u00d2\3\2\2\2\u02cd\u02d1\t\2\2\2\u02ce\u02d0\t\3\2\2\u02cf"+
"\u02ce\3\2\2\2\u02d0\u02d3\3\2\2\2\u02d1\u02cf\3\2\2\2\u02d1\u02d2\3\2"+
"\2\2\u02d2\u02d4\3\2\2\2\u02d3\u02d1\3\2\2\2\u02d4\u02d5\5\u00d5k\2\u02d5"+
"\u02d6\3\2\2\2\u02d6\u02d7\bj\2\2\u02d7\u00d4\3\2\2\2\u02d8\u02dc\7=\2"+
"\2\u02d9\u02db\n\2\2\2\u02da\u02d9\3\2\2\2\u02db\u02de\3\2\2\2\u02dc\u02da"+
"\3\2\2\2\u02dc\u02dd\3\2\2\2\u02dd\u02df\3\2\2\2\u02de\u02dc\3\2\2\2\u02df"+
"\u02e0\bk\2\2\u02e0\u00d6\3\2\2\2\u02e1\u02e2\t\3\2\2\u02e2\u02e3\3\2"+
"\2\2\u02e3\u02e4\bl\3\2\u02e4\u00d8\3\2\2\2\u02e5\u02e7\t\2\2\2\u02e6"+
"\u02e5\3\2\2\2\u02e7\u02e8\3\2\2\2\u02e8\u02e6\3\2\2\2\u02e8\u02e9\3\2"+
"\2\2\u02e9\u00da\3\2\2\2\u02ea\u02ee\t\4\2\2\u02eb\u02ed\t\5\2\2\u02ec"+
"\u02eb\3\2\2\2\u02ed\u02f0\3\2\2\2\u02ee\u02ec\3\2\2\2\u02ee\u02ef\3\2"+
"\2\2\u02ef\u00dc\3\2\2\2\u02f0\u02ee\3\2\2\2\u02f1\u02f9\4\62;\2\u02f2"+
"\u02f4\4\63;\2\u02f3\u02f5\4\62;\2\u02f4\u02f3\3\2\2\2\u02f5\u02f6\3\2"+
"\2\2\u02f6\u02f4\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f7\u02f9\3\2\2\2\u02f8"+
"\u02f1\3\2\2\2\u02f8\u02f2\3\2\2\2\u02f9\u00de\3\2\2\2\u02fa\u02fc\7&"+
"\2\2\u02fb\u02fd\t\6\2\2\u02fc\u02fb\3\2\2\2\u02fd\u02fe\3\2\2\2\u02fe"+
"\u02fc\3\2\2\2\u02fe\u02ff\3\2\2\2\u02ff\u00e0\3\2\2\2\u0300\u0302\7\'"+
"\2\2\u0301\u0303\4\62\63\2\u0302\u0301\3\2\2\2\u0303\u0304\3\2\2\2\u0304"+
"\u0302\3\2\2\2\u0304\u0305\3\2\2\2\u0305\u00e2\3\2\2\2\u0306\u030c\5\u00e5"+
"s\2\u0307\u0309\t\7\2\2\u0308\u030a\t\b\2\2\u0309\u0308\3\2\2\2\u0309"+
"\u030a\3\2\2\2\u030a\u030b\3\2\2\2\u030b\u030d\5\u00e5s\2\u030c\u0307"+
"\3\2\2\2\u030c\u030d\3\2\2\2\u030d\u00e4\3\2\2\2\u030e\u0310\4\62;\2\u030f"+
"\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u030f\3\2\2\2\u0311\u0312\3\2"+
"\2\2\u0312\u0319\3\2\2\2\u0313\u0315\7\60\2\2\u0314\u0316\4\62;\2\u0315"+
"\u0314\3\2\2\2\u0316\u0317\3\2\2\2\u0317\u0315\3\2\2\2\u0317\u0318\3\2"+
"\2\2\u0318\u031a\3\2\2\2\u0319\u0313\3\2\2\2\u0319\u031a\3\2\2\2\u031a"+
"\u00e6\3\2\2\2\u031b\u031c\7^\2\2\u031c\u0320\13\2\2\2\u031d\u031e\7^"+
"\2\2\u031e\u0320\5\u00d9m\2\u031f\u031b\3\2\2\2\u031f\u031d\3\2\2\2\u0320"+
"\u00e8\3\2\2\2\u0321\u0326\7$\2\2\u0322\u0325\5\u00e7t\2\u0323\u0325\n"+
"\t\2\2\u0324\u0322\3\2\2\2\u0324\u0323\3\2\2\2\u0325\u0328\3\2\2\2\u0326"+
"\u0324\3\2\2\2\u0326\u0327\3\2\2\2\u0327\u0329\3\2\2\2\u0328\u0326\3\2"+
"\2\2\u0329\u032a\7$\2\2\u032a\u032b\bu\4\2\u032b\u00ea\3\2\2\2\u032c\u032d"+
"\7}\2\2\u032d\u032e\7}\2\2\u032e\u0330\3\2\2\2\u032f\u0331\13\2\2\2\u0330"+
"\u032f\3\2\2\2\u0331\u0332\3\2\2\2\u0332\u0333\3\2\2\2\u0332\u0330\3\2"+
"\2\2\u0333\u0334\3\2\2\2\u0334\u0335\7\177\2\2\u0335\u0336\7\177\2\2\u0336"+
"\u0337\3\2\2\2\u0337\u0338\bv\5\2\u0338\u00ec\3\2\2\2\u0339\u033c\7)\2"+
"\2\u033a\u033d\5\u00e7t\2\u033b\u033d\n\t\2\2\u033c\u033a\3\2\2\2\u033c"+
"\u033b\3\2\2\2\u033d\u033e\3\2\2\2\u033e\u033f\7)\2\2\u033f\u0340\bw\6"+
"\2\u0340\u00ee\3\2\2\2\26\2\u02d1\u02dc\u02e8\u02ee\u02f6\u02f8\u02fc"+
"\u02fe\u0304\u0309\u030c\u0311\u0317\u0319\u031f\u0324\u0326\u0332\u033c"+
"\7\2\3\2\b\2\2\3u\2\3v\3\3w\4";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

File diff suppressed because it is too large Load Diff

View File

@ -130,16 +130,12 @@ class StackVm(private var traceOutputFile: String?) {
canvas?.requestFocusInWindow()
variables = program.variables.toMutableMap()
if("A" in variables || "X" in variables || "Y" in variables ||
"XY" in variables || "AX" in variables ||"AY" in variables)
throw VmExecutionException("program contains variable(s) for the reserved registers A,X,...")
if("A" in variables || "X" in variables || "Y" in variables)
throw VmExecutionException("program contains variable(s) for the reserved registers A/X/Y")
// define the 'registers'
variables["A"] = Value(DataType.UBYTE, 0)
variables["X"] = Value(DataType.UBYTE, 0)
variables["Y"] = Value(DataType.UBYTE, 0)
variables["AX"] = Value(DataType.UWORD, 0)
variables["AY"] = Value(DataType.UWORD, 0)
variables["XY"] = Value(DataType.UWORD, 0)
initMemory(program.memory)
evalstack.clear()

View File

@ -61,8 +61,7 @@ class TestStackVmOpcodes {
fun testInitAndNop() {
val ins = mutableListOf(Instruction(Opcode.NOP))
vm.load(makeProg(ins), null)
assertEquals(6, vm.variables.size)
assertTrue(vm.variables.containsKey("XY"))
assertEquals(3, vm.variables.size)
assertTrue(vm.variables.containsKey("A"))
vm.step(1)
assertThat(vm.callstack, empty())
@ -187,9 +186,8 @@ class TestStackVmOpcodes {
fun testPushVar() {
val ins = mutableListOf(Instruction(Opcode.PUSH_VAR_FLOAT, callLabel = "varname"))
vm.load(makeProg(ins, mapOf("varname" to Value(DataType.FLOAT, 42.999))), null)
assertEquals(7, vm.variables.size)
assertEquals(4, vm.variables.size)
assertTrue(vm.variables.containsKey("varname"))
assertTrue(vm.variables.containsKey("XY"))
assertTrue(vm.variables.containsKey("A"))
assertEquals(Value(DataType.FLOAT, 42.999), vm.variables["varname"])
assertThat(vm.evalstack, empty())
@ -262,7 +260,7 @@ class TestStackVmOpcodes {
"var3" to Value(DataType.FLOAT, 0)
)
vm.load(makeProg(ins, vars), null)
assertEquals(9, vm.variables.size)
assertEquals(6, vm.variables.size)
vm.step(6)
assertEquals(Value(DataType.UBYTE, 123), vm.variables["var1"])
assertEquals(Value(DataType.UWORD, 0x42ea), vm.variables["var2"])
@ -275,7 +273,7 @@ class TestStackVmOpcodes {
"var1" to Value(DataType.UBYTE, 0)
)
vm.load(makeProg(ins2, vars2), null)
assertEquals(7, vm.variables.size)
assertEquals(4, vm.variables.size)
assertFailsWith<VmExecutionException> {
vm.step(2)
}

View File

@ -224,8 +224,7 @@ Variables that represent CPU hardware registers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following variables are reserved
and map directly (read/write) to a CPU hardware register: ``A``, ``X``, ``Y``, ``AX``, ``AY``, ``XY`` (the 2-letter ones
are a pseudo 16-bit 'register' by pairing two 8-bit registers).
and map directly (read/write) to a CPU hardware register: ``A``, ``X``, ``Y``.
Special types: const and memory-mapped
@ -318,10 +317,7 @@ It can be used for example to work with the *address* of a memory mapped variabl
the value it holds. You could take the address of a string as well, but that is redundant:
the compiler already treats those as a value that you manipulate via its address.
For most other types this prefix is not supported and will result in a compilation error.
The resulting value is simply a 16 bit word. Example::
AX = #somevar
The resulting value is simply a 16 bit word.
.. todo::
This is not yet implemented.

View File

@ -303,8 +303,9 @@ Reserved names
The following names are reserved, they have a special meaning::
A X Y ; 6502 hardware registers
AX AY XY ; 16-bit pseudo register pairs
A X Y ; 6502 hardware registers
Pc Pz Pn Pv ; 6502 status register flags
true false ; boolean values 1 and 0
Range expression

View File

@ -120,12 +120,12 @@ Directly Usable Registers
The following 6502 CPU hardware registers are directly usable in program code (and are reserved symbols):
- ``A``, ``X``, ``Y`` the three main cpu registers (8 bits)
- ``AX``, ``AY``, ``XY`` surrogate 16-bit registers: LSB-order (lo/hi) combined register pairs
- the status register (P) carry flag and interrupt disable flag can be written via a couple of special
builtin functions (``set_carry()``, ``clear_carry()``, ``set_irqd()``, ``clear_irqd()``)
However, you must assume that the 3 hardware registers ``A``, ``X`` and ``Y``
are volatile. Their values cannot be depended upon, the compiler will use them as required.
Even simple assignments may require modification of one or more of the registers (for instance, when using arrays).
Subroutine Calling Conventions