adding singed integer datatypes

This commit is contained in:
Irmen de Jong 2018-10-10 09:21:20 +02:00
parent f5261a3425
commit 2f7d03b6ab
23 changed files with 2442 additions and 2023 deletions

View File

@ -103,7 +103,7 @@ constdecl: 'const' varinitializer ;
memoryvardecl: 'memory' varinitializer;
datatype: 'byte' | 'word' | 'float' | 'str' | 'str_p' | 'str_s' | 'str_ps' ;
datatype: 'ubyte' | 'byte' | 'uword' | 'word' | 'float' | 'str' | 'str_p' | 'str_s' | 'str_ps' ;
arrayspec: '[' expression (',' expression)? ']' ;

View File

@ -1,8 +1,8 @@
%option enable_floats
~ irq {
word global_time
byte time_changed
uword global_time
ubyte time_changed
sub irq() {
global_time++
@ -13,8 +13,8 @@
~ main {
const word width = 320
const word height = 200
const uword width = 320
const uword height = 200
; vertices
float[8] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
@ -22,7 +22,7 @@
float[8] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
; edges (msb=from vertex, lsb=to vertex)
word[12] edges = [$0001, $0103, $0302, $0200, $0405, $0507, $0706, $0604, $0004, $0105, $0206, $0307]
uword[12] edges = [$0001, $0103, $0302, $0200, $0405, $0507, $0706, $0604, $0004, $0105, $0206, $0307]
; storage for rotated coordinates
float[len(xcoor)] rotatedx
@ -37,7 +37,7 @@
_vm_gfx_text(8, 6, 1, "Spin")
_vm_gfx_text(29, 11, 1, "to Win !")
for byte i in 0 to width//10 {
for ubyte i in 0 to width//10 {
_vm_gfx_line(i*2+width//2-width//10, 130, i*10.w, 199, 6)
}
@ -68,7 +68,7 @@
float Azy = cosb*sinc
float Azz = cosb*cosc
for byte i in 0 to len(xcoor)-1 {
for ubyte i in 0 to len(xcoor)-1 {
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]
@ -87,18 +87,18 @@
}
; draw all edges of the object
for word edge in edges {
byte e_from = msb(edge)
byte e_to = lsb(edge)
for uword edge in edges {
ubyte e_from = msb(edge)
ubyte e_to = lsb(edge)
_vm_gfx_line(toscreenx(rotatedx[e_from], rotatedz[e_from]), toscreeny(rotatedy[e_from], rotatedz[e_from]),
toscreenx(rotatedx[e_to], rotatedz[e_to]), toscreeny(rotatedy[e_to], rotatedz[e_to]), e_from+e_to)
}
; accentuate the vertices a bit with small boxes
for byte i in 0 to len(xcoor)-1 {
for ubyte i in 0 to len(xcoor)-1 {
word sx = toscreenx(rotatedx[i], rotatedz[i])
word sy = toscreeny(rotatedy[i], rotatedz[i])
byte color=i+2
ubyte color=i+2
_vm_gfx_pixel(sx-1, sy-1, color)
_vm_gfx_pixel(sx, sy-1, color)
_vm_gfx_pixel(sx+1, sy-1, color)

View File

@ -1,26 +1,26 @@
%option enable_floats
~ main {
const word width = 320 // 2
const word height = 256 // 2
const word xoffset = 40
const word yoffset = 30
const uword width = 320 // 2
const uword height = 256 // 2
const uword xoffset = 40
const uword yoffset = 30
sub start() {
_vm_gfx_clearscr(11)
_vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
for byte pixely in yoffset to yoffset+height-1 {
for ubyte pixely in yoffset to yoffset+height-1 {
float yy = flt((pixely-yoffset))/height/3.6+0.4
for word pixelx in xoffset to xoffset+width-1 {
for uword pixelx in xoffset to xoffset+width-1 {
float xx = flt((pixelx-xoffset))/width/3.0+0.2
float xsquared = 0.0
float ysquared = 0.0
float x = 0.0
float y = 0.0
byte iter = 0
ubyte iter = 0
while (iter<32 and xsquared+ysquared<4.0) {
y = x*y*2.0 + yy
@ -42,9 +42,9 @@
~ irq {
memory byte jiffyclockHi = $a0
memory byte jiffyclockMid = $a1
memory byte jiffyclockLo = $a2
memory ubyte jiffyclockHi = $a0
memory ubyte jiffyclockMid = $a1
memory ubyte jiffyclockLo = $a2
sub irq() {
_vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi)

View File

@ -2,7 +2,7 @@
sub start() {
str name = " "
str guess = "000000"
byte secretnumber = rnd() % 100
ubyte secretnumber = rnd() % 100
_vm_write_str("Let's play a number guessing game!\n")
_vm_write_str("Enter your name: ")
@ -11,14 +11,14 @@
_vm_write_str(name)
_vm_write_str(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n")
for byte attempts_left in 10 to 1 step -1 {
for ubyte attempts_left in 10 to 1 step -1 {
_vm_write_str("\nYou have ")
_vm_write_num(attempts_left)
_vm_write_str(" guess")
if attempts_left>1 _vm_write_str("es")
_vm_write_str(" left. What is your next guess? ")
_vm_input_str(guess)
byte guessednumber = str2byte(guess)
ubyte guessednumber = str2byte(guess)
if guessednumber==secretnumber {
_vm_write_str("\nYou guessed it, impressive!\n")
_vm_write_str("Thanks for playing.\n")

View File

@ -2,15 +2,15 @@
~ main {
const word width = 320
const word height = 200
const uword width = 320
const uword height = 200
sub start() {
_vm_gfx_clearscr(0)
float t
byte color
ubyte color
while(1) {
float x = sin(t*1.01) + cos(t*1.1234)
@ -21,10 +21,10 @@
}
}
sub screenx(x: float) -> word {
sub screenx(x: float) -> uword {
return floor(x * flt(width)/4.1) + width // 2
}
sub screeny(y: float) -> word {
sub screeny(y: float) -> uword {
return floor(y * flt(height)/4.1) + height // 2
}
}

View File

@ -17,17 +17,22 @@ import kotlin.math.floor
/**************************** AST Data classes ****************************/
enum class DataType {
UBYTE,
BYTE,
UWORD,
WORD,
FLOAT,
STR,
STR_P,
STR_S,
STR_PS,
ARRAY,
ARRAY_UB,
ARRAY_B,
ARRAY_UW,
ARRAY_W,
ARRAY_F,
MATRIX
MATRIX_UB,
MATRIX_B
}
enum class Register {
@ -63,7 +68,15 @@ enum class BranchCondition {
val IterableDatatypes = setOf(
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX)
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B)
val StringDatatypes = setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
val NumericDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT)
val IntegerDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD)
val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B)
class FatalAstException (override var message: String) : Exception(message)
@ -586,19 +599,22 @@ class VarDecl(val type: VarDeclType,
val datatype = when {
arrayspec == null -> declaredDatatype
arrayspec.y != null -> when (declaredDatatype) {
DataType.BYTE -> DataType.MATRIX
DataType.UBYTE -> DataType.MATRIX_UB
DataType.BYTE -> DataType.MATRIX_B
else -> {
datatypeErrors.add(SyntaxError("matrix can only contain bytes", position))
DataType.BYTE
DataType.UBYTE
}
}
else -> when (declaredDatatype) {
DataType.BYTE -> DataType.ARRAY
DataType.UBYTE -> DataType.ARRAY_UB
DataType.BYTE -> DataType.ARRAY_B
DataType.UWORD -> DataType.ARRAY_UW
DataType.WORD -> DataType.ARRAY_W
DataType.FLOAT -> DataType.ARRAY_F
else -> {
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
DataType.BYTE
DataType.UBYTE
}
}
}
@ -620,7 +636,9 @@ class VarDecl(val type: VarDeclType,
fun asDefaultValueDecl(): VarDecl {
val constValue = when(declaredDatatype) {
DataType.UBYTE -> LiteralValue(DataType.UBYTE, 0, position=position)
DataType.BYTE -> LiteralValue(DataType.BYTE, 0, position=position)
DataType.UWORD -> LiteralValue(DataType.UWORD, wordvalue=0, position=position)
DataType.WORD -> LiteralValue(DataType.WORD, wordvalue=0, position=position)
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue=0.0, position=position)
else -> throw FatalAstException("can only set a default value for a numeric type")
@ -669,8 +687,8 @@ 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.BYTE
Register.AX, Register.AY, Register.XY -> DataType.WORD
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
if(identifier!=null) {
@ -742,21 +760,42 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
"and", "or", "xor",
"<", ">",
"<=", ">=",
"==", "!=" -> DataType.BYTE
"==", "!=" -> DataType.UBYTE
"/" -> {
val rightNum = right.constValue(namespace, heap)?.asNumericValue?.toDouble()
if(rightNum!=null) {
when(leftDt) {
DataType.UBYTE ->
when(rightDt) {
DataType.UBYTE -> DataType.UBYTE
DataType.BYTE -> DataType.BYTE
DataType.UWORD -> if(rightNum >= 256) DataType.UBYTE else DataType.UWORD
DataType.WORD -> {
if(rightNum < 0)
if(rightNum<-256) DataType.UBYTE else DataType.WORD
else
if(rightNum>256) DataType.UBYTE else DataType.UWORD
}
DataType.FLOAT -> if(rightNum <= -256 || rightNum >= 256) DataType.UBYTE else DataType.FLOAT
else -> throw FatalAstException("invalid rightDt $rightDt")
}
DataType.BYTE ->
when(rightDt) {
DataType.BYTE -> DataType.BYTE
DataType.WORD -> if(rightNum <= -256 || rightNum >= 256) DataType.BYTE else DataType.WORD
DataType.UBYTE, DataType.BYTE -> DataType.BYTE
DataType.UWORD, DataType.WORD -> if(rightNum <= -256 || rightNum >= 256) DataType.BYTE else DataType.WORD
DataType.FLOAT -> if(rightNum <= -256 || rightNum >= 256) DataType.BYTE else DataType.FLOAT
else -> throw FatalAstException("invalid rightDt $rightDt")
}
DataType.UWORD ->
when(rightDt) {
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> if(rightNum <= -65536 || rightNum >= 65536) DataType.UWORD else DataType.FLOAT
else -> throw FatalAstException("invalid rightDt $rightDt")
}
DataType.WORD ->
when(rightDt) {
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.UBYTE, DataType.UWORD, DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> if(rightNum <= -65536 || rightNum >= 65536) DataType.WORD else DataType.FLOAT
else -> throw FatalAstException("invalid rightDt $rightDt")
}
@ -771,16 +810,26 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
private fun integerDivisionOpDt(leftDt: DataType, rightDt: DataType): DataType {
return when(leftDt) {
DataType.BYTE -> when(rightDt) {
DataType.UBYTE -> when(rightDt) {
DataType.UBYTE, DataType.UWORD -> DataType.UBYTE
DataType.BYTE, DataType.WORD, DataType.FLOAT -> DataType.BYTE
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.WORD -> when(rightDt) {
DataType.BYTE -> when(rightDt) {
in NumericDatatypes -> DataType.BYTE
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.UWORD -> when(rightDt) {
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
DataType.BYTE, DataType.WORD, DataType.FLOAT -> DataType.WORD
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.WORD -> when(rightDt) {
in NumericDatatypes -> DataType.WORD
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.FLOAT -> when(rightDt) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> DataType.WORD
in NumericDatatypes -> DataType.WORD
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
@ -789,23 +838,35 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
private fun arithmeticOpDt(leftDt: DataType, rightDt: DataType): DataType {
return when(leftDt) {
DataType.BYTE -> when(rightDt) {
DataType.UBYTE -> when(rightDt) {
DataType.UBYTE -> DataType.UBYTE
DataType.BYTE -> DataType.BYTE
DataType.UWORD -> DataType.UWORD
DataType.WORD -> DataType.WORD
DataType.FLOAT -> DataType.FLOAT
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.WORD -> when(rightDt) {
DataType.BYTE -> when(rightDt) {
DataType.BYTE, DataType.UBYTE -> DataType.BYTE
DataType.WORD, DataType.UWORD -> DataType.WORD
DataType.FLOAT -> DataType.FLOAT
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.UWORD -> when(rightDt) {
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> DataType.FLOAT
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.FLOAT -> when(rightDt) {
DataType.BYTE -> DataType.FLOAT
DataType.WORD -> DataType.FLOAT
DataType.WORD -> when(rightDt) {
DataType.BYTE, DataType.UBYTE, DataType.WORD, DataType.UWORD -> DataType.WORD
DataType.FLOAT -> DataType.FLOAT
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
DataType.FLOAT -> when(rightDt) {
in NumericDatatypes -> DataType.FLOAT
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
}
}
@ -829,15 +890,18 @@ class ArrayIndexedExpression(val identifier: IdentifierReference?,
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? {
if (register != null)
return DataType.BYTE
return DataType.UBYTE
val target = identifier?.targetStatement(namespace)
if (target is VarDecl) {
return when (target.datatype) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> null
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.BYTE
DataType.ARRAY, DataType.MATRIX -> DataType.BYTE
in NumericDatatypes -> null
in StringDatatypes -> DataType.UBYTE
DataType.ARRAY_UB, DataType.MATRIX_UB -> DataType.UBYTE
DataType.ARRAY_B, DataType.MATRIX_B -> DataType.BYTE
DataType.ARRAY_UW -> DataType.UWORD
DataType.ARRAY_W -> DataType.WORD
DataType.ARRAY_F -> DataType.FLOAT
else -> throw FatalAstException("invalid dt")
}
}
throw FatalAstException("cannot get indexed element on $target")
@ -860,18 +924,18 @@ class LiteralValue(val type: DataType,
override fun referencesIdentifier(name: String) = arrayvalue?.any { it.referencesIdentifier(name) } ?: false
val isString = type==DataType.STR || type==DataType.STR_P || type==DataType.STR_S || type==DataType.STR_PS
val isNumeric = type==DataType.BYTE || type==DataType.WORD || type==DataType.FLOAT
val isArray = type==DataType.ARRAY || type==DataType.ARRAY_W || type==DataType.ARRAY_F || type==DataType.MATRIX
val isString = type in StringDatatypes
val isNumeric = type in NumericDatatypes
val isArray = type in ArrayDatatypes
companion object {
fun fromBoolean(bool: Boolean, position: Position) =
LiteralValue(DataType.BYTE, bytevalue = if(bool) 1 else 0, position=position)
LiteralValue(DataType.UBYTE, bytevalue = if(bool) 1 else 0, position=position)
fun fromNumber(value: Number, type: DataType, position: Position) : LiteralValue {
return when(type) {
DataType.BYTE -> LiteralValue(type, bytevalue = value.toShort(), position = position)
DataType.WORD -> LiteralValue(type, wordvalue = value.toInt(), position = position)
DataType.UBYTE, DataType.BYTE -> LiteralValue(type, bytevalue = value.toShort(), position = position)
DataType.UWORD, DataType.WORD -> LiteralValue(type, wordvalue = value.toInt(), position = position)
DataType.FLOAT -> LiteralValue(type, floatvalue = value.toDouble(), position = position)
else -> throw FatalAstException("non numeric datatype")
}
@ -882,9 +946,10 @@ class LiteralValue(val type: DataType,
return if(floatval == floor(floatval) && floatval in -32768..65535) {
// the floating point value is actually an integer.
when (floatval) {
// note: we cheat a little here and allow negative integers during expression evaluations
in -128..255 -> LiteralValue(DataType.BYTE, bytevalue = floatval.toShort(), position = position)
in -32768..65535 -> LiteralValue(DataType.WORD, wordvalue = floatval.toInt(), position = position)
in 0..255 -> LiteralValue(DataType.UBYTE, bytevalue=floatval.toShort(), position = position)
in -128..127 -> LiteralValue(DataType.BYTE, bytevalue=floatval.toShort(), position = position)
in 0..65535 -> LiteralValue(DataType.UWORD, wordvalue = floatval.toInt(), position = position)
in -32768..32767 -> LiteralValue(DataType.WORD, wordvalue = floatval.toInt(), position = position)
else -> LiteralValue(DataType.FLOAT, floatvalue = floatval, position = position)
}
} else {
@ -894,9 +959,9 @@ class LiteralValue(val type: DataType,
fun optimalInteger(value: Number, position: Position): LiteralValue {
return when (value) {
// note: we cheat a little here and allow negative integers during expression evaluations
in -128..255 -> LiteralValue(DataType.BYTE, bytevalue = value.toShort(), position = position)
in -32768..65535 -> LiteralValue(DataType.WORD, wordvalue = value.toInt(), position = position)
in 0..255 -> LiteralValue(DataType.UBYTE, bytevalue=value.toShort(), position = position)
in -128..127 -> LiteralValue(DataType.BYTE, bytevalue=value.toShort(), position = position)
in 0..65535 -> LiteralValue(DataType.UWORD, wordvalue = value.toInt(), position = position)
else -> throw FatalAstException("integer overflow: $value")
}
}
@ -904,12 +969,12 @@ class LiteralValue(val type: DataType,
init {
when(type){
DataType.BYTE -> if(bytevalue==null) throw FatalAstException("literal value missing bytevalue")
DataType.WORD -> if(wordvalue==null) throw FatalAstException("literal value missing wordvalue")
DataType.UBYTE, DataType.BYTE -> if(bytevalue==null) throw FatalAstException("literal value missing bytevalue")
DataType.UWORD, DataType.WORD -> if(wordvalue==null) throw FatalAstException("literal value missing wordvalue")
DataType.FLOAT -> if(floatvalue==null) throw FatalAstException("literal value missing floatvalue")
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS ->
in StringDatatypes ->
if(strvalue==null && heapId==null) throw FatalAstException("literal value missing strvalue/heapId")
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX ->
in ArrayDatatypes ->
if(arrayvalue==null && heapId==null) throw FatalAstException("literal value missing arrayvalue/heapId")
}
if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && strvalue==null && heapId==null)
@ -946,18 +1011,20 @@ class LiteralValue(val type: DataType,
override fun toString(): String {
val vstr = when(type) {
DataType.UBYTE -> "ubyte:$bytevalue"
DataType.BYTE -> "byte:$bytevalue"
DataType.UWORD -> "uword:$wordvalue"
DataType.WORD -> "word:$wordvalue"
DataType.FLOAT -> "float:$floatvalue"
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS-> {
if(heapId!=null) "str:#$heapId"
else "str:$strvalue"
}
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F -> {
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> {
if(heapId!=null) "array:#$heapId"
else "array:$arrayvalue"
}
DataType.MATRIX -> {
DataType.MATRIX_UB, DataType.MATRIX_B -> {
if(heapId!=null) "matrix:#$heapId"
else "matrix:$arrayvalue"
}
@ -1020,12 +1087,15 @@ class RangeExpr(var from: IExpression,
val toDt=to.resultingDatatype(namespace, heap)
return when {
fromDt==null || toDt==null -> null
fromDt==DataType.UBYTE && toDt==DataType.UBYTE -> DataType.UBYTE
fromDt==DataType.UWORD && toDt==DataType.UWORD -> DataType.UWORD
fromDt==DataType.STR && toDt==DataType.STR -> DataType.STR
fromDt==DataType.STR_P && toDt==DataType.STR_P -> DataType.STR_P
fromDt==DataType.STR_S && toDt==DataType.STR_S -> DataType.STR_S
fromDt==DataType.STR_PS && toDt==DataType.STR_PS -> DataType.STR_PS
fromDt==DataType.WORD || toDt==DataType.WORD -> DataType.WORD
fromDt==DataType.STR || toDt==DataType.STR -> DataType.STR
fromDt==DataType.STR_P || toDt==DataType.STR_P -> DataType.STR_P
fromDt==DataType.STR_S || toDt==DataType.STR_S -> DataType.STR_S
fromDt==DataType.STR_PS || toDt==DataType.STR_PS -> DataType.STR_PS
else -> DataType.BYTE
fromDt==DataType.BYTE || toDt==DataType.BYTE -> DataType.UBYTE
else -> DataType.UBYTE
}
}
override fun toString(): String {
@ -1090,8 +1160,8 @@ class RegisterExpr(val register: Register, override val position: Position) : IE
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? {
return when(register){
Register.A, Register.X, Register.Y -> DataType.BYTE
Register.AX, Register.AY, Register.XY -> DataType.WORD
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
}
}
@ -1711,29 +1781,31 @@ private fun prog8Parser.DirectiveargContext.toAst() : DirectiveArg =
private fun prog8Parser.IntegerliteralContext.toAst(): NumericLiteral {
fun makeLiteral(text: String, radix: Int, forceWord: Boolean): NumericLiteral {
val integer: Int
var datatype = DataType.BYTE
var datatype = DataType.UBYTE
when (radix) {
10 -> {
integer = text.toInt()
datatype = when(integer) {
in 0..255 -> DataType.BYTE
in 256..65535 -> DataType.WORD
in 0..255 -> DataType.UBYTE
in -128..127 -> DataType.BYTE
in 0..65535 -> DataType.UWORD
in -32768..32767 -> DataType.WORD
else -> DataType.FLOAT
}
}
2 -> {
if(text.length>8)
datatype = DataType.WORD
datatype = DataType.UWORD
integer = text.toInt(2)
}
16 -> {
if(text.length>2)
datatype = DataType.WORD
datatype = DataType.UWORD
integer = text.toInt(16)
}
else -> throw FatalAstException("invalid radix")
}
return NumericLiteral(integer, if(forceWord) DataType.WORD else datatype)
return NumericLiteral(integer, if(forceWord) DataType.UWORD else datatype)
}
val terminal: TerminalNode = children[0] as TerminalNode
val integerPart = this.intpart.text
@ -1758,19 +1830,21 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
val intLit = litval.integerliteral()?.toAst()
when {
intLit!=null -> when(intLit.datatype) {
DataType.UBYTE -> LiteralValue(DataType.UBYTE, bytevalue = intLit.number.toShort(), position = litval.toPosition())
DataType.BYTE -> LiteralValue(DataType.BYTE, bytevalue = intLit.number.toShort(), position = litval.toPosition())
DataType.UWORD -> LiteralValue(DataType.UWORD, wordvalue = intLit.number.toInt(), position = litval.toPosition())
DataType.WORD -> LiteralValue(DataType.WORD, wordvalue = intLit.number.toInt(), position = litval.toPosition())
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue= intLit.number.toDouble(), position = litval.toPosition())
else -> throw FatalAstException("invalid datatype for numeric literal")
}
litval.floatliteral()!=null -> LiteralValue(DataType.FLOAT, floatvalue = litval.floatliteral().toAst(), position = litval.toPosition())
litval.stringliteral()!=null -> LiteralValue(DataType.STR, strvalue = litval.stringliteral().text, position = litval.toPosition())
litval.charliteral()!=null -> LiteralValue(DataType.BYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition())
litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition())
litval.arrayliteral()!=null -> {
val array = litval.arrayliteral()?.toAst()
// byte/word array type difference is not determined here.
// the ConstantFolder takes care of that and converts the type if needed.
LiteralValue(DataType.ARRAY, arrayvalue = array, position = litval.toPosition())
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
}
else -> throw FatalAstException("invalid parsed literal")
}
@ -1796,7 +1870,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
if(funcall!=null) return funcall
if (rangefrom!=null && rangeto!=null) {
val step = rangestep?.toAst() ?: LiteralValue(DataType.BYTE, 1, position = toPosition())
val step = rangestep?.toAst() ?: LiteralValue(DataType.UBYTE, 1, position = toPosition())
return RangeExpr(rangefrom.toAst(), rangeto.toAst(), step, toPosition())
}

View File

@ -115,17 +115,13 @@ class AstChecker(private val namespace: INameScope,
// loop register
when (forLoop.loopRegister) {
Register.A, Register.X, Register.Y -> {
if (iterableDt != DataType.BYTE && iterableDt!=DataType.ARRAY && iterableDt!=DataType.MATRIX &&
iterableDt != DataType.STR && iterableDt != DataType.STR_P &&
iterableDt != DataType.STR_S && iterableDt != DataType.STR_PS)
if (iterableDt != DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt!=DataType.MATRIX_UB && iterableDt !in StringDatatypes)
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
}
Register.AX, Register.AY, Register.XY -> {
if (iterableDt != DataType.WORD && iterableDt != DataType.BYTE &&
iterableDt != DataType.STR && iterableDt != DataType.STR_P &&
iterableDt != DataType.STR_S && iterableDt != DataType.STR_PS &&
iterableDt !=DataType.ARRAY && iterableDt!=DataType.ARRAY_W && iterableDt!=DataType.ARRAY_F && iterableDt!=DataType.MATRIX)
checkResult.add(ExpressionError("register pair can only loop over words", forLoop.position))
if (iterableDt != DataType.UWORD && iterableDt != DataType.UBYTE && iterableDt !in StringDatatypes &&
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW && iterableDt!=DataType.MATRIX_UB)
checkResult.add(ExpressionError("register pair can only loop over bytes or words", forLoop.position))
}
}
} else {
@ -136,17 +132,13 @@ class AstChecker(private val namespace: INameScope,
} else {
when (loopvar.datatype) {
DataType.BYTE -> {
if(iterableDt!=DataType.BYTE && iterableDt!=DataType.ARRAY && iterableDt!=DataType.MATRIX &&
iterableDt != DataType.STR && iterableDt != DataType.STR_P &&
iterableDt != DataType.STR_S && iterableDt != DataType.STR_PS)
DataType.UBYTE -> {
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt!=DataType.MATRIX_UB && iterableDt !in StringDatatypes)
checkResult.add(ExpressionError("byte loop variable can only loop over bytes", forLoop.position))
}
DataType.WORD -> {
if(iterableDt!=DataType.BYTE && iterableDt!=DataType.WORD &&
iterableDt !=DataType.ARRAY && iterableDt!=DataType.ARRAY_W && iterableDt!=DataType.MATRIX &&
iterableDt != DataType.STR && iterableDt != DataType.STR_P &&
iterableDt != DataType.STR_S && iterableDt != DataType.STR_PS)
DataType.UWORD -> {
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.UWORD && iterableDt !in StringDatatypes &&
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW && iterableDt!=DataType.MATRIX_UB)
checkResult.add(ExpressionError("word loop variable can only loop over bytes or words", forLoop.position))
}
// there's no support for a floating-point loop variable
@ -243,25 +235,26 @@ class AstChecker(private val namespace: INameScope,
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.first.type!=DataType.BYTE)
err("parameter '${param.first.name}' should be byte")
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.BYTE || param.first.type==DataType.FLOAT)
err("parameter '${param.first.name}' should be word/str/array")
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/array")
}
}
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.first.value!=DataType.BYTE)
err("return value #${ret.first.index+1} should be byte")
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.BYTE || ret.first.value==DataType.FLOAT)
err("return value #${ret.first.index+1} should be byte")
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/array")
}
}
@ -334,11 +327,8 @@ class AstChecker(private val namespace: INameScope,
}
// it is not possible to assign a new array to something.
when(assignment.value.resultingDatatype(namespace, heap)) {
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX ->
checkResult.add(SyntaxError("it's not possible to assign an array literal value to something, use it as a variable decl initializer instead", assignment.position))
else -> {}
}
if(assignment.value.resultingDatatype(namespace, heap) in ArrayDatatypes)
checkResult.add(SyntaxError("it's not possible to assign an array literal value to something, use it as a variable decl initializer instead", assignment.position))
if(assignment.aug_op!=null) {
// check augmented assignment:
@ -405,17 +395,17 @@ class AstChecker(private val namespace: INameScope,
// CONST can only occur on simple types (byte, word, float)
if(decl.type==VarDeclType.CONST) {
if (decl.datatype != DataType.BYTE && decl.datatype != DataType.WORD && decl.datatype != DataType.FLOAT)
err("const modifier can only be used on simple types (byte, word, float)")
if (decl.datatype !in NumericDatatypes)
err("const modifier can only be used on numeric types (byte, word, float)")
}
when(decl.type) {
VarDeclType.VAR, VarDeclType.CONST -> {
if (decl.value == null) {
when {
decl.datatype == DataType.BYTE || decl.datatype==DataType.WORD || decl.datatype==DataType.FLOAT -> {
decl.datatype in NumericDatatypes -> {
// initialize numeric var with value zero by default.
val litVal = LiteralValue(DataType.BYTE, 0, position = decl.position)
val litVal = LiteralValue(DataType.UBYTE, 0, position = decl.position)
litVal.parent = decl
decl.value = litVal
}
@ -531,15 +521,15 @@ class AstChecker(private val namespace: INameScope,
val lv = super.process(literalValue)
when(lv.type) {
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
in StringDatatypes -> {
if(lv.heapId==null)
throw FatalAstException("string should have been moved to heap at ${lv.position}")
}
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> {
in ArrayDatatypes -> {
if(lv.heapId==null)
throw FatalAstException("array/matrix should have been moved to heap at ${lv.position}")
}
DataType.BYTE, DataType.WORD, DataType.FLOAT -> {}
else -> {}
}
return lv
}
@ -562,7 +552,7 @@ class AstChecker(private val namespace: INameScope,
super.process(range)
val from = range.from.constValue(namespace, heap)
val to = range.to.constValue(namespace, heap)
val stepLv = range.step.constValue(namespace, heap) ?: LiteralValue(DataType.BYTE, 1, position = range.position)
val stepLv = range.step.constValue(namespace, heap) ?: LiteralValue(DataType.UBYTE, 1, position = range.position)
if (stepLv.asIntegerValue == null || stepLv.asIntegerValue == 0) {
err("range step must be an integer != 0")
return range
@ -651,7 +641,7 @@ class AstChecker(private val namespace: INameScope,
} else {
if(target !is VarDecl || target.type==VarDeclType.CONST) {
checkResult.add(SyntaxError("can only increment or decrement a variable", postIncrDecr.position))
} else if(target.datatype!=DataType.FLOAT && target.datatype!=DataType.WORD && target.datatype!=DataType.BYTE) {
} else if(target.datatype !in NumericDatatypes) {
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word variable", postIncrDecr.position))
}
}
@ -667,7 +657,7 @@ class AstChecker(private val namespace: INameScope,
}
else {
val dt = (target as VarDecl).datatype
if(dt!=DataType.ARRAY && dt!=DataType.ARRAY_W && dt!=DataType.ARRAY_F)
if(dt !in NumericDatatypes)
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
}
}
@ -680,7 +670,7 @@ class AstChecker(private val namespace: INameScope,
if(reg==null) {
val target = arrayIndexedExpression.identifier!!.targetStatement(namespace)
if(target is VarDecl) {
if(target.datatype==DataType.BYTE || target.datatype==DataType.WORD || target.datatype==DataType.FLOAT)
if(target.datatype !in IterableDatatypes)
checkResult.add(SyntaxError("array indexing requires an iterable variable", arrayIndexedExpression.position))
val arraysize = target.arrayspec?.size()
if(arraysize!=null) {
@ -720,14 +710,11 @@ class AstChecker(private val namespace: INameScope,
}
when(targetDt) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> {
in NumericDatatypes -> {
checkResult.add(SyntaxError("can't assign a range to a scalar type", range.position))
return false
}
DataType.STR,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> {
in StringDatatypes -> {
// range check bytes (chars)
if(!from.isString || !to.isString) {
checkResult.add(ExpressionError("range for string must have single characters from and to values", range.position))
@ -740,7 +727,7 @@ class AstChecker(private val namespace: INameScope,
}
return true
}
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> {
in ArrayDatatypes -> {
// range and length check bytes
val expectedSize = arrayspec!!.size()
val rangeSize=range.size()
@ -750,6 +737,7 @@ class AstChecker(private val namespace: INameScope,
}
return true
}
else -> throw FatalAstException("invalid targetDt")
}
}
@ -761,15 +749,15 @@ class AstChecker(private val namespace: INameScope,
when (targetDt) {
DataType.FLOAT -> {
val number = when(value.type) {
DataType.BYTE -> value.bytevalue!!.toDouble()
DataType.WORD -> value.wordvalue!!.toDouble()
DataType.UBYTE, DataType.BYTE -> value.bytevalue!!.toDouble()
DataType.UWORD, DataType.WORD -> value.wordvalue!!.toDouble()
DataType.FLOAT -> value.floatvalue!!
else -> return err("numeric value expected")
}
if (number > 1.7014118345e+38 || number < -1.7014118345e+38)
return err("value '$number' out of range for MFLPT format")
}
DataType.BYTE -> {
DataType.UBYTE -> {
val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("unsigned byte value expected instead of float; possible loss of precision")
else
@ -777,7 +765,15 @@ class AstChecker(private val namespace: INameScope,
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
}
DataType.WORD -> {
DataType.BYTE -> {
val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("byte value expected instead of float; possible loss of precision")
else
err("byte value expected")
if (number < -128 || number > 127)
return err("value '$number' out of range for byte")
}
DataType.UWORD -> {
val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("unsigned word value expected instead of float; possible loss of precision")
else
@ -785,6 +781,14 @@ class AstChecker(private val namespace: INameScope,
if (number < 0 || number > 65535)
return err("value '$number' out of range for unsigned word")
}
DataType.WORD -> {
val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("word value expected instead of float; possible loss of precision")
else
err("word value expected")
if (number < -32768 || number > 32767)
return err("value '$number' out of range for word")
}
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
if(!value.isString)
return err("string value expected")
@ -792,9 +796,9 @@ class AstChecker(private val namespace: INameScope,
if (str.isEmpty() || str.length > 255)
return err("string length must be 1 to 255")
}
DataType.ARRAY -> {
DataType.ARRAY_UB, DataType.ARRAY_B -> {
// value may be either a single byte, or a byte array (of all constant values)
if(value.type==DataType.ARRAY) {
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_B) {
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
val arraySpecSize = arrayspec.size()
if(arraySpecSize!=null && arraySpecSize>0) {
@ -805,20 +809,29 @@ class AstChecker(private val namespace: INameScope,
if (arraySize != expectedSize)
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
}
} else if(value.type==DataType.ARRAY_W) {
} else if(value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_W) {
return err("initialization value must be an array of bytes")
} else {
val number = value.bytevalue ?: return if (value.floatvalue!=null)
err("unsigned byte value expected instead of float; possible loss of precision")
else
err("unsigned byte value expected")
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
if(targetDt==DataType.ARRAY_UB) {
val number = value.bytevalue ?: return if (value.floatvalue != null)
err("unsigned byte value expected instead of float; possible loss of precision")
else
err("unsigned byte value expected")
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
} else {
val number = value.bytevalue ?: return if (value.floatvalue != null)
err("byte value expected instead of float; possible loss of precision")
else
err("byte value expected")
if (number < -128 || number > 127)
return err("value '$number' out of range for byte")
}
}
}
DataType.ARRAY_W -> {
DataType.ARRAY_UW, DataType.ARRAY_W -> {
// value may be either a single word, or a word array
if(value.type==DataType.ARRAY || value.type==DataType.ARRAY_W) {
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_B || value.type==DataType.ARRAY_W) {
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
val arraySpecSize = arrayspec.size()
if(arraySpecSize!=null && arraySpecSize>0) {
@ -831,17 +844,26 @@ class AstChecker(private val namespace: INameScope,
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
}
} else {
val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("unsigned byte or word value expected instead of float; possible loss of precision")
else
err("unsigned byte or word value expected")
if (number < 0 || number > 65535)
return err("value '$number' out of range for unsigned word")
if(targetDt==DataType.ARRAY_UW) {
val number = value.asIntegerValue ?: return if (value.floatvalue != null)
err("unsigned byte or word value expected instead of float; possible loss of precision")
else
err("unsigned byte or word value expected")
if (number < 0 || number > 65535)
return err("value '$number' out of range for unsigned word")
} else {
val number = value.asIntegerValue ?: return if (value.floatvalue != null)
err("byte or word value expected instead of float; possible loss of precision")
else
err("byte or word value expected")
if (number < -32768 || number > 32767)
return err("value '$number' out of range for word")
}
}
}
DataType.ARRAY_F -> {
// value may be either a single float, or a float array
if(value.type==DataType.ARRAY || value.type==DataType.ARRAY_W || value.type==DataType.ARRAY_F) {
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_F) {
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
val arraySpecSize = arrayspec.size()
if(arraySpecSize!=null && arraySpecSize>0) {
@ -861,9 +883,9 @@ class AstChecker(private val namespace: INameScope,
return err("value '$number' out of range for mfplt5 floating point")
}
}
DataType.MATRIX -> {
DataType.MATRIX_UB, DataType.MATRIX_B -> {
// value can only be a single byte, or a byte array (which represents the matrix)
if(value.type==DataType.ARRAY || value.type==DataType.MATRIX) {
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_B || value.type==DataType.MATRIX_UB || value.type==DataType.MATRIX_B) {
val arraySpecSize = arrayspec.size()
if(arraySpecSize!=null && arraySpecSize>0) {
val constX = arrayspec.x.constValue(namespace, heap)
@ -876,10 +898,17 @@ class AstChecker(private val namespace: INameScope,
return err("initializer matrix size mismatch (expecting $expectedSize, got ${matrix.size} elements)")
}
} else {
val number = value.bytevalue
?: return err("unsigned byte value expected")
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
if(targetDt==DataType.MATRIX_UB) {
val number = value.bytevalue
?: return err("unsigned byte value expected")
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
} else {
val number = value.bytevalue
?: return err("byte value expected")
if (number < -128 || number > 127)
return err("value '$number' out of range for byte")
}
}
}
}
@ -896,8 +925,10 @@ class AstChecker(private val namespace: INameScope,
val result = when(targetDatatype) {
DataType.BYTE -> sourceDatatype==DataType.BYTE
DataType.UBYTE -> sourceDatatype==DataType.UBYTE
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD
DataType.FLOAT -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD || sourceDatatype==DataType.FLOAT
DataType.UWORD -> sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.UWORD
DataType.FLOAT -> sourceDatatype in NumericDatatypes
DataType.STR -> sourceDatatype==DataType.STR
DataType.STR_S -> sourceDatatype==DataType.STR_S
DataType.STR_P -> sourceDatatype==DataType.STR_P
@ -908,9 +939,9 @@ class AstChecker(private val namespace: INameScope,
if(result)
return true
if(sourceDatatype==DataType.WORD && targetDatatype==DataType.BYTE)
if((sourceDatatype==DataType.UWORD || sourceDatatype==DataType.WORD) && (targetDatatype==DataType.UBYTE || targetDatatype==DataType.BYTE))
checkResult.add(ExpressionError("cannot assign word to byte, use msb() or lsb()?", position))
else if(sourceDatatype==DataType.FLOAT && (targetDatatype==DataType.BYTE || targetDatatype==DataType.WORD))
else if(sourceDatatype==DataType.FLOAT && targetDatatype in IntegerDatatypes)
checkResult.add(ExpressionError("cannot assign float to ${targetDatatype.toString().toLowerCase()}; possible loss of precision. Suggestion: round the value or revert to byte/word arithmetic", position))
else
checkResult.add(ExpressionError("cannot assign ${sourceDatatype.toString().toLowerCase()} to ${targetDatatype.toString().toLowerCase()}", position))

View File

@ -125,7 +125,7 @@ class AstIdentifiersChecker : IAstProcessor {
val loopVar = forLoop.loopVar!!
val varName = loopVar.nameInSource.last()
when (forLoop.decltype) {
DataType.BYTE, DataType.WORD -> {
DataType.UBYTE, DataType.UWORD -> {
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(loopVar.nameInSource, forLoop.body.statements.first())
if(existing==null) {
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, loopVar.position)

View File

@ -100,7 +100,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
// for variables that are not on the heap (so: byte, word, float),
// replace the var decl with an assignment and add a new vardecl with the default constant value.
if(decl.datatype == DataType.BYTE || decl.datatype==DataType.WORD || decl.datatype==DataType.FLOAT) {
if(decl.datatype in NumericDatatypes) {
val scope = decl.definingScope()
if(scope !in vardeclsToAdd)
vardeclsToAdd[scope] = mutableListOf()

View File

@ -164,26 +164,26 @@ class StackVmProgram(val name: String, val heap: HeapValues) {
instructions.asSequence().withIndex().windowed(2).toList().forEach {
when(it[0].value.opcode) {
Opcode.PUSH_VAR ->
if(it[1].value.opcode==Opcode.POP_VAR) {
Opcode.PUSH_VAR_BYTE ->
if(it[1].value.opcode==Opcode.POP_VAR_BYTE) {
if(it[0].value.callLabel!=it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR, null, it[0].value.callLabel, it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_BYTE, null, it[0].value.callLabel, it[1].value.callLabel)
else
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.PUSH_VAR_W ->
if(it[1].value.opcode==Opcode.POP_VAR_W) {
Opcode.PUSH_VAR_WORD ->
if(it[1].value.opcode==Opcode.POP_VAR_WORD) {
if(it[0].value.callLabel!=it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_W, null, it[0].value.callLabel, it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_WORD, null, it[0].value.callLabel, it[1].value.callLabel)
else
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.PUSH_VAR_F ->
if(it[1].value.opcode==Opcode.POP_VAR_F) {
Opcode.PUSH_VAR_FLOAT ->
if(it[1].value.opcode==Opcode.POP_VAR_FLOAT) {
if(it[0].value.callLabel!=it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_F, null, it[0].value.callLabel, it[1].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_FLOAT, null, it[0].value.callLabel, it[1].value.callLabel)
else
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
@ -208,9 +208,9 @@ class StackVmProgram(val name: String, val heap: HeapValues) {
Opcode.MSB2WORD,
Opcode.B2FLOAT,
Opcode.W2FLOAT,
Opcode.DISCARD,
Opcode.DISCARD_W,
Opcode.DISCARD_F
Opcode.DISCARD_BYTE,
Opcode.DISCARD_WORD,
Opcode.DISCARD_FLOAT
)
val instructionsToReplace = mutableMapOf<Int, Instruction>()
@ -218,40 +218,40 @@ class StackVmProgram(val name: String, val heap: HeapValues) {
this.instructions.asSequence().withIndex().windowed(2).toList().forEach {
if(it[1].value.opcode in typeConversionOpcodes) {
when(it[0].value.opcode) {
Opcode.PUSH -> when (it[1].value.opcode) {
Opcode.PUSH_BYTE -> when (it[1].value.opcode) {
Opcode.LSB -> instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
Opcode.MSB -> throw CompilerException("msb of a byte")
Opcode.B2WORD -> {
val ins = Instruction(Opcode.PUSH_W, Value(DataType.WORD, it[0].value.arg!!.integerValue()))
val ins = Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, it[0].value.arg!!.integerValue()))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.MSB2WORD -> {
val ins = Instruction(Opcode.PUSH_W, Value(DataType.WORD, 256 * it[0].value.arg!!.integerValue()))
val ins = Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 256 * it[0].value.arg!!.integerValue()))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.B2FLOAT -> {
val ins = Instruction(Opcode.PUSH_F, Value(DataType.FLOAT, it[0].value.arg!!.integerValue().toDouble()))
val ins = Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, it[0].value.arg!!.integerValue().toDouble()))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.W2FLOAT -> throw CompilerException("invalid conversion following a byte")
Opcode.DISCARD -> {
Opcode.DISCARD_BYTE -> {
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.DISCARD_W, Opcode.DISCARD_F -> throw CompilerException("invalid discard type following a byte")
Opcode.DISCARD_WORD, Opcode.DISCARD_FLOAT -> throw CompilerException("invalid discard type following a byte")
else -> {}
}
Opcode.PUSH_W -> when (it[1].value.opcode) {
Opcode.PUSH_WORD -> when (it[1].value.opcode) {
Opcode.LSB -> {
val ins = Instruction(Opcode.PUSH, Value(DataType.BYTE, it[0].value.arg!!.integerValue() and 255))
val ins = Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, it[0].value.arg!!.integerValue() and 255))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.MSB -> {
val ins = Instruction(Opcode.PUSH, Value(DataType.BYTE, it[0].value.arg!!.integerValue() ushr 8 and 255))
val ins = Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, it[0].value.arg!!.integerValue() ushr 8 and 255))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
@ -259,38 +259,38 @@ class StackVmProgram(val name: String, val heap: HeapValues) {
Opcode.MSB2WORD,
Opcode.B2FLOAT -> throw CompilerException("invalid conversion following a word")
Opcode.W2FLOAT -> {
val ins = Instruction(Opcode.PUSH_F, Value(DataType.FLOAT, it[0].value.arg!!.integerValue().toDouble()))
val ins = Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, it[0].value.arg!!.integerValue().toDouble()))
instructionsToReplace[it[0].index] = ins
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.DISCARD_W -> {
Opcode.DISCARD_WORD -> {
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.DISCARD, Opcode.DISCARD_F -> throw CompilerException("invalid discard type following a byte")
Opcode.DISCARD_BYTE, Opcode.DISCARD_FLOAT -> throw CompilerException("invalid discard type following a byte")
else -> {}
}
Opcode.PUSH_F -> when (it[1].value.opcode) {
Opcode.PUSH_FLOAT -> when (it[1].value.opcode) {
Opcode.LSB,
Opcode.MSB,
Opcode.B2WORD,
Opcode.MSB2WORD,
Opcode.B2FLOAT,
Opcode.W2FLOAT -> throw CompilerException("invalid conversion following a float")
Opcode.DISCARD_F -> {
Opcode.DISCARD_FLOAT -> {
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
Opcode.DISCARD, Opcode.DISCARD_W -> throw CompilerException("invalid discard type following a float")
Opcode.DISCARD_BYTE, Opcode.DISCARD_WORD -> throw CompilerException("invalid discard type following a float")
else -> {}
}
Opcode.PUSH_VAR_F,
Opcode.PUSH_VAR_W,
Opcode.PUSH_VAR,
Opcode.PUSH_MEM,
Opcode.PUSH_MEM_W,
Opcode.PUSH_MEM_F -> when (it[1].value.opcode) {
Opcode.DISCARD_F, Opcode.DISCARD_W, Opcode.DISCARD -> {
Opcode.PUSH_VAR_FLOAT,
Opcode.PUSH_VAR_WORD,
Opcode.PUSH_VAR_BYTE,
Opcode.PUSH_MEM_BYTE,
Opcode.PUSH_MEM_WORD,
Opcode.PUSH_MEM_FLOAT -> when (it[1].value.opcode) {
Opcode.DISCARD_FLOAT, Opcode.DISCARD_WORD, Opcode.DISCARD_BYTE -> {
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
@ -308,14 +308,15 @@ class StackVmProgram(val name: String, val heap: HeapValues) {
fun blockvar(scopedname: String, decl: VarDecl) {
val value = when(decl.datatype) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> Value(decl.datatype, (decl.value as LiteralValue).asNumericValue!!)
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> Value(decl.datatype, (decl.value as LiteralValue).asNumericValue!!)
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
val litval = (decl.value as LiteralValue)
if(litval.heapId==null)
throw CompilerException("string should already be in the heap")
Value(decl.datatype, litval.heapId)
}
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> {
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B, DataType.MATRIX_UB,
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F -> {
val litval = (decl.value as LiteralValue)
if(litval.heapId==null)
throw CompilerException("array/matrix should already be in the heap")
@ -471,17 +472,20 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun opcodePush(dt: DataType): Opcode {
return when (dt) {
DataType.BYTE -> Opcode.PUSH
DataType.WORD -> Opcode.PUSH_W
DataType.FLOAT -> Opcode.PUSH_F
DataType.UBYTE, DataType.BYTE -> Opcode.PUSH_BYTE
DataType.UWORD, DataType.WORD -> Opcode.PUSH_WORD
DataType.FLOAT -> Opcode.PUSH_FLOAT
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> Opcode.PUSH_W
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.PUSH_WORD
}
}
private fun opcodeAdd(dt: DataType): Opcode {
return when (dt) {
DataType.UBYTE -> Opcode.ADD_UB
DataType.BYTE -> Opcode.ADD_B
DataType.UWORD -> Opcode.ADD_UW
DataType.WORD -> Opcode.ADD_W
DataType.FLOAT -> Opcode.ADD_F
else -> throw CompilerException("invalid dt $dt")
@ -490,7 +494,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun opcodeSub(dt: DataType): Opcode {
return when (dt) {
DataType.UBYTE -> Opcode.SUB_UB
DataType.BYTE -> Opcode.SUB_B
DataType.UWORD -> Opcode.SUB_UW
DataType.WORD -> Opcode.SUB_W
DataType.FLOAT -> Opcode.SUB_F
else -> throw CompilerException("invalid dt $dt")
@ -499,85 +505,90 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun opcodePushvar(dt: DataType): Opcode {
return when (dt) {
DataType.BYTE -> Opcode.PUSH_VAR
DataType.WORD -> Opcode.PUSH_VAR_W
DataType.FLOAT -> Opcode.PUSH_VAR_F
DataType.UBYTE, DataType.BYTE -> Opcode.PUSH_VAR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.PUSH_VAR_WORD
DataType.FLOAT -> Opcode.PUSH_VAR_FLOAT
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> Opcode.PUSH_VAR_W
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.PUSH_VAR_WORD
}
}
private fun opcodePushvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.PUSH_VAR
Register.AX, Register.AY, Register.XY -> Opcode.PUSH_VAR_W
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
Register.AX, Register.AY, Register.XY -> Opcode.POP_VAR_W
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 -> Opcode.READ_INDEXED_VAR
DataType.ARRAY_W -> Opcode.READ_INDEXED_VAR_W
DataType.ARRAY_F -> Opcode.READ_INDEXED_VAR_F
DataType.MATRIX -> Opcode.READ_INDEXED_VAR
DataType.ARRAY_UB, DataType.ARRAY_B -> Opcode.READ_INDEXED_VAR_BYTE
DataType.ARRAY_UW, DataType.ARRAY_W -> Opcode.READ_INDEXED_VAR_WORD
DataType.ARRAY_F -> Opcode.READ_INDEXED_VAR_FLOAT
DataType.MATRIX_UB, DataType.MATRIX_B -> Opcode.READ_INDEXED_VAR_BYTE
else -> throw CompilerException("invalid dt for indexed $dt")
}
}
private fun opcodeWriteindexedvar(dt: DataType): Opcode {
return when (dt) {
DataType.ARRAY -> Opcode.WRITE_INDEXED_VAR
DataType.ARRAY_W -> Opcode.WRITE_INDEXED_VAR_W
DataType.ARRAY_F -> Opcode.WRITE_INDEXED_VAR_F
DataType.MATRIX -> Opcode.WRITE_INDEXED_VAR
DataType.ARRAY_UB, DataType.ARRAY_B -> Opcode.WRITE_INDEXED_VAR_BYTE
DataType.ARRAY_UW, DataType.ARRAY_W -> Opcode.WRITE_INDEXED_VAR_WORD
DataType.ARRAY_F -> Opcode.WRITE_INDEXED_VAR_FLOAT
DataType.MATRIX_UB, DataType.MATRIX_B -> Opcode.WRITE_INDEXED_VAR_BYTE
else -> throw CompilerException("invalid dt for indexed $dt")
}
}
private fun opcodeDiscard(dt: DataType): Opcode {
return when(dt) {
DataType.BYTE -> Opcode.DISCARD
DataType.WORD -> Opcode.DISCARD_W
DataType.FLOAT -> Opcode.DISCARD_F
DataType.UBYTE, DataType.BYTE -> Opcode.DISCARD_BYTE
DataType.UWORD, DataType.WORD -> Opcode.DISCARD_WORD
DataType.FLOAT -> Opcode.DISCARD_FLOAT
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> Opcode.DISCARD_W
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.DISCARD_WORD
}
}
private fun opcodePopvar(dt: DataType): Opcode {
return when (dt) {
DataType.BYTE -> Opcode.POP_VAR
DataType.WORD -> Opcode.POP_VAR_W
DataType.FLOAT -> Opcode.POP_VAR_F
DataType.UBYTE, DataType.BYTE -> Opcode.POP_VAR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.POP_VAR_WORD
DataType.FLOAT -> Opcode.POP_VAR_FLOAT
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> Opcode.POP_VAR_W
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.POP_VAR_WORD
}
}
private fun opcodeDecvar(reg: Register): Opcode {
return when(reg) {
Register.A, Register.X, Register.Y -> Opcode.DEC_VAR
Register.AX, Register.AY, Register.XY -> Opcode.DEC_VAR_W
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
Register.AX, Register.AY, Register.XY -> Opcode.INC_VAR_W
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.BYTE -> Opcode.DEC_VAR
DataType.UBYTE -> Opcode.DEC_VAR_UB
DataType.BYTE -> Opcode.DEC_VAR_B
DataType.UWORD -> Opcode.DEC_VAR_UW
DataType.WORD -> Opcode.DEC_VAR_W
else -> throw CompilerException("can't dec type $dt")
}
@ -585,7 +596,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun opcodeIncvar(dt: DataType): Opcode {
return when(dt) {
DataType.BYTE -> Opcode.INC_VAR
DataType.UBYTE -> Opcode.INC_VAR_UB
DataType.BYTE -> Opcode.INC_VAR_B
DataType.UWORD -> Opcode.INC_VAR_UW
DataType.WORD -> Opcode.INC_VAR_W
else -> throw CompilerException("can't inc type $dt")
}
@ -706,10 +719,34 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val floatWarning = "byte or word value implicitly converted to float. Suggestion: use explicit flt() conversion, a float number, or revert to byte/word arithmetic"
return when(leftDt) {
DataType.UBYTE -> {
when(rightDt) {
DataType.UBYTE -> DataType.UBYTE
DataType.BYTE -> DataType.BYTE
DataType.UWORD -> DataType.UWORD
DataType.WORD -> DataType.WORD
DataType.FLOAT -> {
printWarning(floatWarning, leftpos)
DataType.FLOAT
}
else -> throw CompilerException("non-numeric datatype $rightDt")
}
}
DataType.BYTE -> {
when(rightDt) {
DataType.BYTE -> DataType.BYTE
DataType.WORD -> DataType.WORD
DataType.UBYTE, DataType.BYTE -> DataType.BYTE
DataType.UWORD, DataType.WORD -> DataType.WORD
DataType.FLOAT -> {
printWarning(floatWarning, leftpos)
DataType.FLOAT
}
else -> throw CompilerException("non-numeric datatype $rightDt")
}
}
DataType.UWORD -> {
when(rightDt) {
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> {
printWarning(floatWarning, leftpos)
DataType.FLOAT
@ -719,7 +756,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
DataType.WORD -> {
when(rightDt) {
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.UBYTE, DataType.UWORD, DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> {
printWarning(floatWarning, leftpos)
DataType.FLOAT
@ -780,18 +817,19 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
else -> {
val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr")
when(lv.type) {
DataType.BYTE -> stackvmProg.instr(Opcode.PUSH, Value(DataType.BYTE, lv.bytevalue!!))
DataType.WORD -> stackvmProg.instr(Opcode.PUSH_W, Value(DataType.WORD, lv.wordvalue!!))
DataType.FLOAT -> stackvmProg.instr(Opcode.PUSH_F, Value(DataType.FLOAT, lv.floatvalue!!))
DataType.UBYTE, DataType.BYTE -> stackvmProg.instr(Opcode.PUSH_BYTE, Value(DataType.UBYTE, lv.bytevalue!!))
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.PUSH_WORD, Value(DataType.UWORD, lv.wordvalue!!))
DataType.FLOAT -> stackvmProg.instr(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, lv.floatvalue!!))
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
if(lv.heapId==null)
throw CompilerException("string should have been moved into heap ${lv.position}")
stackvmProg.instr(Opcode.PUSH_W, Value(lv.type, lv.heapId))
stackvmProg.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
}
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> {
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> {
if(lv.heapId==null)
throw CompilerException("array/matrix should have been moved into heap ${lv.position}")
stackvmProg.instr(Opcode.PUSH_W, Value(lv.type, lv.heapId))
stackvmProg.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
}
}
}
@ -802,25 +840,32 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
// only WIDENS a type, never NARROWS
if(givenDt==targetDt)
return
if(givenDt!=DataType.BYTE && givenDt!=DataType.WORD && givenDt!=DataType.FLOAT)
throw CompilerException("converting a non-numeric $givenDt")
if(targetDt!=DataType.BYTE && targetDt!=DataType.WORD && targetDt!=DataType.FLOAT)
throw CompilerException("converting to non-numeric $targetDt")
if(givenDt !in NumericDatatypes)
throw CompilerException("converting non-numeric $givenDt")
if(targetDt !in NumericDatatypes)
throw CompilerException("converting $givenDt to non-numeric $targetDt")
when(givenDt) {
DataType.BYTE -> when(targetDt) {
DataType.WORD -> stackvmProg.instr(Opcode.B2WORD)
DataType.UBYTE -> when(targetDt) {
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.UB2UWORD)
DataType.FLOAT -> stackvmProg.instr(Opcode.B2FLOAT)
else -> {}
}
DataType.BYTE -> when(targetDt) {
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.B2WORD)
DataType.FLOAT -> stackvmProg.instr(Opcode.B2FLOAT)
else -> {}
}
DataType.UWORD -> when(targetDt) {
DataType.UBYTE, DataType.BYTE -> throw CompilerException("narrowing type")
DataType.FLOAT -> stackvmProg.instr(Opcode.UW2FLOAT)
else -> {}
}
DataType.WORD -> when(targetDt) {
DataType.BYTE -> throw CompilerException("narrowing type")
DataType.UBYTE, DataType.BYTE -> throw CompilerException("narrowing type")
DataType.FLOAT -> stackvmProg.instr(Opcode.W2FLOAT)
else -> {}
}
DataType.FLOAT -> when(targetDt) {
DataType.BYTE, DataType.WORD -> throw CompilerException("narrowing type")
else -> {}
}
DataType.FLOAT -> if(targetDt in IntegerDatatypes) throw CompilerException("narrowing type")
else -> {}
}
}
@ -838,9 +883,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
throw CompilerException("const ref should have been const-folded away")
VarDeclType.MEMORY -> {
when (target.datatype) {
DataType.BYTE -> stackvmProg.instr(Opcode.PUSH_MEM, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue!!))
DataType.WORD -> stackvmProg.instr(Opcode.PUSH_MEM_W, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue!!))
DataType.FLOAT -> stackvmProg.instr(Opcode.PUSH_MEM_F, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue!!))
DataType.UBYTE -> stackvmProg.instr(Opcode.PUSH_MEM_BYTE, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
DataType.UWORD -> stackvmProg.instr(Opcode.PUSH_MEM_WORD, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
DataType.FLOAT -> stackvmProg.instr(Opcode.PUSH_MEM_FLOAT, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!))
else -> TODO("invalid datatype for memory variable expression: $target")
}
}
@ -884,8 +929,8 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
// 1 argument, type determines the exact opcode to use
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.B2FLOAT)
DataType.WORD -> stackvmProg.instr(Opcode.W2FLOAT)
DataType.UBYTE -> stackvmProg.instr(Opcode.B2FLOAT)
DataType.UWORD -> stackvmProg.instr(Opcode.W2FLOAT)
DataType.FLOAT -> stackvmProg.instr(Opcode.NOP)
else -> throw CompilerException("wrong datatype for flt()")
}
@ -897,48 +942,48 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"lsl" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.SHL)
DataType.WORD -> stackvmProg.instr(Opcode.SHL_W)
DataType.UBYTE -> stackvmProg.instr(Opcode.SHL_BYTE)
DataType.UWORD -> stackvmProg.instr(Opcode.SHL_WORD)
else -> throw CompilerException("wrong datatype")
}
}
"lsr" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.SHR)
DataType.WORD -> stackvmProg.instr(Opcode.SHR_W)
DataType.UBYTE -> stackvmProg.instr(Opcode.SHR_BYTE)
DataType.UWORD -> stackvmProg.instr(Opcode.SHR_WORD)
else -> throw CompilerException("wrong datatype")
}
}
"rol" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROL)
DataType.WORD -> stackvmProg.instr(Opcode.ROL_W)
DataType.UBYTE -> stackvmProg.instr(Opcode.ROL_BYTE)
DataType.UWORD -> stackvmProg.instr(Opcode.ROL_WORD)
else -> throw CompilerException("wrong datatype")
}
}
"ror" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROR)
DataType.WORD -> stackvmProg.instr(Opcode.ROR_W)
DataType.UBYTE, DataType.BYTE -> stackvmProg.instr(Opcode.ROR_BYTE)
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.ROR_WORD)
else -> throw CompilerException("wrong datatype")
}
}
"rol2" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROL2)
DataType.WORD -> stackvmProg.instr(Opcode.ROL2_W)
DataType.UBYTE, DataType.BYTE -> stackvmProg.instr(Opcode.ROL2_BYTE)
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.ROL2_WORD)
else -> throw CompilerException("wrong datatype")
}
}
"ror2" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROR2)
DataType.WORD -> stackvmProg.instr(Opcode.ROR2_W)
DataType.UBYTE, DataType.BYTE -> stackvmProg.instr(Opcode.ROR2_BYTE)
DataType.UWORD, DataType.WORD -> stackvmProg.instr(Opcode.ROR2_WORD)
else -> throw CompilerException("wrong datatype")
}
}
@ -962,13 +1007,14 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
private fun translateBinaryOperator(operator: String, dt: DataType) {
val validDt = setOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
if(dt !in validDt)
throw CompilerException("invalid datatype for operator: $dt")
if(dt !in NumericDatatypes)
throw CompilerException("non-numeric datatype for operator: $dt")
val opcode = when(operator) {
"+" -> {
when(dt) {
DataType.UBYTE -> Opcode.ADD_UB
DataType.BYTE -> Opcode.ADD_B
DataType.UWORD -> Opcode.ADD_UW
DataType.WORD -> Opcode.ADD_W
DataType.FLOAT -> Opcode.ADD_F
else -> throw CompilerException("only byte/word/float possible")
@ -976,7 +1022,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"-" -> {
when(dt) {
DataType.UBYTE -> Opcode.SUB_UB
DataType.BYTE -> Opcode.SUB_B
DataType.UWORD -> Opcode.SUB_UW
DataType.WORD -> Opcode.SUB_W
DataType.FLOAT -> Opcode.SUB_F
else -> throw CompilerException("only byte/word/float possible")
@ -984,7 +1032,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"*" -> {
when(dt) {
DataType.UBYTE -> Opcode.MUL_UB
DataType.BYTE -> Opcode.MUL_B
DataType.UWORD -> Opcode.MUL_UW
DataType.WORD -> Opcode.MUL_W
DataType.FLOAT -> Opcode.MUL_F
else -> throw CompilerException("only byte/word/float possible")
@ -992,7 +1042,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"/" -> {
when(dt) {
DataType.UBYTE -> Opcode.DIV_UB
DataType.BYTE -> Opcode.DIV_B
DataType.UWORD -> Opcode.DIV_UW
DataType.WORD -> Opcode.DIV_W
DataType.FLOAT -> Opcode.DIV_F
else -> throw CompilerException("only byte/word/float possible")
@ -1000,7 +1052,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"//" -> {
when(dt) {
DataType.UBYTE -> Opcode.FLOORDIV_UB
DataType.BYTE -> Opcode.FLOORDIV_B
DataType.UWORD -> Opcode.FLOORDIV_UW
DataType.WORD -> Opcode.FLOORDIV_W
DataType.FLOAT -> Opcode.FLOORDIV_F
else -> throw CompilerException("only byte/word/float possible")
@ -1008,7 +1062,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"%" -> {
when(dt) {
DataType.UBYTE -> Opcode.REMAINDER_UB
DataType.BYTE -> Opcode.REMAINDER_B
DataType.UWORD -> Opcode.REMAINDER_UW
DataType.WORD -> Opcode.REMAINDER_W
DataType.FLOAT -> Opcode.REMAINDER_F
else -> throw CompilerException("only byte/word/float possible")
@ -1016,7 +1072,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"**" -> {
when(dt) {
DataType.UBYTE -> Opcode.POW_UB
DataType.BYTE -> Opcode.POW_B
DataType.UWORD -> Opcode.POW_UW
DataType.WORD -> Opcode.POW_W
DataType.FLOAT -> Opcode.POW_F
else -> throw CompilerException("only byte/word/float possible")
@ -1024,49 +1082,51 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"&" -> {
when(dt) {
DataType.BYTE -> Opcode.BITAND
DataType.WORD -> Opcode.BITAND_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITAND_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITAND_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"|" -> {
when(dt) {
DataType.BYTE -> Opcode.BITOR
DataType.WORD -> Opcode.BITOR_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"^" -> {
when(dt) {
DataType.BYTE -> Opcode.BITXOR
DataType.WORD -> Opcode.BITXOR_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITXOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITXOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"and" -> {
when(dt) {
DataType.BYTE -> Opcode.AND
DataType.WORD -> Opcode.AND_W
DataType.UBYTE, DataType.BYTE -> Opcode.AND_BYTE
DataType.UWORD, DataType.WORD -> Opcode.AND_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"or" -> {
when(dt) {
DataType.BYTE -> Opcode.OR
DataType.WORD -> Opcode.OR_W
DataType.UBYTE, DataType.BYTE -> Opcode.OR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.OR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"xor" -> {
when(dt) {
DataType.BYTE -> Opcode.XOR
DataType.WORD -> Opcode.XOR_W
DataType.UBYTE, DataType.BYTE -> Opcode.XOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.XOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"<" -> {
when(dt) {
DataType.BYTE -> Opcode.LESS
DataType.UBYTE -> Opcode.LESS_UB
DataType.BYTE -> Opcode.LESS_B
DataType.UWORD -> Opcode.LESS_UW
DataType.WORD -> Opcode.LESS_W
DataType.FLOAT -> Opcode.LESS_F
else -> throw CompilerException("only byte/word/lfoat possible")
@ -1074,7 +1134,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
">" -> {
when(dt) {
DataType.BYTE -> Opcode.GREATER
DataType.UBYTE -> Opcode.GREATER_UB
DataType.BYTE -> Opcode.GREATER_B
DataType.UWORD -> Opcode.GREATER_UW
DataType.WORD -> Opcode.GREATER_W
DataType.FLOAT -> Opcode.GREATER_F
else -> throw CompilerException("only byte/word/lfoat possible")
@ -1082,7 +1144,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"<=" -> {
when(dt) {
DataType.BYTE -> Opcode.LESSEQ
DataType.UBYTE -> Opcode.LESSEQ_UB
DataType.BYTE -> Opcode.LESSEQ_B
DataType.UWORD -> Opcode.LESSEQ_UW
DataType.WORD -> Opcode.LESSEQ_W
DataType.FLOAT -> Opcode.LESSEQ_F
else -> throw CompilerException("only byte/word/lfoat possible")
@ -1090,7 +1154,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
">=" -> {
when(dt) {
DataType.BYTE -> Opcode.GREATEREQ
DataType.UBYTE -> Opcode.GREATEREQ_UB
DataType.BYTE -> Opcode.GREATEREQ_B
DataType.UWORD -> Opcode.GREATEREQ_UW
DataType.WORD -> Opcode.GREATEREQ_W
DataType.FLOAT -> Opcode.GREATEREQ_F
else -> throw CompilerException("only byte/word/lfoat possible")
@ -1098,16 +1164,16 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"==" -> {
when (dt) {
DataType.BYTE -> Opcode.EQUAL
DataType.WORD -> Opcode.EQUAL_W
DataType.UBYTE, DataType.BYTE -> Opcode.EQUAL_BYTE
DataType.UWORD, DataType.WORD -> Opcode.EQUAL_WORD
DataType.FLOAT -> Opcode.EQUAL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"!=" -> {
when (dt) {
DataType.BYTE -> Opcode.NOTEQUAL
DataType.WORD -> Opcode.NOTEQUAL_W
DataType.UBYTE, DataType.BYTE -> Opcode.NOTEQUAL_BYTE
DataType.UWORD, DataType.WORD -> Opcode.NOTEQUAL_WORD
DataType.FLOAT -> Opcode.NOTEQUAL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
@ -1127,20 +1193,20 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
DataType.BYTE -> Opcode.NEG_B
DataType.WORD -> Opcode.NEG_W
DataType.FLOAT -> Opcode.NEG_F
else -> throw CompilerException("only byte/word/lfoat possible")
else -> throw CompilerException("only byte/word/foat possible")
}
}
"~" -> {
when(operandDt) {
DataType.BYTE -> Opcode.INV
DataType.WORD -> Opcode.INV_W
DataType.UBYTE, DataType.BYTE -> Opcode.INV_BYTE
DataType.UWORD, DataType.WORD -> Opcode.INV_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"not" -> {
when(operandDt) {
DataType.BYTE -> Opcode.NOT
DataType.WORD -> Opcode.NOT_W
DataType.UBYTE, DataType.BYTE -> Opcode.NOT_BYTE
DataType.UWORD, DataType.WORD -> Opcode.NOT_WORD
else -> throw CompilerException("only byte/word possible")
}
}
@ -1168,9 +1234,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
// calc matrix index i=y*columns+x
// (the const-folding will have removed this for us when both x and y are constants)
translate(y)
stackvmProg.instr(Opcode.PUSH, Value(DataType.WORD, (variable!!.arrayspec!!.x as LiteralValue).asIntegerValue!!))
stackvmProg.instr(Opcode.MUL_W)
stackvmProg.instr(Opcode.ADD_W)
stackvmProg.instr(Opcode.PUSH_BYTE, Value(DataType.UWORD, (variable!!.arrayspec!!.x as LiteralValue).asIntegerValue!!))
stackvmProg.instr(Opcode.MUL_UW)
stackvmProg.instr(Opcode.ADD_UW)
}
if(variable!=null) {
@ -1181,9 +1247,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
} else {
// register indexed
if (write)
stackvmProg.instr(opcodeWriteindexedvar(DataType.ARRAY), callLabel = arrayindexed.register!!.toString())
stackvmProg.instr(opcodeWriteindexedvar(DataType.ARRAY_UB), callLabel = arrayindexed.register!!.toString())
else
stackvmProg.instr(opcodeReadindexedvar(DataType.ARRAY), callLabel = arrayindexed.register!!.toString())
stackvmProg.instr(opcodeReadindexedvar(DataType.ARRAY_UB), callLabel = arrayindexed.register!!.toString())
}
}
@ -1195,7 +1261,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"FUNC_$funcname"
).toUpperCase()
val callNr = Syscall.valueOf(function).callNr
stackvmProg.instr(Opcode.SYSCALL, Value(DataType.BYTE, callNr))
stackvmProg.instr(Opcode.SYSCALL, Value(DataType.UBYTE, callNr))
}
private fun translate(stmt: Jump) {
@ -1204,7 +1270,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
when {
stmt.generatedLabel!=null -> jumpLabel = stmt.generatedLabel
stmt.address!=null -> jumpAddress = Value(DataType.WORD, stmt.address)
stmt.address!=null -> jumpAddress = Value(DataType.UWORD, stmt.address)
else -> {
val target = stmt.identifier!!.targetStatement(namespace)!!
jumpLabel = when(target) {
@ -1263,23 +1329,27 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
if(valueDt!=targetDt) {
// convert value to target datatype if possible
when(targetDt) {
DataType.BYTE -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.WORD -> {
if(valueDt==DataType.BYTE)
stackvmProg.instr(Opcode.B2WORD)
else
throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.UBYTE, DataType.BYTE -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.UWORD, DataType.WORD -> {
when (valueDt) {
DataType.UBYTE -> stackvmProg.instr(Opcode.UB2UWORD)
DataType.BYTE -> stackvmProg.instr(Opcode.B2WORD)
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
}
}
DataType.FLOAT -> {
when (valueDt) {
DataType.UBYTE -> stackvmProg.instr(Opcode.UB2FLOAT)
DataType.BYTE -> stackvmProg.instr(Opcode.B2FLOAT)
DataType.WORD -> stackvmProg.instr(Opcode.W2FLOAT)
DataType.UWORD -> stackvmProg.instr(Opcode.W2FLOAT)
DataType.WORD -> stackvmProg.instr(Opcode.UW2FLOAT)
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
}
}
// todo: maybe if you assign byte or word to array/matrix, clear it with that value?
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
null -> throw CompilerException("could not determine targetdt")
}
}
@ -1330,76 +1400,76 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) {
if(valueDt==null)
throw CompilerException("value datatype not known")
val validDt = setOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
val validDt = setOf(DataType.UBYTE, DataType.UWORD, DataType.FLOAT)
if(valueDt !in validDt)
throw CompilerException("invalid datatype(s) for operand(s)")
val opcode = when(aug_op) {
"+=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.ADD_B
DataType.WORD -> Opcode.ADD_W
DataType.UBYTE -> Opcode.ADD_UB
DataType.UWORD -> Opcode.ADD_UW
DataType.FLOAT -> Opcode.ADD_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"-=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.SUB_B
DataType.WORD -> Opcode.SUB_W
DataType.UBYTE -> Opcode.SUB_UB
DataType.UWORD -> Opcode.SUB_UW
DataType.FLOAT -> Opcode.SUB_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"/=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.DIV_B
DataType.WORD -> Opcode.DIV_W
DataType.UBYTE -> Opcode.DIV_UB
DataType.UWORD -> Opcode.DIV_UW
DataType.FLOAT -> Opcode.DIV_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"//=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.FLOORDIV_B
DataType.WORD -> Opcode.FLOORDIV_W
DataType.UBYTE -> Opcode.FLOORDIV_UB
DataType.UWORD -> Opcode.FLOORDIV_UW
DataType.FLOAT -> Opcode.FLOORDIV_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"*=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.MUL_B
DataType.WORD -> Opcode.MUL_W
DataType.UBYTE -> Opcode.MUL_UB
DataType.UWORD -> Opcode.MUL_UW
DataType.FLOAT -> Opcode.MUL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"**=" -> {
when (valueDt) {
DataType.BYTE -> Opcode.POW_B
DataType.WORD -> Opcode.POW_W
DataType.UBYTE -> Opcode.POW_UB
DataType.UWORD -> Opcode.POW_UW
DataType.FLOAT -> Opcode.POW_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"&=" -> {
when(valueDt) {
DataType.BYTE -> Opcode.BITAND
DataType.WORD -> Opcode.BITAND_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITAND_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITAND_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"|=" -> {
when(valueDt) {
DataType.BYTE -> Opcode.BITOR
DataType.WORD -> Opcode.BITOR_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"^=" -> {
when(valueDt) {
DataType.BYTE -> Opcode.BITXOR
DataType.WORD -> Opcode.BITXOR_W
DataType.UBYTE, DataType.BYTE -> Opcode.BITXOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITXOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
@ -1431,8 +1501,8 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val reg = loop.loopRegister
loopVarName = reg.toString()
loopVarDt = when (reg) {
Register.A, Register.X, Register.Y -> DataType.BYTE
Register.AX, Register.AY, Register.XY -> DataType.WORD
Register.A, Register.X, Register.Y -> DataType.UBYTE
Register.AX, Register.AY, Register.XY -> DataType.UWORD
}
} else {
val loopvar = (loop.loopVar!!.targetStatement(namespace) as VarDecl)
@ -1451,11 +1521,11 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
if((range.last-range.first) % range.step != 0)
throw CompilerException("range first and last must be exactly inclusive")
when (loopVarDt) {
DataType.BYTE -> {
DataType.UBYTE -> {
if (range.first < 0 || range.first > 255 || range.last < 0 || range.last > 255)
throw CompilerException("range out of bounds for byte")
}
DataType.WORD -> {
DataType.UWORD -> {
if (range.first < 0 || range.first > 65535 || range.last < 0 || range.last > 65535)
throw CompilerException("range out of bounds for word")
}
@ -1492,17 +1562,17 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
private fun translateForOverIterableVar(loop: ForLoop, loopvarDt: DataType, iterableValue: LiteralValue) {
if(loopvarDt==DataType.BYTE && iterableValue.type !in setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY, DataType.MATRIX))
if(loopvarDt==DataType.UBYTE && iterableValue.type !in setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY_UB, DataType.MATRIX_UB))
throw CompilerException("loop variable type doesn't match iterableValue type")
else if(loopvarDt==DataType.WORD && iterableValue.type != DataType.ARRAY_W)
else if(loopvarDt==DataType.UWORD && iterableValue.type != DataType.ARRAY_UW)
throw CompilerException("loop variable type doesn't match iterableValue type")
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.BYTE,
DataType.WORD,
DataType.UBYTE, DataType.BYTE,
DataType.UWORD, DataType.WORD,
DataType.FLOAT -> throw CompilerException("non-iterableValue type")
DataType.STR,
DataType.STR_P,
@ -1511,9 +1581,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
numElements = iterableValue.strvalue?.length ?: heap.get(iterableValue.heapId!!).str!!.length
indexVar = if(numElements>255) "XY" else "X"
}
DataType.ARRAY,
DataType.ARRAY_W,
DataType.MATRIX -> {
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.MATRIX_UB, DataType.MATRIX_B -> {
numElements = iterableValue.arrayvalue?.size ?: heap.get(iterableValue.heapId!!).array!!.size
indexVar = if(numElements>255) "XY" else "X"
}
@ -1549,7 +1619,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel)
val zero = Value(if(numElements<=255) DataType.BYTE else DataType.WORD, 0)
val zero = Value(if(numElements<=255) DataType.UBYTE else DataType.UWORD, 0)
stackvmProg.instr(opcodePush(zero.type), zero)
stackvmProg.instr(opcodePopvar(zero.type), callLabel = indexVar)
stackvmProg.label(loopLabel)
@ -1565,7 +1635,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
stackvmProg.label(continueLabel)
stackvmProg.instr(opcodeIncvar(zero.type), callLabel = indexVar)
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH / SUB opcodes and make use of the wrapping around of the value.
// 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.
stackvmProg.instr(opcodePush(zero.type), Value(zero.type, numElements))
stackvmProg.instr(opcodePushvar(zero.type), callLabel = indexVar)
stackvmProg.instr(opcodeSub(zero.type))
@ -1627,7 +1697,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
}
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH / SUB opcodes and make use of the wrapping around of the value.
// 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.
stackvmProg.instr(opcodePush(varDt), Value(varDt, range.last+range.step))
stackvmProg.instr(opcodePushvar(varDt), callLabel = varname)
stackvmProg.instr(opcodeSub(varDt))

View File

@ -21,22 +21,22 @@ abstract class Zeropage(private val options: CompilationOptions) {
if(y==null) {
// 1 dimensional array
when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
DataType.WORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
else -> throw CompilerException("array can only be of byte, word, float")
}
} else {
// 2 dimensional matrix (only bytes for now)
when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * y
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * y
else -> throw CompilerException("matrix can only contain bytes")
}
}
} else {
when (vardecl.datatype) {
DataType.BYTE -> 1
DataType.WORD -> 2
DataType.UBYTE -> 1
DataType.UWORD -> 2
DataType.FLOAT -> {
if (options.floats) {
printWarning("allocating a large value (float) in zeropage", vardecl.position)

View File

@ -15,12 +15,12 @@ class FunctionSignature(val pure: Boolean, // does it have side effects?
val BuiltinFunctions = mapOf(
"rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null),
"rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null),
"sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) },
"cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) },
"acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) },
@ -33,54 +33,59 @@ val BuiltinFunctions = mapOf(
"sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) },
"rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) },
"deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) },
"avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), DataType.FLOAT, ::builtinAvg),
"avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.FLOAT, ::builtinAvg),
"abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT, ::builtinAbs),
"round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::round) }, // type depends on arg
"floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::floor) }, // type depends on arg
"ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::ceil) }, // type depends on arg
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
"len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), null, ::builtinLen), // type depends on args
"any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }},
"all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX))), DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }},
"lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.WORD))), DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }},
"msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.WORD))), DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}},
"flt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE, DataType.WORD))), DataType.FLOAT, ::builtinFlt),
"wrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE))), DataType.WORD, ::builtinWrd),
"wrdhi" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE))), DataType.WORD, ::builtinWrdHi),
"rnd" to FunctionSignature(true, emptyList(), DataType.BYTE),
"rndw" to FunctionSignature(true, emptyList(), DataType.WORD),
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
"len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes.toList())), null, ::builtinLen), // type depends on args
"any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }},
"all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }},
"lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }},
"msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}},
"flt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes.toList())), DataType.FLOAT, ::builtinFlt),
"uwrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE, DataType.WORD))), DataType.UWORD, ::builtinUwrd),
"wrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD))), DataType.WORD, ::builtinWrd),
"uwrdhi" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE))), DataType.UWORD, ::builtinWrdHi),
"b2ub" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE))), DataType.UBYTE, ::builtinB2ub),
"ub2b" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE))), DataType.BYTE, ::builtinUb2b),
"rnd" to FunctionSignature(true, emptyList(), DataType.UBYTE),
"rndw" to FunctionSignature(true, emptyList(), DataType.UWORD),
"rndf" to FunctionSignature(true, emptyList(), DataType.FLOAT),
"set_carry" to FunctionSignature(false, emptyList(), null),
"clear_carry" to FunctionSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null),
"str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))), DataType.BYTE),
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))), DataType.WORD),
"str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))), DataType.FLOAT),
"_vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.WORD))), null),
"_vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.WORD))), null),
"_vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", listOf(DataType.BYTE, DataType.WORD, DataType.FLOAT))), null),
"_vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", listOf(DataType.BYTE))), null),
"_vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))), null),
"_vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))), null),
"_vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", listOf(DataType.BYTE))), null),
"str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.BYTE),
"str2ubyte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.UBYTE),
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.WORD),
"str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.UWORD),
"str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.FLOAT),
"_vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.UWORD))), null),
"_vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.UWORD))), null),
"_vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes.toList())), null),
"_vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", listOf(DataType.UBYTE))), null),
"_vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), null),
"_vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", StringDatatypes.toList())), null),
"_vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", listOf(DataType.UBYTE))), null),
"_vm_gfx_pixel" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("y", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("color", listOf(DataType.BYTE))), null),
BuiltinFunctionParam("x", IntegerDatatypes.toList()),
BuiltinFunctionParam("y", IntegerDatatypes.toList()),
BuiltinFunctionParam("color", IntegerDatatypes.toList())), null),
"_vm_gfx_line" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x1", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("y1", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("x2", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("y2", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("color", listOf(DataType.BYTE))), null),
BuiltinFunctionParam("x1", IntegerDatatypes.toList()),
BuiltinFunctionParam("y1", IntegerDatatypes.toList()),
BuiltinFunctionParam("x2", IntegerDatatypes.toList()),
BuiltinFunctionParam("y2", IntegerDatatypes.toList()),
BuiltinFunctionParam("color", IntegerDatatypes.toList())), null),
"_vm_gfx_text" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("y", listOf(DataType.BYTE, DataType.WORD)),
BuiltinFunctionParam("color", listOf(DataType.BYTE)),
BuiltinFunctionParam("text", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS))),
BuiltinFunctionParam("x", IntegerDatatypes.toList()),
BuiltinFunctionParam("y", IntegerDatatypes.toList()),
BuiltinFunctionParam("color", IntegerDatatypes.toList()),
BuiltinFunctionParam("text", StringDatatypes.toList())),
null)
)
@ -89,25 +94,28 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
fun datatypeFromListArg(arglist: IExpression): DataType {
if(arglist is LiteralValue) {
if(arglist.type==DataType.ARRAY || arglist.type==DataType.ARRAY_W || arglist.type==DataType.ARRAY_F || arglist.type==DataType.MATRIX) {
if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F || arglist.type==DataType.MATRIX_UB) {
val dt = arglist.arrayvalue!!.map {it.resultingDatatype(namespace, heap)}
if(dt.any { it!=DataType.BYTE && it!=DataType.WORD && it!=DataType.FLOAT}) {
if(dt.any { it!=DataType.UBYTE && it!=DataType.UWORD && it!=DataType.FLOAT}) {
throw FatalAstException("fuction $function only accepts array of numeric values")
}
if(dt.any { it==DataType.FLOAT }) return DataType.FLOAT
if(dt.any { it==DataType.WORD }) return DataType.WORD
return DataType.BYTE
if(dt.any { it==DataType.UWORD }) return DataType.UWORD
return DataType.UBYTE
}
}
if(arglist is IdentifierReference) {
val dt = arglist.resultingDatatype(namespace, heap)
return when(dt) {
DataType.BYTE, DataType.WORD, DataType.FLOAT,
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT,
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> dt
DataType.ARRAY -> DataType.BYTE
DataType.ARRAY_UB -> DataType.UBYTE
DataType.ARRAY_B -> DataType.BYTE
DataType.ARRAY_UW -> DataType.UWORD
DataType.ARRAY_W -> DataType.WORD
DataType.ARRAY_F -> DataType.FLOAT
DataType.MATRIX -> DataType.BYTE
DataType.MATRIX_UB -> DataType.UBYTE
DataType.MATRIX_B -> DataType.BYTE
null -> throw FatalAstException("function requires one argument which is an array $function")
}
}
@ -123,18 +131,23 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
"max", "min" -> {
val dt = datatypeFromListArg(args.single())
when(dt) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> dt
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.BYTE
DataType.ARRAY -> DataType.BYTE
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> dt
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UBYTE
DataType.ARRAY_UB -> DataType.UBYTE
DataType.ARRAY_B -> DataType.BYTE
DataType.ARRAY_UW -> DataType.UWORD
DataType.ARRAY_W -> DataType.WORD
DataType.ARRAY_F -> DataType.FLOAT
DataType.MATRIX -> DataType.BYTE
DataType.MATRIX_UB -> DataType.UBYTE
DataType.MATRIX_B -> DataType.BYTE
}
}
"round", "floor", "ceil" -> {
val dt=args.single().resultingDatatype(namespace, heap)
when(dt) {
DataType.UBYTE -> DataType.UBYTE
DataType.BYTE -> DataType.BYTE
DataType.UWORD -> DataType.UWORD
DataType.WORD -> DataType.WORD
DataType.FLOAT -> DataType.WORD
else -> null
@ -143,12 +156,15 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
"sum" -> {
val dt=datatypeFromListArg(args.single())
when(dt) {
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
DataType.BYTE, DataType.WORD -> DataType.WORD
DataType.FLOAT -> DataType.FLOAT
DataType.ARRAY, DataType.ARRAY_W -> DataType.WORD
DataType.ARRAY_UB, DataType.ARRAY_UW -> DataType.UWORD
DataType.ARRAY_B, DataType.ARRAY_W -> DataType.WORD
DataType.ARRAY_F -> DataType.FLOAT
DataType.MATRIX -> DataType.WORD
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.WORD
DataType.MATRIX_UB -> DataType.UWORD
DataType.MATRIX_B -> DataType.WORD
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UWORD
}
}
"len" -> {
@ -162,14 +178,14 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
is VarDecl -> {
val value = stmt.value
if(value is LiteralValue) {
if(value.isString) return DataType.BYTE // strings are 0..255
if(value.isString) return DataType.UBYTE // strings are 0..255
}
}
}
DataType.WORD // assume other lengths are words for now.
DataType.UWORD // assume other lengths are words for now.
}
is LiteralValue -> throw FatalAstException("len of literalvalue should have been const-folded away already")
else -> DataType.WORD
else -> DataType.UWORD
}
}
else -> throw FatalAstException("unknown result type for builtin function $function")
@ -196,7 +212,7 @@ private fun oneDoubleArgOutputInt(args: List<IExpression>, position: Position, n
throw SyntaxError("built-in function requires one floating point argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val float: Double = when(constval.type) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> constval.asNumericValue!!.toDouble()
DataType.UBYTE, DataType.UWORD, DataType.FLOAT -> constval.asNumericValue!!.toDouble()
else -> throw SyntaxError("built-in function requires one floating point argument", position)
}
return numericLiteral(function(float).toInt(), args[0].position)
@ -206,7 +222,7 @@ private fun oneIntArgOutputInt(args: List<IExpression>, position: Position, name
if(args.size!=1)
throw SyntaxError("built-in function requires one integer argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE && constval.type!=DataType.WORD)
if(constval.type!=DataType.UBYTE && constval.type!=DataType.UWORD)
throw SyntaxError("built-in function requires one integer argument", position)
val integer = constval.asNumericValue?.toInt()!!
@ -227,7 +243,7 @@ private fun collectionArgOutputNumber(args: List<IExpression>, position: Positio
function(constants.map { it!!.toDouble() }).toDouble()
} else {
when(iterable.type) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> throw SyntaxError("function expects an iterable type", position)
DataType.UBYTE, DataType.UWORD, DataType.FLOAT -> throw SyntaxError("function expects an iterable type", position)
else -> {
if(iterable.heapId==null)
throw FatalAstException("iterable value should be on the heap")
@ -274,20 +290,53 @@ private fun builtinWrd(args: List<IExpression>, position: Position, namespace:IN
throw SyntaxError("wrd requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE)
throw SyntaxError("wrd requires one byte argument", position)
if(constval.type!=DataType.UBYTE && constval.type!=DataType.BYTE && constval.type!=DataType.UWORD)
throw SyntaxError("wrd requires one argument of type ubyte, byte or uword", position)
return LiteralValue(DataType.WORD, wordvalue = constval.bytevalue!!.toInt(), position = position)
}
private fun builtinUwrd(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 arg, convert to uword
if(args.size!=1)
throw SyntaxError("uwrd requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE && constval.type!=DataType.WORD && constval.type!=DataType.UWORD)
throw SyntaxError("uwrd requires one argument of type byte, word or uword", position)
return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt(), position = position)
}
private fun builtinWrdHi(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 byte arg, convert to word (in hi byte)
// 1 arg, convert to word (in hi byte)
if(args.size!=1)
throw SyntaxError("wrdhi requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE)
if(constval.type!=DataType.UBYTE)
throw SyntaxError("wrdhi requires one byte argument", position)
return LiteralValue(DataType.WORD, wordvalue = constval.bytevalue!!.toInt() shl 8, position = position)
return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt() shl 8, position = position)
}
private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 byte arg, convert to ubyte
if(args.size!=1)
throw SyntaxError("b2ub requires one byte argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE)
throw SyntaxError("b2ub requires one argument of type byte", position)
return LiteralValue(DataType.UBYTE, bytevalue=constval.bytevalue!!, position = position)
}
private fun builtinUb2b(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 ubyte arg, convert to byte
if(args.size!=1)
throw SyntaxError("ub2b requires one ubyte argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE)
throw SyntaxError("ub2b requires one argument of type ubyte", position)
return LiteralValue(DataType.BYTE, bytevalue=constval.bytevalue!!, position = position)
}
private fun builtinAbs(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -333,7 +382,7 @@ private fun builtinLen(args: List<IExpression>, position: Position, namespace:IN
?: throw SyntaxError("len over weird argument ${args[0]}", position)
}
return when(argument.type) {
DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX -> {
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
val arraySize = argument.arrayvalue?.size ?: heap.get(argument.heapId!!).array!!.size
numericLiteral(arraySize, args[0].position)
}
@ -345,8 +394,8 @@ private fun builtinLen(args: List<IExpression>, position: Position, namespace:IN
val str = argument.strvalue ?: heap.get(argument.heapId!!).str!!
numericLiteral(str.length, args[0].position)
}
DataType.BYTE,
DataType.WORD,
DataType.UBYTE, DataType.BYTE,
DataType.UWORD, DataType.WORD,
DataType.FLOAT -> throw SyntaxError("len of weird argument ${args[0]}", position)
}
}
@ -362,7 +411,7 @@ private fun numericLiteral(value: Number, position: Position): LiteralValue {
return when(tweakedValue) {
is Int -> LiteralValue.optimalNumeric(value.toInt(), position)
is Short -> LiteralValue.optimalNumeric(value.toInt(), position)
is Byte -> LiteralValue(DataType.BYTE, bytevalue = value.toShort(), position = position)
is Byte -> LiteralValue(DataType.UBYTE, bytevalue = value.toShort(), position = position)
is Double -> LiteralValue(DataType.FLOAT, floatvalue = value.toDouble(), position = position)
is Float -> LiteralValue(DataType.FLOAT, floatvalue = value.toDouble(), position = position)
else -> throw FatalAstException("invalid number type ${value::class}")

View File

@ -86,39 +86,39 @@ class ConstExprEvaluator {
}
private fun bitwisexor(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.type== DataType.BYTE) {
if(left.type== DataType.UBYTE) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.BYTE, bytevalue = (left.bytevalue!!.toInt() xor (right.asIntegerValue and 255)).toShort(), position = left.position)
return LiteralValue(DataType.UBYTE, bytevalue = (left.bytevalue!!.toInt() xor (right.asIntegerValue and 255)).toShort(), position = left.position)
}
} else if(left.type== DataType.WORD) {
} else if(left.type== DataType.UWORD) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.WORD, wordvalue = left.wordvalue!! xor right.asIntegerValue, position = left.position)
return LiteralValue(DataType.UWORD, wordvalue = left.wordvalue!! xor right.asIntegerValue, position = left.position)
}
}
throw ExpressionError("cannot calculate $left ^ $right", left.position)
}
private fun bitwiseor(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.type== DataType.BYTE) {
if(left.type== DataType.UBYTE) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.BYTE, bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort(), position = left.position)
return LiteralValue(DataType.UBYTE, bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort(), position = left.position)
}
} else if(left.type== DataType.WORD) {
} else if(left.type== DataType.UWORD) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.WORD, wordvalue = left.wordvalue!! or right.asIntegerValue, position = left.position)
return LiteralValue(DataType.UWORD, wordvalue = left.wordvalue!! or right.asIntegerValue, position = left.position)
}
}
throw ExpressionError("cannot calculate $left | $right", left.position)
}
private fun bitwiseand(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.type== DataType.BYTE) {
if(left.type== DataType.UBYTE) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.BYTE, bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort(), position = left.position)
return LiteralValue(DataType.UBYTE, bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort(), position = left.position)
}
} else if(left.type== DataType.WORD) {
} else if(left.type== DataType.UWORD) {
if(right.asIntegerValue!=null) {
return LiteralValue(DataType.WORD, wordvalue = left.wordvalue!! or right.asIntegerValue, position = left.position)
return LiteralValue(DataType.UWORD, wordvalue = left.wordvalue!! or right.asIntegerValue, position = left.position)
}
}
throw ExpressionError("cannot calculate $left & $right", left.position)

View File

@ -38,33 +38,33 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
DataType.FLOAT -> {
// vardecl: for float vars, promote constant integer initialization values to floats
val literal = decl.value as? LiteralValue
if (literal != null && (literal.type == DataType.BYTE || literal.type==DataType.WORD)) {
if (literal != null && literal.type in IntegerDatatypes) {
val newValue = LiteralValue(DataType.FLOAT, floatvalue = literal.asNumericValue!!.toDouble(), position = literal.position)
decl.value = newValue
}
}
DataType.BYTE, DataType.WORD -> {
in IntegerDatatypes -> {
// vardecl: for byte/word vars, convert char/string of length 1 initialization values to integer
val literal = decl.value as? LiteralValue
if (literal != null && literal.isString && literal.strvalue?.length == 1) {
val petscii = Petscii.encodePetscii(literal.strvalue)[0]
val newValue = LiteralValue(DataType.BYTE, bytevalue = petscii, position = literal.position)
val newValue = LiteralValue(DataType.UBYTE, bytevalue = petscii, position = literal.position)
decl.value = newValue
}
}
DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX -> {
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
val litval = decl.value as? LiteralValue
val size = decl.arrayspec!!.size()
if(litval!=null && litval.isArray) {
// array initializer value is an array already, keep as-is (or convert to WORDs if needed)
if(litval.heapId!=null) {
if (decl.datatype == DataType.MATRIX && litval.type != DataType.MATRIX) {
val array = heap.get(litval.heapId).copy(type = DataType.MATRIX)
if (decl.datatype == DataType.MATRIX_UB && litval.type != DataType.MATRIX_UB) {
val array = heap.get(litval.heapId).copy(type = DataType.MATRIX_UB)
heap.update(litval.heapId, array)
} else if(decl.datatype==DataType.ARRAY_W && litval.type == DataType.ARRAY) {
} else if(decl.datatype==DataType.ARRAY_UW && litval.type == DataType.ARRAY_UB) {
val array = heap.get(litval.heapId)
if(array.array!=null) {
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_W, null, array.array, null))
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_UW, null, array.array, null))
decl.value = LiteralValue(decl.datatype, heapId = litval.heapId, position = litval.position)
}
}
@ -426,6 +426,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
return super.process(range)
}
// todo datatypes
override fun process(literalValue: LiteralValue): LiteralValue {
if(literalValue.strvalue!=null) {
// intern the string; move it into the heap
@ -438,9 +439,9 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
} else if(literalValue.arrayvalue!=null) {
val newArray = literalValue.arrayvalue.map { it.process(this) }.toTypedArray()
var arrayDt = DataType.ARRAY
if(newArray.any { it.resultingDatatype(namespace, heap) == DataType.WORD })
arrayDt = DataType.ARRAY_W
var arrayDt = DataType.ARRAY_UB
if(newArray.any { it.resultingDatatype(namespace, heap) == DataType.UWORD })
arrayDt = DataType.ARRAY_UW
if(newArray.any { it.resultingDatatype(namespace, heap) == DataType.FLOAT })
arrayDt = DataType.ARRAY_F
@ -452,7 +453,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
addError(ExpressionError("array/matrix literal can contain only constant values", literalValue.position))
return super.process(literalValue)
}
if(arrayDt==DataType.ARRAY || arrayDt==DataType.MATRIX) {
if(arrayDt==DataType.ARRAY_UB || arrayDt==DataType.MATRIX_UB) {
// all values should be bytes
val integerArray = litArray.map { (it as LiteralValue).bytevalue }
if(integerArray.any { it==null || it.toInt() !in 0..255 }) {
@ -463,7 +464,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
val heapId = heap.add(arrayDt, array)
val newValue = LiteralValue(arrayDt, heapId=heapId, position = literalValue.position)
return super.process(newValue)
} else if(arrayDt==DataType.ARRAY_W) {
} else if(arrayDt==DataType.ARRAY_UW) {
// all values should be bytes or words
val integerArray = litArray.map { (it as LiteralValue).asIntegerValue }
if(integerArray.any {it==null || it !in 0..65535 }) {
@ -472,7 +473,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
val array = integerArray.filterNotNull().toIntArray()
val heapId = heap.add(arrayDt, array)
val newValue = LiteralValue(DataType.ARRAY_W, heapId=heapId, position = literalValue.position)
val newValue = LiteralValue(DataType.ARRAY_UW, heapId=heapId, position = literalValue.position)
return super.process(newValue)
} else if(arrayDt==DataType.ARRAY_F) {
// all values should be bytes, words or floats
@ -523,13 +524,13 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
val targetDt = assignment.target.determineDatatype(namespace, heap, assignment)
// see if we can promote/convert a literal value to the required datatype
when(targetDt) {
DataType.WORD -> {
if(lv.type==DataType.BYTE)
assignment.value = LiteralValue(DataType.WORD, wordvalue = lv.asIntegerValue, position=lv.position)
DataType.UWORD -> {
if(lv.type==DataType.UBYTE)
assignment.value = LiteralValue(DataType.UWORD, wordvalue = lv.asIntegerValue, position=lv.position)
else if(lv.type==DataType.FLOAT) {
val d = lv.floatvalue!!
if(floor(d)==d && d in 0..65535) {
assignment.value = LiteralValue(DataType.WORD, wordvalue=floor(d).toInt(), position=lv.position)
assignment.value = LiteralValue(DataType.UWORD, wordvalue=floor(d).toInt(), position=lv.position)
}
}
}
@ -537,13 +538,13 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
if(lv.isNumeric)
assignment.value = LiteralValue(DataType.FLOAT, floatvalue= lv.asNumericValue?.toDouble(), position=lv.position)
}
DataType.BYTE -> {
if(lv.type==DataType.WORD && lv.asIntegerValue in 0..255) {
assignment.value = LiteralValue(DataType.BYTE, lv.asIntegerValue?.toShort(), position=lv.position)
DataType.UBYTE -> {
if(lv.type==DataType.UWORD && lv.asIntegerValue in 0..255) {
assignment.value = LiteralValue(DataType.UBYTE, lv.asIntegerValue?.toShort(), position=lv.position)
} else if(lv.type==DataType.FLOAT) {
val d = lv.floatvalue!!
if(floor(d)==d && d in 0..255) {
assignment.value = LiteralValue(DataType.BYTE, floor(d).toShort(), position=lv.position)
assignment.value = LiteralValue(DataType.UBYTE, floor(d).toShort(), position=lv.position)
}
}
}

View File

@ -284,16 +284,16 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
}
}
if (expr.left.resultingDatatype(namespace, heap) == DataType.BYTE) {
if (expr.left.resultingDatatype(namespace, heap) == DataType.UBYTE) {
if(abs(rightConst.asNumericValue!!.toDouble()) >= 256.0) {
optimizationsDone++
return LiteralValue(DataType.BYTE, 0, position = expr.position)
return LiteralValue(DataType.UBYTE, 0, position = expr.position)
}
}
else if (expr.left.resultingDatatype(namespace, heap) == DataType.WORD) {
else if (expr.left.resultingDatatype(namespace, heap) == DataType.UWORD) {
if(abs(rightConst.asNumericValue!!.toDouble()) >= 65536.0) {
optimizationsDone++
return LiteralValue(DataType.BYTE, 0, position = expr.position)
return LiteralValue(DataType.UBYTE, 0, position = expr.position)
}
}
}

View File

@ -31,9 +31,10 @@ 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, LINECOMMENT=106, COMMENT=107,
WS=108, EOL=109, NAME=110, DEC_INTEGER=111, HEX_INTEGER=112, BIN_INTEGER=113,
FLOAT_NUMBER=114, STRING=115, INLINEASMBLOCK=116, SINGLECHAR=117;
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;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@ -56,26 +57,26 @@ public class prog8Lexer extends Lexer {
"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",
"LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER",
"BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING",
"INLINEASMBLOCK", "SINGLECHAR"
"T__105", "T__106", "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 = {
null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'",
"'%zpreserved'", "'%address'", "'%import'", "'%breakpoint'", "'%asminclude'",
"'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'byte'",
"'word'", "'float'", "'str'", "'str_p'", "'str_s'", "'str_ps'", "'['",
"']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='", "'&='", "'|='",
"'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'",
"'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", "'&'", "'^'",
"'|'", "'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'"
"'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'",
"'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'",
"'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='",
"'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'",
"'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='",
"'&'", "'^'", "'|'", "'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'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -86,9 +87,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, "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, 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);
@ -150,13 +151,13 @@ public class prog8Lexer extends Lexer {
@Override
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
switch (ruleIndex) {
case 116:
case 118:
STRING_action((RuleContext)_localctx, actionIndex);
break;
case 117:
case 119:
INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex);
break;
case 118:
case 120:
SINGLECHAR_action((RuleContext)_localctx, actionIndex);
break;
}
@ -196,7 +197,7 @@ public class prog8Lexer extends Lexer {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2w\u0340\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2y\u0350\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"+
@ -209,50 +210,51 @@ 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\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\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\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3"+
"\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3"+
"\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\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\60\3\60\3\61"+
"\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66"+
"\3\66\3\67\3\67\38\38\39\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?\3?\3?\3@\3@\3@\3@\3@\3@\3A\3A\3A"+
"\3A\3A\3A\3A\3A\3A\3B\3B\3C\3C\3D\3D\3E\3E\3F\3F\3F\3G\3G\3G\3H\3H\3H"+
"\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3N\3N\3O\3O\3O"+
"\3O\3O\3O\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3R\3R\3R\3S\3S\3T\3T\3U\3U\3U\3U"+
"\3U\3U\3U\3V\3V\3V\3V\3V\3V\3V\3V\3V\3W\3W\3X\3X\3X\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`\3a\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\3f\3f\3f\3f\3g\3g\3g\3h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i"+
"\3i\3i\3j\3j\3j\3j\3j\3j\3k\3k\7k\u02cf\nk\fk\16k\u02d2\13k\3k\3k\3k\3"+
"k\3l\3l\7l\u02da\nl\fl\16l\u02dd\13l\3l\3l\3m\3m\3m\3m\3n\6n\u02e6\nn"+
"\rn\16n\u02e7\3o\3o\7o\u02ec\no\fo\16o\u02ef\13o\3p\3p\3p\6p\u02f4\np"+
"\rp\16p\u02f5\5p\u02f8\np\3q\3q\6q\u02fc\nq\rq\16q\u02fd\3r\3r\6r\u0302"+
"\nr\rr\16r\u0303\3s\3s\3s\5s\u0309\ns\3s\5s\u030c\ns\3t\6t\u030f\nt\r"+
"t\16t\u0310\3t\3t\6t\u0315\nt\rt\16t\u0316\5t\u0319\nt\3u\3u\3u\3u\5u"+
"\u031f\nu\3v\3v\3v\7v\u0324\nv\fv\16v\u0327\13v\3v\3v\3v\3w\3w\3w\3w\6"+
"w\u0330\nw\rw\16w\u0331\3w\3w\3w\3w\3w\3x\3x\3x\5x\u033c\nx\3x\3x\3x\3"+
"\u0331\2y\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\65"+
"i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008b"+
"G\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009f"+
"Q\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3"+
"[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7"+
"e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00db"+
"o\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7\2\u00e9\2\u00ebu\u00edv\u00ef"+
"w\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\u034f\2\3\3\2\2\2\2\5\3\2\2\2"+
"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"+
"\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"+
@ -274,204 +276,208 @@ 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\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef"+
"\3\2\2\2\3\u00f1\3\2\2\2\5\u00f3\3\2\2\2\7\u00f5\3\2\2\2\t\u00fa\3\2\2"+
"\2\13\u0102\3\2\2\2\r\u010c\3\2\2\2\17\u0116\3\2\2\2\21\u0122\3\2\2\2"+
"\23\u012b\3\2\2\2\25\u0133\3\2\2\2\27\u013f\3\2\2\2\31\u014b\3\2\2\2\33"+
"\u0156\3\2\2\2\35\u015e\3\2\2\2\37\u0160\3\2\2\2!\u0162\3\2\2\2#\u0168"+
"\3\2\2\2%\u016f\3\2\2\2\'\u0174\3\2\2\2)\u0179\3\2\2\2+\u017f\3\2\2\2"+
"-\u0183\3\2\2\2/\u0189\3\2\2\2\61\u018f\3\2\2\2\63\u0196\3\2\2\2\65\u0198"+
"\3\2\2\2\67\u019a\3\2\2\29\u019d\3\2\2\2;\u01a0\3\2\2\2=\u01a3\3\2\2\2"+
"?\u01a7\3\2\2\2A\u01aa\3\2\2\2C\u01ae\3\2\2\2E\u01b1\3\2\2\2G\u01b4\3"+
"\2\2\2I\u01b7\3\2\2\2K\u01ba\3\2\2\2M\u01bd\3\2\2\2O\u01bf\3\2\2\2Q\u01c1"+
"\3\2\2\2S\u01c3\3\2\2\2U\u01c5\3\2\2\2W\u01c8\3\2\2\2Y\u01ca\3\2\2\2["+
"\u01cc\3\2\2\2]\u01cf\3\2\2\2_\u01d1\3\2\2\2a\u01d3\3\2\2\2c\u01d5\3\2"+
"\2\2e\u01d8\3\2\2\2g\u01db\3\2\2\2i\u01de\3\2\2\2k\u01e1\3\2\2\2m\u01e3"+
"\3\2\2\2o\u01e5\3\2\2\2q\u01e7\3\2\2\2s\u01ea\3\2\2\2u\u01ef\3\2\2\2w"+
"\u01f3\3\2\2\2y\u01f6\3\2\2\2{\u01fa\3\2\2\2}\u01fe\3\2\2\2\177\u0205"+
"\3\2\2\2\u0081\u020b\3\2\2\2\u0083\u0214\3\2\2\2\u0085\u0216\3\2\2\2\u0087"+
"\u0218\3\2\2\2\u0089\u021a\3\2\2\2\u008b\u021c\3\2\2\2\u008d\u021f\3\2"+
"\2\2\u008f\u0222\3\2\2\2\u0091\u0225\3\2\2\2\u0093\u0228\3\2\2\2\u0095"+
"\u022b\3\2\2\2\u0097\u022e\3\2\2\2\u0099\u0231\3\2\2\2\u009b\u0234\3\2"+
"\2\2\u009d\u0239\3\2\2\2\u009f\u023f\3\2\2\2\u00a1\u0244\3\2\2\2\u00a3"+
"\u0248\3\2\2\2\u00a5\u024b\3\2\2\2\u00a7\u024d\3\2\2\2\u00a9\u024f\3\2"+
"\2\2\u00ab\u0256\3\2\2\2\u00ad\u025f\3\2\2\2\u00af\u0261\3\2\2\2\u00b1"+
"\u0264\3\2\2\2\u00b3\u0269\3\2\2\2\u00b5\u026f\3\2\2\2\u00b7\u0275\3\2"+
"\2\2\u00b9\u027b\3\2\2\2\u00bb\u0280\3\2\2\2\u00bd\u0286\3\2\2\2\u00bf"+
"\u028c\3\2\2\2\u00c1\u0292\3\2\2\2\u00c3\u0299\3\2\2\2\u00c5\u029f\3\2"+
"\2\2\u00c7\u02a6\3\2\2\2\u00c9\u02ac\3\2\2\2\u00cb\u02b2\3\2\2\2\u00cd"+
"\u02b6\3\2\2\2\u00cf\u02b9\3\2\2\2\u00d1\u02bf\3\2\2\2\u00d3\u02c6\3\2"+
"\2\2\u00d5\u02cc\3\2\2\2\u00d7\u02d7\3\2\2\2\u00d9\u02e0\3\2\2\2\u00db"+
"\u02e5\3\2\2\2\u00dd\u02e9\3\2\2\2\u00df\u02f7\3\2\2\2\u00e1\u02f9\3\2"+
"\2\2\u00e3\u02ff\3\2\2\2\u00e5\u0305\3\2\2\2\u00e7\u030e\3\2\2\2\u00e9"+
"\u031e\3\2\2\2\u00eb\u0320\3\2\2\2\u00ed\u032b\3\2\2\2\u00ef\u0338\3\2"+
"\2\2\u00f1\u00f2\7\u0080\2\2\u00f2\4\3\2\2\2\u00f3\u00f4\7<\2\2\u00f4"+
"\6\3\2\2\2\u00f5\u00f6\7i\2\2\u00f6\u00f7\7q\2\2\u00f7\u00f8\7v\2\2\u00f8"+
"\u00f9\7q\2\2\u00f9\b\3\2\2\2\u00fa\u00fb\7\'\2\2\u00fb\u00fc\7q\2\2\u00fc"+
"\u00fd\7w\2\2\u00fd\u00fe\7v\2\2\u00fe\u00ff\7r\2\2\u00ff\u0100\7w\2\2"+
"\u0100\u0101\7v\2\2\u0101\n\3\2\2\2\u0102\u0103\7\'\2\2\u0103\u0104\7"+
"n\2\2\u0104\u0105\7c\2\2\u0105\u0106\7w\2\2\u0106\u0107\7p\2\2\u0107\u0108"+
"\7e\2\2\u0108\u0109\7j\2\2\u0109\u010a\7g\2\2\u010a\u010b\7t\2\2\u010b"+
"\f\3\2\2\2\u010c\u010d\7\'\2\2\u010d\u010e\7|\2\2\u010e\u010f\7g\2\2\u010f"+
"\u0110\7t\2\2\u0110\u0111\7q\2\2\u0111\u0112\7r\2\2\u0112\u0113\7c\2\2"+
"\u0113\u0114\7i\2\2\u0114\u0115\7g\2\2\u0115\16\3\2\2\2\u0116\u0117\7"+
"\'\2\2\u0117\u0118\7|\2\2\u0118\u0119\7r\2\2\u0119\u011a\7t\2\2\u011a"+
"\u011b\7g\2\2\u011b\u011c\7u\2\2\u011c\u011d\7g\2\2\u011d\u011e\7t\2\2"+
"\u011e\u011f\7x\2\2\u011f\u0120\7g\2\2\u0120\u0121\7f\2\2\u0121\20\3\2"+
"\2\2\u0122\u0123\7\'\2\2\u0123\u0124\7c\2\2\u0124\u0125\7f\2\2\u0125\u0126"+
"\7f\2\2\u0126\u0127\7t\2\2\u0127\u0128\7g\2\2\u0128\u0129\7u\2\2\u0129"+
"\u012a\7u\2\2\u012a\22\3\2\2\2\u012b\u012c\7\'\2\2\u012c\u012d\7k\2\2"+
"\u012d\u012e\7o\2\2\u012e\u012f\7r\2\2\u012f\u0130\7q\2\2\u0130\u0131"+
"\7t\2\2\u0131\u0132\7v\2\2\u0132\24\3\2\2\2\u0133\u0134\7\'\2\2\u0134"+
"\u0135\7d\2\2\u0135\u0136\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138\7c\2\2"+
"\u0138\u0139\7m\2\2\u0139\u013a\7r\2\2\u013a\u013b\7q\2\2\u013b\u013c"+
"\7k\2\2\u013c\u013d\7p\2\2\u013d\u013e\7v\2\2\u013e\26\3\2\2\2\u013f\u0140"+
"\7\'\2\2\u0140\u0141\7c\2\2\u0141\u0142\7u\2\2\u0142\u0143\7o\2\2\u0143"+
"\u0144\7k\2\2\u0144\u0145\7p\2\2\u0145\u0146\7e\2\2\u0146\u0147\7n\2\2"+
"\u0147\u0148\7w\2\2\u0148\u0149\7f\2\2\u0149\u014a\7g\2\2\u014a\30\3\2"+
"\2\2\u014b\u014c\7\'\2\2\u014c\u014d\7c\2\2\u014d\u014e\7u\2\2\u014e\u014f"+
"\7o\2\2\u014f\u0150\7d\2\2\u0150\u0151\7k\2\2\u0151\u0152\7p\2\2\u0152"+
"\u0153\7c\2\2\u0153\u0154\7t\2\2\u0154\u0155\7{\2\2\u0155\32\3\2\2\2\u0156"+
"\u0157\7\'\2\2\u0157\u0158\7q\2\2\u0158\u0159\7r\2\2\u0159\u015a\7v\2"+
"\2\u015a\u015b\7k\2\2\u015b\u015c\7q\2\2\u015c\u015d\7p\2\2\u015d\34\3"+
"\2\2\2\u015e\u015f\7.\2\2\u015f\36\3\2\2\2\u0160\u0161\7?\2\2\u0161 \3"+
"\2\2\2\u0162\u0163\7e\2\2\u0163\u0164\7q\2\2\u0164\u0165\7p\2\2\u0165"+
"\u0166\7u\2\2\u0166\u0167\7v\2\2\u0167\"\3\2\2\2\u0168\u0169\7o\2\2\u0169"+
"\u016a\7g\2\2\u016a\u016b\7o\2\2\u016b\u016c\7q\2\2\u016c\u016d\7t\2\2"+
"\u016d\u016e\7{\2\2\u016e$\3\2\2\2\u016f\u0170\7d\2\2\u0170\u0171\7{\2"+
"\2\u0171\u0172\7v\2\2\u0172\u0173\7g\2\2\u0173&\3\2\2\2\u0174\u0175\7"+
"y\2\2\u0175\u0176\7q\2\2\u0176\u0177\7t\2\2\u0177\u0178\7f\2\2\u0178("+
"\3\2\2\2\u0179\u017a\7h\2\2\u017a\u017b\7n\2\2\u017b\u017c\7q\2\2\u017c"+
"\u017d\7c\2\2\u017d\u017e\7v\2\2\u017e*\3\2\2\2\u017f\u0180\7u\2\2\u0180"+
"\u0181\7v\2\2\u0181\u0182\7t\2\2\u0182,\3\2\2\2\u0183\u0184\7u\2\2\u0184"+
"\u0185\7v\2\2\u0185\u0186\7t\2\2\u0186\u0187\7a\2\2\u0187\u0188\7r\2\2"+
"\u0188.\3\2\2\2\u0189\u018a\7u\2\2\u018a\u018b\7v\2\2\u018b\u018c\7t\2"+
"\2\u018c\u018d\7a\2\2\u018d\u018e\7u\2\2\u018e\60\3\2\2\2\u018f\u0190"+
"\7u\2\2\u0190\u0191\7v\2\2\u0191\u0192\7t\2\2\u0192\u0193\7a\2\2\u0193"+
"\u0194\7r\2\2\u0194\u0195\7u\2\2\u0195\62\3\2\2\2\u0196\u0197\7]\2\2\u0197"+
"\64\3\2\2\2\u0198\u0199\7_\2\2\u0199\66\3\2\2\2\u019a\u019b\7-\2\2\u019b"+
"\u019c\7?\2\2\u019c8\3\2\2\2\u019d\u019e\7/\2\2\u019e\u019f\7?\2\2\u019f"+
":\3\2\2\2\u01a0\u01a1\7\61\2\2\u01a1\u01a2\7?\2\2\u01a2<\3\2\2\2\u01a3"+
"\u01a4\7\61\2\2\u01a4\u01a5\7\61\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,\2"+
"\2\u01ab\u01ac\7,\2\2\u01ac\u01ad\7?\2\2\u01adB\3\2\2\2\u01ae\u01af\7"+
"(\2\2\u01af\u01b0\7?\2\2\u01b0D\3\2\2\2\u01b1\u01b2\7~\2\2\u01b2\u01b3"+
"\7?\2\2\u01b3F\3\2\2\2\u01b4\u01b5\7`\2\2\u01b5\u01b6\7?\2\2\u01b6H\3"+
"\2\2\2\u01b7\u01b8\7-\2\2\u01b8\u01b9\7-\2\2\u01b9J\3\2\2\2\u01ba\u01bb"+
"\7/\2\2\u01bb\u01bc\7/\2\2\u01bcL\3\2\2\2\u01bd\u01be\7*\2\2\u01beN\3"+
"\2\2\2\u01bf\u01c0\7+\2\2\u01c0P\3\2\2\2\u01c1\u01c2\7-\2\2\u01c2R\3\2"+
"\2\2\u01c3\u01c4\7/\2\2\u01c4T\3\2\2\2\u01c5\u01c6\7,\2\2\u01c6\u01c7"+
"\7,\2\2\u01c7V\3\2\2\2\u01c8\u01c9\7,\2\2\u01c9X\3\2\2\2\u01ca\u01cb\7"+
"\61\2\2\u01cbZ\3\2\2\2\u01cc\u01cd\7\61\2\2\u01cd\u01ce\7\61\2\2\u01ce"+
"\\\3\2\2\2\u01cf\u01d0\7\'\2\2\u01d0^\3\2\2\2\u01d1\u01d2\7>\2\2\u01d2"+
"`\3\2\2\2\u01d3\u01d4\7@\2\2\u01d4b\3\2\2\2\u01d5\u01d6\7>\2\2\u01d6\u01d7"+
"\7?\2\2\u01d7d\3\2\2\2\u01d8\u01d9\7@\2\2\u01d9\u01da\7?\2\2\u01daf\3"+
"\2\2\2\u01db\u01dc\7?\2\2\u01dc\u01dd\7?\2\2\u01ddh\3\2\2\2\u01de\u01df"+
"\7#\2\2\u01df\u01e0\7?\2\2\u01e0j\3\2\2\2\u01e1\u01e2\7(\2\2\u01e2l\3"+
"\2\2\2\u01e3\u01e4\7`\2\2\u01e4n\3\2\2\2\u01e5\u01e6\7~\2\2\u01e6p\3\2"+
"\2\2\u01e7\u01e8\7v\2\2\u01e8\u01e9\7q\2\2\u01e9r\3\2\2\2\u01ea\u01eb"+
"\7u\2\2\u01eb\u01ec\7v\2\2\u01ec\u01ed\7g\2\2\u01ed\u01ee\7r\2\2\u01ee"+
"t\3\2\2\2\u01ef\u01f0\7c\2\2\u01f0\u01f1\7p\2\2\u01f1\u01f2\7f\2\2\u01f2"+
"v\3\2\2\2\u01f3\u01f4\7q\2\2\u01f4\u01f5\7t\2\2\u01f5x\3\2\2\2\u01f6\u01f7"+
"\7z\2\2\u01f7\u01f8\7q\2\2\u01f8\u01f9\7t\2\2\u01f9z\3\2\2\2\u01fa\u01fb"+
"\7p\2\2\u01fb\u01fc\7q\2\2\u01fc\u01fd\7v\2\2\u01fd|\3\2\2\2\u01fe\u01ff"+
"\7t\2\2\u01ff\u0200\7g\2\2\u0200\u0201\7v\2\2\u0201\u0202\7w\2\2\u0202"+
"\u0203\7t\2\2\u0203\u0204\7p\2\2\u0204~\3\2\2\2\u0205\u0206\7d\2\2\u0206"+
"\u0207\7t\2\2\u0207\u0208\7g\2\2\u0208\u0209\7c\2\2\u0209\u020a\7m\2\2"+
"\u020a\u0080\3\2\2\2\u020b\u020c\7e\2\2\u020c\u020d\7q\2\2\u020d\u020e"+
"\7p\2\2\u020e\u020f\7v\2\2\u020f\u0210\7k\2\2\u0210\u0211\7p\2\2\u0211"+
"\u0212\7w\2\2\u0212\u0213\7g\2\2\u0213\u0082\3\2\2\2\u0214\u0215\7\60"+
"\2\2\u0215\u0084\3\2\2\2\u0216\u0217\7C\2\2\u0217\u0086\3\2\2\2\u0218"+
"\u0219\7Z\2\2\u0219\u0088\3\2\2\2\u021a\u021b\7[\2\2\u021b\u008a\3\2\2"+
"\2\u021c\u021d\7C\2\2\u021d\u021e\7Z\2\2\u021e\u008c\3\2\2\2\u021f\u0220"+
"\7C\2\2\u0220\u0221\7[\2\2\u0221\u008e\3\2\2\2\u0222\u0223\7Z\2\2\u0223"+
"\u0224\7[\2\2\u0224\u0090\3\2\2\2\u0225\u0226\7R\2\2\u0226\u0227\7e\2"+
"\2\u0227\u0092\3\2\2\2\u0228\u0229\7R\2\2\u0229\u022a\7|\2\2\u022a\u0094"+
"\3\2\2\2\u022b\u022c\7R\2\2\u022c\u022d\7p\2\2\u022d\u0096\3\2\2\2\u022e"+
"\u022f\7R\2\2\u022f\u0230\7x\2\2\u0230\u0098\3\2\2\2\u0231\u0232\7\60"+
"\2\2\u0232\u0233\7y\2\2\u0233\u009a\3\2\2\2\u0234\u0235\7v\2\2\u0235\u0236"+
"\7t\2\2\u0236\u0237\7w\2\2\u0237\u0238\7g\2\2\u0238\u009c\3\2\2\2\u0239"+
"\u023a\7h\2\2\u023a\u023b\7c\2\2\u023b\u023c\7n\2\2\u023c\u023d\7u\2\2"+
"\u023d\u023e\7g\2\2\u023e\u009e\3\2\2\2\u023f\u0240\7\'\2\2\u0240\u0241"+
"\7c\2\2\u0241\u0242\7u\2\2\u0242\u0243\7o\2\2\u0243\u00a0\3\2\2\2\u0244"+
"\u0245\7u\2\2\u0245\u0246\7w\2\2\u0246\u0247\7d\2\2\u0247\u00a2\3\2\2"+
"\2\u0248\u0249\7/\2\2\u0249\u024a\7@\2\2\u024a\u00a4\3\2\2\2\u024b\u024c"+
"\7}\2\2\u024c\u00a6\3\2\2\2\u024d\u024e\7\177\2\2\u024e\u00a8\3\2\2\2"+
"\u024f\u0250\7c\2\2\u0250\u0251\7u\2\2\u0251\u0252\7o\2\2\u0252\u0253"+
"\7u\2\2\u0253\u0254\7w\2\2\u0254\u0255\7d\2\2\u0255\u00aa\3\2\2\2\u0256"+
"\u0257\7e\2\2\u0257\u0258\7n\2\2\u0258\u0259\7q\2\2\u0259\u025a\7d\2\2"+
"\u025a\u025b\7d\2\2\u025b\u025c\7g\2\2\u025c\u025d\7t\2\2\u025d\u025e"+
"\7u\2\2\u025e\u00ac\3\2\2\2\u025f\u0260\7B\2\2\u0260\u00ae\3\2\2\2\u0261"+
"\u0262\7k\2\2\u0262\u0263\7h\2\2\u0263\u00b0\3\2\2\2\u0264\u0265\7g\2"+
"\2\u0265\u0266\7n\2\2\u0266\u0267\7u\2\2\u0267\u0268\7g\2\2\u0268\u00b2"+
"\3\2\2\2\u0269\u026a\7k\2\2\u026a\u026b\7h\2\2\u026b\u026c\7a\2\2\u026c"+
"\u026d\7e\2\2\u026d\u026e\7u\2\2\u026e\u00b4\3\2\2\2\u026f\u0270\7k\2"+
"\2\u0270\u0271\7h\2\2\u0271\u0272\7a\2\2\u0272\u0273\7e\2\2\u0273\u0274"+
"\7e\2\2\u0274\u00b6\3\2\2\2\u0275\u0276\7k\2\2\u0276\u0277\7h\2\2\u0277"+
"\u0278\7a\2\2\u0278\u0279\7g\2\2\u0279\u027a\7s\2\2\u027a\u00b8\3\2\2"+
"\2\u027b\u027c\7k\2\2\u027c\u027d\7h\2\2\u027d\u027e\7a\2\2\u027e\u027f"+
"\7|\2\2\u027f\u00ba\3\2\2\2\u0280\u0281\7k\2\2\u0281\u0282\7h\2\2\u0282"+
"\u0283\7a\2\2\u0283\u0284\7p\2\2\u0284\u0285\7g\2\2\u0285\u00bc\3\2\2"+
"\2\u0286\u0287\7k\2\2\u0287\u0288\7h\2\2\u0288\u0289\7a\2\2\u0289\u028a"+
"\7p\2\2\u028a\u028b\7|\2\2\u028b\u00be\3\2\2\2\u028c\u028d\7k\2\2\u028d"+
"\u028e\7h\2\2\u028e\u028f\7a\2\2\u028f\u0290\7r\2\2\u0290\u0291\7n\2\2"+
"\u0291\u00c0\3\2\2\2\u0292\u0293\7k\2\2\u0293\u0294\7h\2\2\u0294\u0295"+
"\7a\2\2\u0295\u0296\7r\2\2\u0296\u0297\7q\2\2\u0297\u0298\7u\2\2\u0298"+
"\u00c2\3\2\2\2\u0299\u029a\7k\2\2\u029a\u029b\7h\2\2\u029b\u029c\7a\2"+
"\2\u029c\u029d\7o\2\2\u029d\u029e\7k\2\2\u029e\u00c4\3\2\2\2\u029f\u02a0"+
"\7k\2\2\u02a0\u02a1\7h\2\2\u02a1\u02a2\7a\2\2\u02a2\u02a3\7p\2\2\u02a3"+
"\u02a4\7g\2\2\u02a4\u02a5\7i\2\2\u02a5\u00c6\3\2\2\2\u02a6\u02a7\7k\2"+
"\2\u02a7\u02a8\7h\2\2\u02a8\u02a9\7a\2\2\u02a9\u02aa\7x\2\2\u02aa\u02ab"+
"\7u\2\2\u02ab\u00c8\3\2\2\2\u02ac\u02ad\7k\2\2\u02ad\u02ae\7h\2\2\u02ae"+
"\u02af\7a\2\2\u02af\u02b0\7x\2\2\u02b0\u02b1\7e\2\2\u02b1\u00ca\3\2\2"+
"\2\u02b2\u02b3\7h\2\2\u02b3\u02b4\7q\2\2\u02b4\u02b5\7t\2\2\u02b5\u00cc"+
"\3\2\2\2\u02b6\u02b7\7k\2\2\u02b7\u02b8\7p\2\2\u02b8\u00ce\3\2\2\2\u02b9"+
"\u02ba\7y\2\2\u02ba\u02bb\7j\2\2\u02bb\u02bc\7k\2\2\u02bc\u02bd\7n\2\2"+
"\u02bd\u02be\7g\2\2\u02be\u00d0\3\2\2\2\u02bf\u02c0\7t\2\2\u02c0\u02c1"+
"\7g\2\2\u02c1\u02c2\7r\2\2\u02c2\u02c3\7g\2\2\u02c3\u02c4\7c\2\2\u02c4"+
"\u02c5\7v\2\2\u02c5\u00d2\3\2\2\2\u02c6\u02c7\7w\2\2\u02c7\u02c8\7p\2"+
"\2\u02c8\u02c9\7v\2\2\u02c9\u02ca\7k\2\2\u02ca\u02cb\7n\2\2\u02cb\u00d4"+
"\3\2\2\2\u02cc\u02d0\t\2\2\2\u02cd\u02cf\t\3\2\2\u02ce\u02cd\3\2\2\2\u02cf"+
"\u02d2\3\2\2\2\u02d0\u02ce\3\2\2\2\u02d0\u02d1\3\2\2\2\u02d1\u02d3\3\2"+
"\2\2\u02d2\u02d0\3\2\2\2\u02d3\u02d4\5\u00d7l\2\u02d4\u02d5\3\2\2\2\u02d5"+
"\u02d6\bk\2\2\u02d6\u00d6\3\2\2\2\u02d7\u02db\7=\2\2\u02d8\u02da\n\2\2"+
"\2\u02d9\u02d8\3\2\2\2\u02da\u02dd\3\2\2\2\u02db\u02d9\3\2\2\2\u02db\u02dc"+
"\3\2\2\2\u02dc\u02de\3\2\2\2\u02dd\u02db\3\2\2\2\u02de\u02df\bl\2\2\u02df"+
"\u00d8\3\2\2\2\u02e0\u02e1\t\3\2\2\u02e1\u02e2\3\2\2\2\u02e2\u02e3\bm"+
"\3\2\u02e3\u00da\3\2\2\2\u02e4\u02e6\t\2\2\2\u02e5\u02e4\3\2\2\2\u02e6"+
"\u02e7\3\2\2\2\u02e7\u02e5\3\2\2\2\u02e7\u02e8\3\2\2\2\u02e8\u00dc\3\2"+
"\2\2\u02e9\u02ed\t\4\2\2\u02ea\u02ec\t\5\2\2\u02eb\u02ea\3\2\2\2\u02ec"+
"\u02ef\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ed\u02ee\3\2\2\2\u02ee\u00de\3\2"+
"\2\2\u02ef\u02ed\3\2\2\2\u02f0\u02f8\4\62;\2\u02f1\u02f3\4\63;\2\u02f2"+
"\u02f4\4\62;\2\u02f3\u02f2\3\2\2\2\u02f4\u02f5\3\2\2\2\u02f5\u02f3\3\2"+
"\2\2\u02f5\u02f6\3\2\2\2\u02f6\u02f8\3\2\2\2\u02f7\u02f0\3\2\2\2\u02f7"+
"\u02f1\3\2\2\2\u02f8\u00e0\3\2\2\2\u02f9\u02fb\7&\2\2\u02fa\u02fc\t\6"+
"\2\2\u02fb\u02fa\3\2\2\2\u02fc\u02fd\3\2\2\2\u02fd\u02fb\3\2\2\2\u02fd"+
"\u02fe\3\2\2\2\u02fe\u00e2\3\2\2\2\u02ff\u0301\7\'\2\2\u0300\u0302\4\62"+
"\63\2\u0301\u0300\3\2\2\2\u0302\u0303\3\2\2\2\u0303\u0301\3\2\2\2\u0303"+
"\u0304\3\2\2\2\u0304\u00e4\3\2\2\2\u0305\u030b\5\u00e7t\2\u0306\u0308"+
"\t\7\2\2\u0307\u0309\t\b\2\2\u0308\u0307\3\2\2\2\u0308\u0309\3\2\2\2\u0309"+
"\u030a\3\2\2\2\u030a\u030c\5\u00e7t\2\u030b\u0306\3\2\2\2\u030b\u030c"+
"\3\2\2\2\u030c\u00e6\3\2\2\2\u030d\u030f\4\62;\2\u030e\u030d\3\2\2\2\u030f"+
"\u0310\3\2\2\2\u0310\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u0318\3\2"+
"\2\2\u0312\u0314\7\60\2\2\u0313\u0315\4\62;\2\u0314\u0313\3\2\2\2\u0315"+
"\u0316\3\2\2\2\u0316\u0314\3\2\2\2\u0316\u0317\3\2\2\2\u0317\u0319\3\2"+
"\2\2\u0318\u0312\3\2\2\2\u0318\u0319\3\2\2\2\u0319\u00e8\3\2\2\2\u031a"+
"\u031b\7^\2\2\u031b\u031f\13\2\2\2\u031c\u031d\7^\2\2\u031d\u031f\5\u00db"+
"n\2\u031e\u031a\3\2\2\2\u031e\u031c\3\2\2\2\u031f\u00ea\3\2\2\2\u0320"+
"\u0325\7$\2\2\u0321\u0324\5\u00e9u\2\u0322\u0324\n\t\2\2\u0323\u0321\3"+
"\2\2\2\u0323\u0322\3\2\2\2\u0324\u0327\3\2\2\2\u0325\u0323\3\2\2\2\u0325"+
"\u0326\3\2\2\2\u0326\u0328\3\2\2\2\u0327\u0325\3\2\2\2\u0328\u0329\7$"+
"\2\2\u0329\u032a\bv\4\2\u032a\u00ec\3\2\2\2\u032b\u032c\7}\2\2\u032c\u032d"+
"\7}\2\2\u032d\u032f\3\2\2\2\u032e\u0330\13\2\2\2\u032f\u032e\3\2\2\2\u0330"+
"\u0331\3\2\2\2\u0331\u0332\3\2\2\2\u0331\u032f\3\2\2\2\u0332\u0333\3\2"+
"\2\2\u0333\u0334\7\177\2\2\u0334\u0335\7\177\2\2\u0335\u0336\3\2\2\2\u0336"+
"\u0337\bw\5\2\u0337\u00ee\3\2\2\2\u0338\u033b\7)\2\2\u0339\u033c\5\u00e9"+
"u\2\u033a\u033c\n\t\2\2\u033b\u0339\3\2\2\2\u033b\u033a\3\2\2\2\u033c"+
"\u033d\3\2\2\2\u033d\u033e\7)\2\2\u033e\u033f\bx\6\2\u033f\u00f0\3\2\2"+
"\2\26\2\u02d0\u02db\u02e7\u02ed\u02f5\u02f7\u02fb\u02fd\u0303\u0308\u030b"+
"\u0310\u0316\u0318\u031e\u0323\u0325\u0331\u033b\7\2\3\2\b\2\2\3v\2\3"+
"w\3\3x\4";
"\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";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

File diff suppressed because it is too large Load Diff

View File

@ -60,9 +60,9 @@ class Program (val name: String,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> heap.add(it.second, it.third.substring(1, it.third.length-1).unescape())
DataType.ARRAY,
DataType.ARRAY_W,
DataType.MATRIX -> {
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.MATRIX_UB, DataType.MATRIX_B -> {
val numbers = it.third.substring(1, it.third.length-1).split(',')
val intarray = numbers.map{number->number.trim().toInt()}.toIntArray()
heap.add(it.second, intarray)
@ -72,7 +72,7 @@ class Program (val name: String,
val doublearray = numbers.map{number->number.trim().toDouble()}.toDoubleArray()
heap.add(it.second, doublearray)
}
DataType.BYTE, DataType.WORD, DataType.FLOAT -> throw VmExecutionException("invalid heap value type ${it.second}")
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> throw VmExecutionException("invalid heap value type ${it.second}")
}
}
}
@ -98,14 +98,14 @@ class Program (val name: String,
val args = if(parts.size==2) parts[1] else null
val instruction = when(opcode) {
Opcode.LINE -> Instruction(opcode, null, callLabel = args)
Opcode.COPY_VAR, Opcode.COPY_VAR_W, Opcode.COPY_VAR_F -> {
Opcode.COPY_VAR_BYTE, Opcode.COPY_VAR_WORD, Opcode.COPY_VAR_FLOAT -> {
val (v1, v2) = args!!.split(splitpattern, limit = 2)
Instruction(opcode, null, v1, v2)
}
Opcode.JUMP, Opcode.CALL, Opcode.BNEG, Opcode.BPOS,
Opcode.BZ, Opcode.BNZ, Opcode.BCS, Opcode.BCC -> {
if(args!!.startsWith('$')) {
Instruction(opcode, Value(DataType.WORD, args.substring(1).toInt(16)))
Instruction(opcode, Value(DataType.UWORD, args.substring(1).toInt(16)))
} else {
Instruction(opcode, callLabel = args)
}
@ -119,7 +119,7 @@ class Program (val name: String,
}
Opcode.SYSCALL -> {
val call = Syscall.valueOf(args!!)
Instruction(opcode, Value(DataType.BYTE, call.callNr))
Instruction(opcode, Value(DataType.UBYTE, call.callNr))
}
else -> {
Instruction(opcode, getArgValue(args, heap))
@ -142,8 +142,8 @@ class Program (val name: String,
}
val (type, valueStr) = args.split(':')
return when(type) {
"b" -> Value(DataType.BYTE, valueStr.toShort(16))
"w" -> Value(DataType.WORD, valueStr.toInt(16))
"b" -> Value(DataType.UBYTE, valueStr.toShort(16))
"w" -> Value(DataType.UWORD, valueStr.toInt(16))
"f" -> Value(DataType.FLOAT, valueStr.toDouble())
"heap" -> {
val heapId = valueStr.toInt()
@ -165,7 +165,9 @@ class Program (val name: String,
throw VmExecutionException("missing value type character")
val type = DataType.valueOf(typeStr.toUpperCase())
val value = when(type) {
DataType.UBYTE -> Value(DataType.UBYTE, valueStr.substring(2).toShort(16))
DataType.BYTE -> Value(DataType.BYTE, valueStr.substring(2).toShort(16))
DataType.UWORD -> Value(DataType.UWORD, valueStr.substring(2).toInt(16))
DataType.WORD -> Value(DataType.WORD, valueStr.substring(2).toInt(16))
DataType.FLOAT -> Value(DataType.FLOAT, valueStr.substring(2).toDouble())
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
@ -178,10 +180,13 @@ class Program (val name: String,
Value(type, heapId)
}
}
DataType.ARRAY,
DataType.ARRAY_UB,
DataType.ARRAY_B,
DataType.ARRAY_UW,
DataType.ARRAY_W,
DataType.ARRAY_F,
DataType.MATRIX -> {
DataType.MATRIX_UB,
DataType.MATRIX_B -> {
if(!valueStr.startsWith("heap:"))
throw VmExecutionException("invalid array/matrix value, should be a heap reference")
else {
@ -211,8 +216,8 @@ class Program (val name: String,
val values = mutableListOf<Value>()
valueStrings.forEach {
when(it.length) {
2 -> values.add(Value(DataType.BYTE, it.toShort(16)))
4 -> values.add(Value(DataType.WORD, it.toInt(16)))
2 -> values.add(Value(DataType.UBYTE, it.toShort(16)))
4 -> values.add(Value(DataType.UWORD, it.toInt(16)))
else -> throw VmExecutionException("invalid value at line $lineNr+1")
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
package prog8.stackvm
import prog8.ast.DataType
import prog8.ast.IterableDatatypes
import prog8.ast.NumericDatatypes
import kotlin.math.abs
import kotlin.math.floor
import kotlin.math.pow
@ -14,12 +17,20 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
init {
when(type) {
DataType.BYTE -> {
byteval = (numericvalueOrHeapId.toInt() and 255).toShort() // byte wrap around 0..255
DataType.UBYTE -> {
byteval = (numericvalueOrHeapId.toInt() and 255).toShort() // ubyte wrap around 0..255
asBooleanValue = byteval != (0.toShort())
}
DataType.BYTE -> {
byteval = limitByte(numericvalueOrHeapId.toInt())
asBooleanValue = byteval != (0.toShort())
}
DataType.UWORD -> {
wordval = numericvalueOrHeapId.toInt() and 65535 // uword wrap around 0..65535
asBooleanValue = wordval != 0
}
DataType.WORD -> {
wordval = numericvalueOrHeapId.toInt() and 65535 // word wrap around 0..65535
wordval = limitWord(numericvalueOrHeapId.toInt())
asBooleanValue = wordval != 0
}
DataType.FLOAT -> {
@ -35,9 +46,34 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
}
}
companion object {
fun limitByte(value: Int): Short {
var bval: Int
if(value < 0) {
bval = -(abs(value) and 127)
if(bval==0) bval=-128
}
else
bval = value and 127
return bval.toShort()
}
fun limitWord(value: Int): Int {
var bval: Int
if(value < 0) {
bval = -(abs(value) and 32767)
if(bval==0) bval=-32768
}
else
bval = value and 32767
return bval
}
}
override fun toString(): String {
return when(type) {
DataType.UBYTE -> "ub:%02x".format(byteval)
DataType.BYTE -> "b:%02x".format(byteval)
DataType.UWORD -> "uw:%04x".format(wordval)
DataType.WORD -> "w:%04x".format(wordval)
DataType.FLOAT -> "f:$floatval"
else -> "heap:$heapId"
@ -46,8 +82,8 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun numericValue(): Number {
return when(type) {
DataType.BYTE -> byteval!!
DataType.WORD -> wordval!!
DataType.UBYTE, DataType.BYTE -> byteval!!
DataType.UWORD, DataType.WORD -> wordval!!
DataType.FLOAT -> floatval!!
else -> throw VmExecutionException("invalid datatype for numeric value: $type")
}
@ -55,8 +91,8 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun integerValue(): Int {
return when(type) {
DataType.BYTE -> byteval!!.toInt()
DataType.WORD -> wordval!!
DataType.UBYTE, DataType.BYTE -> byteval!!.toInt()
DataType.UWORD, DataType.WORD -> wordval!!
DataType.FLOAT -> throw VmExecutionException("float to integer loss of precision")
else -> throw VmExecutionException("invalid datatype for integer value: $type")
}
@ -72,28 +108,15 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
override fun equals(other: Any?): Boolean {
if(other==null || other !is Value)
return false
if(type==other.type) {
return when (type) {
DataType.STR, DataType.STR_S, DataType.STR_P, DataType.STR_PS,
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> heapId==other.heapId
DataType.BYTE, DataType.WORD, DataType.FLOAT -> compareTo(other)==0
}
}
if(type==other.type)
return if (type in IterableDatatypes) heapId==other.heapId else compareTo(other)==0
return compareTo(other)==0 // note: datatype doesn't matter
}
operator fun compareTo(other: Value): Int {
return when(type) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> {
when(other.type) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> {
numericValue().toDouble().compareTo(other.numericValue().toDouble())
}
else -> throw VmExecutionException("comparison can only be done between two numeric values")
}
}
else -> throw VmExecutionException("comparison can only be done between two numeric values")
}
return if (type in NumericDatatypes && other.type in NumericDatatypes)
numericValue().toDouble().compareTo(other.numericValue().toDouble())
else throw VmExecutionException("comparison can only be done between two numeric values")
}
private fun arithResult(leftDt: DataType, result: Number, rightDt: DataType, op: String): Value {
@ -101,16 +124,19 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
throw VmExecutionException("left and right datatypes are not the same")
if(result.toDouble() < 0 ) {
return when(leftDt) {
DataType.BYTE -> Value(DataType.BYTE, result.toInt() and 255)
DataType.WORD -> Value(DataType.WORD, result.toInt() and 65535)
DataType.UBYTE, DataType.UWORD -> throw VmExecutionException("arithmetic error: cannot store a negative value in a $leftDt")
DataType.BYTE -> Value(DataType.BYTE, limitByte(result.toInt()))
DataType.WORD -> Value(DataType.WORD, limitWord(result.toInt()))
DataType.FLOAT -> Value(DataType.FLOAT, result)
else -> throw VmExecutionException("$op on non-numeric type")
}
}
return when(leftDt) {
DataType.BYTE -> Value(DataType.BYTE, result.toInt() and 255)
DataType.WORD -> Value(DataType.WORD, result.toInt() and 65535)
DataType.UBYTE -> Value(DataType.UBYTE, result.toInt() and 255)
DataType.BYTE -> Value(DataType.BYTE, limitByte(result.toInt()))
DataType.UWORD -> Value(DataType.UWORD, result.toInt() and 65535)
DataType.WORD -> Value(DataType.WORD, limitWord(result.toInt()))
DataType.FLOAT -> Value(DataType.FLOAT, result)
else -> throw VmExecutionException("$op on non-numeric type")
}
@ -149,16 +175,16 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
val v1 = numericValue()
val v2 = other.numericValue()
if(v2.toDouble()==0.0) {
if (type == DataType.BYTE)
return Value(DataType.BYTE, 255)
else if(type == DataType.WORD)
return Value(DataType.WORD, 65535)
if (type == DataType.UBYTE)
return Value(DataType.UBYTE, 255)
else if(type == DataType.UWORD)
return Value(DataType.UWORD, 65535)
}
val result = v1.toDouble() / v2.toDouble()
// NOTE: integer division returns integer result!
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, result)
DataType.WORD -> Value(DataType.WORD, result)
DataType.UBYTE -> Value(DataType.UBYTE, result)
DataType.UWORD -> Value(DataType.UWORD, result)
DataType.FLOAT -> Value(DataType.FLOAT, result)
else -> throw VmExecutionException("div on non-numeric type")
}
@ -172,8 +198,8 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
val result = floor(v1.toDouble() / v2.toDouble())
// NOTE: integer division returns integer result!
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, result)
DataType.WORD -> Value(DataType.WORD, result)
DataType.UBYTE -> Value(DataType.UBYTE, result)
DataType.UWORD -> Value(DataType.UWORD, result)
DataType.FLOAT -> Value(DataType.FLOAT, result)
else -> throw VmExecutionException("div on non-numeric type")
}
@ -206,17 +232,17 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun rol(carry: Boolean): Pair<Value, Boolean> {
// 9 or 17 bit rotate left (with carry))
return when(type) {
DataType.BYTE -> {
DataType.UBYTE -> {
val v = byteval!!.toInt()
val newCarry = (v and 0x80) != 0
val newval = (v and 0x7f shl 1) or (if(carry) 1 else 0)
Pair(Value(DataType.BYTE, newval), newCarry)
Pair(Value(DataType.UBYTE, newval), newCarry)
}
DataType.WORD -> {
DataType.UWORD -> {
val v = wordval!!
val newCarry = (v and 0x8000) != 0
val newval = (v and 0x7fff shl 1) or (if(carry) 1 else 0)
Pair(Value(DataType.WORD, newval), newCarry)
Pair(Value(DataType.UWORD, newval), newCarry)
}
else -> throw VmExecutionException("rol can only work on byte/word")
}
@ -225,17 +251,17 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun ror(carry: Boolean): Pair<Value, Boolean> {
// 9 or 17 bit rotate right (with carry)
return when(type) {
DataType.BYTE -> {
DataType.UBYTE -> {
val v = byteval!!.toInt()
val newCarry = v and 1 != 0
val newval = (v ushr 1) or (if(carry) 0x80 else 0)
Pair(Value(DataType.BYTE, newval), newCarry)
Pair(Value(DataType.UBYTE, newval), newCarry)
}
DataType.WORD -> {
DataType.UWORD -> {
val v = wordval!!
val newCarry = v and 1 != 0
val newval = (v ushr 1) or (if(carry) 0x8000 else 0)
Pair(Value(DataType.WORD, newval), newCarry)
Pair(Value(DataType.UWORD, newval), newCarry)
}
else -> throw VmExecutionException("ror2 can only work on byte/word")
}
@ -244,17 +270,17 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun rol2(): Value {
// 8 or 16 bit rotate left
return when(type) {
DataType.BYTE -> {
DataType.UBYTE -> {
val v = byteval!!.toInt()
val carry = (v and 0x80) ushr 7
val newval = (v and 0x7f shl 1) or carry
Value(DataType.BYTE, newval)
Value(DataType.UBYTE, newval)
}
DataType.WORD -> {
DataType.UWORD -> {
val v = wordval!!
val carry = (v and 0x8000) ushr 15
val newval = (v and 0x7fff shl 1) or carry
Value(DataType.WORD, newval)
Value(DataType.UWORD, newval)
}
else -> throw VmExecutionException("rol2 can only work on byte/word")
}
@ -263,17 +289,17 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun ror2(): Value {
// 8 or 16 bit rotate right
return when(type) {
DataType.BYTE -> {
DataType.UBYTE -> {
val v = byteval!!.toInt()
val carry = v and 1 shl 7
val newval = (v ushr 1) or carry
Value(DataType.BYTE, newval)
Value(DataType.UBYTE, newval)
}
DataType.WORD -> {
DataType.UWORD -> {
val v = wordval!!
val carry = v and 1 shl 15
val newval = (v ushr 1) or carry
Value(DataType.WORD, newval)
Value(DataType.UWORD, newval)
}
else -> throw VmExecutionException("ror2 can only work on byte/word")
}
@ -281,8 +307,8 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun neg(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, -(byteval!!))
DataType.WORD -> Value(DataType.WORD, -(wordval!!))
DataType.UBYTE -> Value(DataType.UBYTE, -(byteval!!))
DataType.UWORD -> Value(DataType.UWORD, -(wordval!!))
DataType.FLOAT -> Value(DataType.FLOAT, -(floatval)!!)
else -> throw VmExecutionException("neg can only work on byte/word/float")
}
@ -309,23 +335,23 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
return Value(type, result)
}
fun and(other: Value) = Value(DataType.BYTE, if (this.asBooleanValue && other.asBooleanValue) 1 else 0)
fun or(other: Value) = Value(DataType.BYTE, if (this.asBooleanValue || other.asBooleanValue) 1 else 0)
fun xor(other: Value) = Value(DataType.BYTE, if (this.asBooleanValue xor other.asBooleanValue) 1 else 0)
fun not() = Value(DataType.BYTE, if (this.asBooleanValue) 0 else 1)
fun and(other: Value) = Value(DataType.UBYTE, if (this.asBooleanValue && other.asBooleanValue) 1 else 0)
fun or(other: Value) = Value(DataType.UBYTE, if (this.asBooleanValue || other.asBooleanValue) 1 else 0)
fun xor(other: Value) = Value(DataType.UBYTE, if (this.asBooleanValue xor other.asBooleanValue) 1 else 0)
fun not() = Value(DataType.UBYTE, if (this.asBooleanValue) 0 else 1)
fun inv(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, byteval!!.toInt().inv() and 255)
DataType.WORD -> Value(DataType.WORD, wordval!!.inv() and 65535)
DataType.UBYTE -> Value(DataType.UBYTE, byteval!!.toInt().inv() and 255)
DataType.UWORD -> Value(DataType.UWORD, wordval!!.inv() and 65535)
else -> throw VmExecutionException("inv can only work on byte/word")
}
}
fun inc(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, (byteval!! + 1) and 255)
DataType.WORD -> Value(DataType.WORD, (wordval!! + 1) and 65535)
DataType.UBYTE -> Value(DataType.UBYTE, (byteval!! + 1) and 255)
DataType.UWORD -> Value(DataType.UWORD, (wordval!! + 1) and 65535)
DataType.FLOAT -> Value(DataType.FLOAT, floatval!! + 1)
else -> throw VmExecutionException("inc can only work on byte/word/float")
}
@ -333,8 +359,8 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun dec(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, (byteval!! - 1) and 255)
DataType.WORD -> Value(DataType.WORD, (wordval!! - 1) and 65535)
DataType.UBYTE -> Value(DataType.UBYTE, (byteval!! - 1) and 255)
DataType.UWORD -> Value(DataType.UWORD, (wordval!! - 1) and 65535)
DataType.FLOAT -> Value(DataType.FLOAT, floatval!! - 1)
else -> throw VmExecutionException("dec can only work on byte/word/float")
}
@ -342,16 +368,16 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun lsb(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, byteval!!)
DataType.WORD -> Value(DataType.BYTE, wordval!! and 255)
DataType.UBYTE -> Value(DataType.UBYTE, byteval!!)
DataType.UWORD -> Value(DataType.UBYTE, wordval!! and 255)
else -> throw VmExecutionException("not can only work on byte/word")
}
}
fun msb(): Value {
return when(type) {
DataType.BYTE -> Value(DataType.BYTE, 0)
DataType.WORD -> Value(DataType.BYTE, wordval!! ushr 8 and 255)
DataType.UBYTE -> Value(DataType.UBYTE, 0)
DataType.UWORD -> Value(DataType.UBYTE, wordval!! ushr 8 and 255)
else -> throw VmExecutionException("not can only work on byte/word")
}
}

File diff suppressed because it is too large Load Diff

View File

@ -116,16 +116,16 @@ class TestZeropage {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false))
assertFailsWith<AssertionError> {
zp.allocate(VarDecl(VarDeclType.MEMORY, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.MEMORY, DataType.UBYTE, null, "", null, dummypos))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "varname", null, dummypos))
assertFailsWith<AssertionError> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "varname", null, dummypos))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname2", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "varname2", null, dummypos))
}
@Test
@ -183,15 +183,15 @@ class TestZeropage {
}
for (i in 0 until zp.available()) {
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
assertTrue(loc > 0)
}
assertEquals(0, zp.available())
assertFailsWith<CompilerException> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
}
assertFailsWith<CompilerException> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))
}
}
@ -216,16 +216,16 @@ class TestZeropage {
}
for(i in 0..13) {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))
assertEquals(1, zp.available())
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
assertFailsWith<CompilerException> {
// no more space
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))
}
}
@ -237,17 +237,17 @@ class TestZeropage {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
assertEquals(23, zp.available())
assertEquals(0x04, zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null, dummypos)))
assertEquals(0x09, zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos)))
assertEquals(0x12, zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos)))
assertEquals(0x0d, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0x94, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0x2a, zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos)))
assertEquals(0xa7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0xa9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0xb5, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0xf7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0xf9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null, dummypos)))
assertEquals(0x52, zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null, dummypos)))
assertEquals(0x09, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)))
assertEquals(0x12, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)))
assertEquals(0x0d, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0x94, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0x2a, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)))
assertEquals(0xa7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0xa9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0xb5, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0xf7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0xf9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)))
assertEquals(0x52, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)))
assertEquals(0, zp.available())
}
}
@ -314,8 +314,8 @@ class TestPetscii {
@Test
fun testLiteralValueComparisons() {
val ten = LiteralValue(DataType.WORD, wordvalue=10, position=Position("", 0 ,0 ,0))
val nine = LiteralValue(DataType.BYTE, bytevalue=9, position=Position("", 0 ,0 ,0))
val ten = LiteralValue(DataType.UWORD, wordvalue=10, position=Position("", 0 ,0 ,0))
val nine = LiteralValue(DataType.UBYTE, bytevalue=9, position=Position("", 0 ,0 ,0))
assertTrue(ten == ten)
assertFalse(ten == nine)
assertFalse(ten != ten)
@ -347,7 +347,7 @@ class TestPetscii {
@Test
fun testStackvmValueComparisons() {
val ten = Value(DataType.FLOAT, 10)
val nine = Value(DataType.WORD, 9)
val nine = Value(DataType.UWORD, 9)
assertTrue(ten == ten)
assertFalse(ten == nine)
assertFalse(ten != ten)

View File

@ -25,7 +25,7 @@ class TestStackVmValue {
@Test
fun testIdentity() {
val v = Value(DataType.WORD, 12345)
val v = Value(DataType.UWORD, 12345)
assertEquals(v, v)
assertFalse(v != v)
assertTrue(v<=v)
@ -33,49 +33,49 @@ class TestStackVmValue {
assertFalse(v<v)
assertFalse(v>v)
assertTrue(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.BYTE, 100)))
assertTrue(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.UBYTE, 100)))
}
@Test
fun testEqualsAndNotEquals() {
assertEquals(Value(DataType.BYTE, 100), Value(DataType.BYTE, 100))
assertEquals(Value(DataType.BYTE, 100), Value(DataType.WORD, 100))
assertEquals(Value(DataType.BYTE, 100), Value(DataType.FLOAT, 100))
assertEquals(Value(DataType.WORD, 254), Value(DataType.BYTE, 254))
assertEquals(Value(DataType.WORD, 12345), Value(DataType.WORD, 12345))
assertEquals(Value(DataType.WORD, 12345), Value(DataType.FLOAT, 12345))
assertEquals(Value(DataType.FLOAT, 100.0), Value(DataType.BYTE, 100))
assertEquals(Value(DataType.FLOAT, 22239.0), Value(DataType.WORD, 22239))
assertEquals(Value(DataType.UBYTE, 100), Value(DataType.UBYTE, 100))
assertEquals(Value(DataType.UBYTE, 100), Value(DataType.UWORD, 100))
assertEquals(Value(DataType.UBYTE, 100), Value(DataType.FLOAT, 100))
assertEquals(Value(DataType.UWORD, 254), Value(DataType.UBYTE, 254))
assertEquals(Value(DataType.UWORD, 12345), Value(DataType.UWORD, 12345))
assertEquals(Value(DataType.UWORD, 12345), Value(DataType.FLOAT, 12345))
assertEquals(Value(DataType.FLOAT, 100.0), Value(DataType.UBYTE, 100))
assertEquals(Value(DataType.FLOAT, 22239.0), Value(DataType.UWORD, 22239))
assertEquals(Value(DataType.FLOAT, 9.99), Value(DataType.FLOAT, 9.99))
assertTrue(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.BYTE, 100)))
assertFalse(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.WORD, 100)))
assertFalse(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.FLOAT, 100)))
assertFalse(sameValueAndType(Value(DataType.WORD, 254), Value(DataType.BYTE, 254)))
assertTrue(sameValueAndType(Value(DataType.WORD, 12345), Value(DataType.WORD, 12345)))
assertFalse(sameValueAndType(Value(DataType.WORD, 12345), Value(DataType.FLOAT, 12345)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 100.0), Value(DataType.BYTE, 100)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 22239.0), Value(DataType.WORD, 22239)))
assertTrue(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.UBYTE, 100)))
assertFalse(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.UWORD, 100)))
assertFalse(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.FLOAT, 100)))
assertFalse(sameValueAndType(Value(DataType.UWORD, 254), Value(DataType.UBYTE, 254)))
assertTrue(sameValueAndType(Value(DataType.UWORD, 12345), Value(DataType.UWORD, 12345)))
assertFalse(sameValueAndType(Value(DataType.UWORD, 12345), Value(DataType.FLOAT, 12345)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 100.0), Value(DataType.UBYTE, 100)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 22239.0), Value(DataType.UWORD, 22239)))
assertTrue(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.FLOAT, 9.99)))
assertNotEquals(Value(DataType.BYTE, 100), Value(DataType.BYTE, 101))
assertNotEquals(Value(DataType.BYTE, 100), Value(DataType.WORD, 101))
assertNotEquals(Value(DataType.BYTE, 100), Value(DataType.FLOAT, 101))
assertNotEquals(Value(DataType.WORD, 245), Value(DataType.BYTE, 246))
assertNotEquals(Value(DataType.WORD, 12345), Value(DataType.WORD, 12346))
assertNotEquals(Value(DataType.WORD, 12345), Value(DataType.FLOAT, 12346))
assertNotEquals(Value(DataType.FLOAT, 9.99), Value(DataType.BYTE, 9))
assertNotEquals(Value(DataType.FLOAT, 9.99), Value(DataType.WORD, 9))
assertNotEquals(Value(DataType.UBYTE, 100), Value(DataType.UBYTE, 101))
assertNotEquals(Value(DataType.UBYTE, 100), Value(DataType.UWORD, 101))
assertNotEquals(Value(DataType.UBYTE, 100), Value(DataType.FLOAT, 101))
assertNotEquals(Value(DataType.UWORD, 245), Value(DataType.UBYTE, 246))
assertNotEquals(Value(DataType.UWORD, 12345), Value(DataType.UWORD, 12346))
assertNotEquals(Value(DataType.UWORD, 12345), Value(DataType.FLOAT, 12346))
assertNotEquals(Value(DataType.FLOAT, 9.99), Value(DataType.UBYTE, 9))
assertNotEquals(Value(DataType.FLOAT, 9.99), Value(DataType.UWORD, 9))
assertNotEquals(Value(DataType.FLOAT, 9.99), Value(DataType.FLOAT, 9.0))
assertFalse(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.BYTE, 101)))
assertFalse(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.WORD, 101)))
assertFalse(sameValueAndType(Value(DataType.BYTE, 100), Value(DataType.FLOAT, 101)))
assertFalse(sameValueAndType(Value(DataType.WORD, 245), Value(DataType.BYTE, 246)))
assertFalse(sameValueAndType(Value(DataType.WORD, 12345), Value(DataType.WORD, 12346)))
assertFalse(sameValueAndType(Value(DataType.WORD, 12345), Value(DataType.FLOAT, 12346)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.BYTE, 9)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.WORD, 9)))
assertFalse(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.UBYTE, 101)))
assertFalse(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.UWORD, 101)))
assertFalse(sameValueAndType(Value(DataType.UBYTE, 100), Value(DataType.FLOAT, 101)))
assertFalse(sameValueAndType(Value(DataType.UWORD, 245), Value(DataType.UBYTE, 246)))
assertFalse(sameValueAndType(Value(DataType.UWORD, 12345), Value(DataType.UWORD, 12346)))
assertFalse(sameValueAndType(Value(DataType.UWORD, 12345), Value(DataType.FLOAT, 12346)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.UBYTE, 9)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.UWORD, 9)))
assertFalse(sameValueAndType(Value(DataType.FLOAT, 9.99), Value(DataType.FLOAT, 9.0)))
}
@ -86,98 +86,98 @@ class TestStackVmValue {
assertFalse(sameValueAndType(Value(DataType.STR, 999), Value(DataType.STR_P, 999)))
assertFalse(sameValueAndType(Value(DataType.STR, 999), Value(DataType.STR, 222)))
assertTrue(sameValueAndType(Value(DataType.ARRAY, 99), Value(DataType.ARRAY, 99)))
assertFalse(sameValueAndType(Value(DataType.ARRAY, 99), Value(DataType.MATRIX, 99)))
assertFalse(sameValueAndType(Value(DataType.ARRAY, 99), Value(DataType.ARRAY, 22)))
assertTrue(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.ARRAY_UB, 99)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.MATRIX_UB, 99)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.ARRAY_UB, 22)))
assertTrue(sameValueAndType(Value(DataType.ARRAY_W, 999), Value(DataType.ARRAY_W, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_W, 999), Value(DataType.MATRIX, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_W, 999), Value(DataType.ARRAY_W, 222)))
assertTrue(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.ARRAY_UW, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.MATRIX_UB, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.ARRAY_UW, 222)))
assertTrue(sameValueAndType(Value(DataType.ARRAY_F, 999), Value(DataType.ARRAY_F, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_F, 999), Value(DataType.ARRAY_W, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_F, 999), Value(DataType.ARRAY_UW, 999)))
assertFalse(sameValueAndType(Value(DataType.ARRAY_F, 999), Value(DataType.ARRAY_F, 222)))
}
@Test
fun testGreaterThan(){
assertTrue(Value(DataType.BYTE, 100) > Value(DataType.BYTE, 99))
assertTrue(Value(DataType.WORD, 254) > Value(DataType.WORD, 253))
assertTrue(Value(DataType.UBYTE, 100) > Value(DataType.UBYTE, 99))
assertTrue(Value(DataType.UWORD, 254) > Value(DataType.UWORD, 253))
assertTrue(Value(DataType.FLOAT, 100.0) > Value(DataType.FLOAT, 99.9))
assertTrue(Value(DataType.BYTE, 100) >= Value(DataType.BYTE, 100))
assertTrue(Value(DataType.WORD, 254) >= Value(DataType.WORD, 254))
assertTrue(Value(DataType.UBYTE, 100) >= Value(DataType.UBYTE, 100))
assertTrue(Value(DataType.UWORD, 254) >= Value(DataType.UWORD, 254))
assertTrue(Value(DataType.FLOAT, 100.0) >= Value(DataType.FLOAT, 100.0))
assertFalse(Value(DataType.BYTE, 100) > Value(DataType.BYTE, 100))
assertFalse(Value(DataType.WORD, 254) > Value(DataType.WORD, 254))
assertFalse(Value(DataType.UBYTE, 100) > Value(DataType.UBYTE, 100))
assertFalse(Value(DataType.UWORD, 254) > Value(DataType.UWORD, 254))
assertFalse(Value(DataType.FLOAT, 100.0) > Value(DataType.FLOAT, 100.0))
assertFalse(Value(DataType.BYTE, 100) >= Value(DataType.BYTE, 101))
assertFalse(Value(DataType.WORD, 254) >= Value(DataType.WORD, 255))
assertFalse(Value(DataType.UBYTE, 100) >= Value(DataType.UBYTE, 101))
assertFalse(Value(DataType.UWORD, 254) >= Value(DataType.UWORD, 255))
assertFalse(Value(DataType.FLOAT, 100.0) >= Value(DataType.FLOAT, 100.1))
}
@Test
fun testLessThan() {
assertTrue(Value(DataType.BYTE, 100) < Value(DataType.BYTE, 101))
assertTrue(Value(DataType.WORD, 254) < Value(DataType.WORD, 255))
assertTrue(Value(DataType.UBYTE, 100) < Value(DataType.UBYTE, 101))
assertTrue(Value(DataType.UWORD, 254) < Value(DataType.UWORD, 255))
assertTrue(Value(DataType.FLOAT, 100.0) < Value(DataType.FLOAT, 100.1))
assertTrue(Value(DataType.BYTE, 100) <= Value(DataType.BYTE, 100))
assertTrue(Value(DataType.WORD, 254) <= Value(DataType.WORD, 254))
assertTrue(Value(DataType.UBYTE, 100) <= Value(DataType.UBYTE, 100))
assertTrue(Value(DataType.UWORD, 254) <= Value(DataType.UWORD, 254))
assertTrue(Value(DataType.FLOAT, 100.0) <= Value(DataType.FLOAT, 100.0))
assertFalse(Value(DataType.BYTE, 100) < Value(DataType.BYTE, 100))
assertFalse(Value(DataType.WORD, 254) < Value(DataType.WORD, 254))
assertFalse(Value(DataType.UBYTE, 100) < Value(DataType.UBYTE, 100))
assertFalse(Value(DataType.UWORD, 254) < Value(DataType.UWORD, 254))
assertFalse(Value(DataType.FLOAT, 100.0) < Value(DataType.FLOAT, 100.0))
assertFalse(Value(DataType.BYTE, 100) <= Value(DataType.BYTE, 99))
assertFalse(Value(DataType.WORD, 254) <= Value(DataType.WORD, 253))
assertFalse(Value(DataType.UBYTE, 100) <= Value(DataType.UBYTE, 99))
assertFalse(Value(DataType.UWORD, 254) <= Value(DataType.UWORD, 253))
assertFalse(Value(DataType.FLOAT, 100.0) <= Value(DataType.FLOAT, 99.9))
}
@Test
fun testNoDtConversion() {
assertFailsWith<VmExecutionException> {
Value(DataType.WORD, 100).add(Value(DataType.BYTE, 120))
Value(DataType.UWORD, 100).add(Value(DataType.UBYTE, 120))
}
assertFailsWith<VmExecutionException> {
Value(DataType.BYTE, 100).add(Value(DataType.WORD, 120))
Value(DataType.UBYTE, 100).add(Value(DataType.UWORD, 120))
}
assertFailsWith<VmExecutionException> {
Value(DataType.FLOAT, 100.22).add(Value(DataType.WORD, 120))
Value(DataType.FLOAT, 100.22).add(Value(DataType.UWORD, 120))
}
assertFailsWith<VmExecutionException> {
Value(DataType.WORD, 1002).add(Value(DataType.FLOAT, 120.22))
Value(DataType.UWORD, 1002).add(Value(DataType.FLOAT, 120.22))
}
assertFailsWith<VmExecutionException> {
Value(DataType.FLOAT, 100.22).add(Value(DataType.BYTE, 120))
Value(DataType.FLOAT, 100.22).add(Value(DataType.UBYTE, 120))
}
assertFailsWith<VmExecutionException> {
Value(DataType.BYTE, 12).add(Value(DataType.FLOAT, 120.22))
Value(DataType.UBYTE, 12).add(Value(DataType.FLOAT, 120.22))
}
}
@Test
fun testNoAutoFloatConversion() {
assertFailsWith<VmExecutionException> {
Value(DataType.BYTE, 233).add(Value(DataType.FLOAT, 1.234))
Value(DataType.UBYTE, 233).add(Value(DataType.FLOAT, 1.234))
}
assertFailsWith<VmExecutionException> {
Value(DataType.WORD, 233).add(Value(DataType.FLOAT, 1.234))
Value(DataType.UWORD, 233).add(Value(DataType.FLOAT, 1.234))
}
assertFailsWith<VmExecutionException> {
Value(DataType.BYTE, 233).mul(Value(DataType.FLOAT, 1.234))
Value(DataType.UBYTE, 233).mul(Value(DataType.FLOAT, 1.234))
}
assertFailsWith<VmExecutionException> {
Value(DataType.WORD, 233).mul(Value(DataType.FLOAT, 1.234))
Value(DataType.UWORD, 233).mul(Value(DataType.FLOAT, 1.234))
}
assertFailsWith<VmExecutionException> {
Value(DataType.BYTE, 233).div(Value(DataType.FLOAT, 1.234))
Value(DataType.UBYTE, 233).div(Value(DataType.FLOAT, 1.234))
}
assertFailsWith<VmExecutionException> {
Value(DataType.WORD, 233).div(Value(DataType.FLOAT, 1.234))
Value(DataType.UWORD, 233).div(Value(DataType.FLOAT, 1.234))
}
val result = Value(DataType.FLOAT, 233.333).add(Value(DataType.FLOAT, 1.234))
}
@ -191,7 +191,7 @@ class TestParserLiteralValue {
@Test
fun testIdentity() {
val v = LiteralValue(DataType.WORD, wordvalue = 12345, position = dummyPos)
val v = LiteralValue(DataType.UWORD, wordvalue = 12345, position = dummyPos)
assertEquals(v, v)
assertFalse(v != v)
assertTrue(v <= v)
@ -199,62 +199,62 @@ class TestParserLiteralValue {
assertFalse(v < v)
assertFalse(v > v)
assertTrue(sameValueAndType(LiteralValue(DataType.WORD, wordvalue = 12345, position = dummyPos), LiteralValue(DataType.WORD, wordvalue = 12345, position = dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue = 12345, position = dummyPos), LiteralValue(DataType.UWORD, wordvalue = 12345, position = dummyPos)))
}
@Test
fun testEqualsAndNotEquals() {
assertEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=100, position=dummyPos))
assertEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertEquals(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos), LiteralValue(DataType.BYTE, 254, position=dummyPos))
assertEquals(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos))
assertEquals(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12345.0, position=dummyPos))
assertEquals(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos), LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertEquals(LiteralValue(DataType.FLOAT, floatvalue=22239.0, position=dummyPos), LiteralValue(DataType.WORD,wordvalue=22239, position=dummyPos))
assertEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=100, position=dummyPos))
assertEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertEquals(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos), LiteralValue(DataType.UBYTE, 254, position=dummyPos))
assertEquals(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos))
assertEquals(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12345.0, position=dummyPos))
assertEquals(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos), LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertEquals(LiteralValue(DataType.FLOAT, floatvalue=22239.0, position=dummyPos), LiteralValue(DataType.UWORD,wordvalue=22239, position=dummyPos))
assertEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos))
assertTrue(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.BYTE, 100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos), LiteralValue(DataType.BYTE, 254, position=dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12345.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos), LiteralValue(DataType.BYTE, 100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=22239.0, position=dummyPos), LiteralValue(DataType.WORD,wordvalue=22239, position=dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UBYTE, 100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos), LiteralValue(DataType.UBYTE, 254, position=dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12345.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos), LiteralValue(DataType.UBYTE, 100, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=22239.0, position=dummyPos), LiteralValue(DataType.UWORD,wordvalue=22239, position=dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos)))
assertNotEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.BYTE, 101, position=dummyPos))
assertNotEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=101, position=dummyPos))
assertNotEquals(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=101.0, position=dummyPos))
assertNotEquals(LiteralValue(DataType.WORD, wordvalue=245, position=dummyPos), LiteralValue(DataType.BYTE, 246, position=dummyPos))
assertNotEquals(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=12346, position=dummyPos))
assertNotEquals(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12346.0, position=dummyPos))
assertNotEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.BYTE, 9, position=dummyPos))
assertNotEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=9, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UBYTE, 101, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=101, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=101.0, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UWORD, wordvalue=245, position=dummyPos), LiteralValue(DataType.UBYTE, 246, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=12346, position=dummyPos))
assertNotEquals(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12346.0, position=dummyPos))
assertNotEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.UBYTE, 9, position=dummyPos))
assertNotEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=9, position=dummyPos))
assertNotEquals(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=9.0, position=dummyPos))
assertFalse(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.BYTE, 101, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=101, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.BYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=101.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=245, position=dummyPos), LiteralValue(DataType.BYTE, 246, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=12346, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.WORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12346.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.BYTE, 9, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.WORD, wordvalue=9, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UBYTE, 101, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=101, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UBYTE, 100, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=101.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=245, position=dummyPos), LiteralValue(DataType.UBYTE, 246, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=12346, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.UWORD, wordvalue=12345, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=12346.0, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.UBYTE, 9, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.UWORD, wordvalue=9, position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.FLOAT, floatvalue=9.99, position=dummyPos), LiteralValue(DataType.FLOAT, floatvalue=9.0, position=dummyPos)))
assertTrue(sameValueAndType(LiteralValue(DataType.STR, strvalue = "hello", position=dummyPos), LiteralValue(DataType.STR, strvalue="hello", position=dummyPos)))
assertFalse(sameValueAndType(LiteralValue(DataType.STR, strvalue = "hello", position=dummyPos), LiteralValue(DataType.STR, strvalue="bye", position=dummyPos)))
val lvOne = LiteralValue(DataType.BYTE, 1, position=dummyPos)
val lvTwo = LiteralValue(DataType.BYTE, 2, position=dummyPos)
val lvThree = LiteralValue(DataType.BYTE, 3, position=dummyPos)
val lvOneR = LiteralValue(DataType.BYTE, 1, position=dummyPos)
val lvTwoR = LiteralValue(DataType.BYTE, 2, position=dummyPos)
val lvThreeR = LiteralValue(DataType.BYTE, 3, position=dummyPos)
val lv1 = LiteralValue(DataType.ARRAY, arrayvalue = arrayOf(lvOne, lvTwo, lvThree), position=dummyPos)
val lv2 = LiteralValue(DataType.ARRAY, arrayvalue = arrayOf(lvOneR, lvTwoR, lvThreeR), position=dummyPos)
val lvOne = LiteralValue(DataType.UBYTE, 1, position=dummyPos)
val lvTwo = LiteralValue(DataType.UBYTE, 2, position=dummyPos)
val lvThree = LiteralValue(DataType.UBYTE, 3, position=dummyPos)
val lvOneR = LiteralValue(DataType.UBYTE, 1, position=dummyPos)
val lvTwoR = LiteralValue(DataType.UBYTE, 2, position=dummyPos)
val lvThreeR = LiteralValue(DataType.UBYTE, 3, position=dummyPos)
val lv1 = LiteralValue(DataType.ARRAY_UB, arrayvalue = arrayOf(lvOne, lvTwo, lvThree), position=dummyPos)
val lv2 = LiteralValue(DataType.ARRAY_UB, arrayvalue = arrayOf(lvOneR, lvTwoR, lvThreeR), position=dummyPos)
assertFailsWith<ExpressionError> {
assertEquals(lv1, lv2)
}
@ -262,39 +262,39 @@ class TestParserLiteralValue {
@Test
fun testGreaterThan(){
assertTrue(LiteralValue(DataType.BYTE, 100, position=dummyPos) > LiteralValue(DataType.BYTE, 99, position=dummyPos))
assertTrue(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) > LiteralValue(DataType.WORD, wordvalue=253, position=dummyPos))
assertTrue(LiteralValue(DataType.UBYTE, 100, position=dummyPos) > LiteralValue(DataType.UBYTE, 99, position=dummyPos))
assertTrue(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) > LiteralValue(DataType.UWORD, wordvalue=253, position=dummyPos))
assertTrue(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) > LiteralValue(DataType.FLOAT, floatvalue=99.9, position=dummyPos))
assertTrue(LiteralValue(DataType.BYTE, 100, position=dummyPos) >= LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertTrue(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) >= LiteralValue(DataType.WORD,wordvalue= 254, position=dummyPos))
assertTrue(LiteralValue(DataType.UBYTE, 100, position=dummyPos) >= LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertTrue(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) >= LiteralValue(DataType.UWORD,wordvalue= 254, position=dummyPos))
assertTrue(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) >= LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertFalse(LiteralValue(DataType.BYTE, 100, position=dummyPos) > LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertFalse(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) > LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos))
assertFalse(LiteralValue(DataType.UBYTE, 100, position=dummyPos) > LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertFalse(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) > LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos))
assertFalse(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) > LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertFalse(LiteralValue(DataType.BYTE, 100, position=dummyPos) >= LiteralValue(DataType.BYTE, 101, position=dummyPos))
assertFalse(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) >= LiteralValue(DataType.WORD,wordvalue= 255, position=dummyPos))
assertFalse(LiteralValue(DataType.UBYTE, 100, position=dummyPos) >= LiteralValue(DataType.UBYTE, 101, position=dummyPos))
assertFalse(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) >= LiteralValue(DataType.UWORD,wordvalue= 255, position=dummyPos))
assertFalse(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) >= LiteralValue(DataType.FLOAT, floatvalue=100.1, position=dummyPos))
}
@Test
fun testLessThan() {
assertTrue(LiteralValue(DataType.BYTE, 100, position=dummyPos) < LiteralValue(DataType.BYTE, 101, position=dummyPos))
assertTrue(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) < LiteralValue(DataType.WORD, wordvalue=255, position=dummyPos))
assertTrue(LiteralValue(DataType.UBYTE, 100, position=dummyPos) < LiteralValue(DataType.UBYTE, 101, position=dummyPos))
assertTrue(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) < LiteralValue(DataType.UWORD, wordvalue=255, position=dummyPos))
assertTrue(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) < LiteralValue(DataType.FLOAT, floatvalue=100.1, position=dummyPos))
assertTrue(LiteralValue(DataType.BYTE, 100, position=dummyPos) <= LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertTrue(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) <= LiteralValue(DataType.WORD,wordvalue= 254, position=dummyPos))
assertTrue(LiteralValue(DataType.UBYTE, 100, position=dummyPos) <= LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertTrue(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) <= LiteralValue(DataType.UWORD,wordvalue= 254, position=dummyPos))
assertTrue(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) <= LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertFalse(LiteralValue(DataType.BYTE, 100, position=dummyPos) < LiteralValue(DataType.BYTE, 100, position=dummyPos))
assertFalse(LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos) < LiteralValue(DataType.WORD, wordvalue=254, position=dummyPos))
assertFalse(LiteralValue(DataType.UBYTE, 100, position=dummyPos) < LiteralValue(DataType.UBYTE, 100, position=dummyPos))
assertFalse(LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos) < LiteralValue(DataType.UWORD, wordvalue=254, position=dummyPos))
assertFalse(LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos) < LiteralValue(DataType.FLOAT, floatvalue=100.0, position=dummyPos))
assertFalse(LiteralValue(DataType.BYTE, 100, position=dummyPos) <= LiteralValue(DataType.BYTE, 99, position=dummyPos))
assertFalse(LiteralValue(DataType.WORD,wordvalue= 254, position=dummyPos) <= LiteralValue(DataType.WORD,wordvalue= 253, position=dummyPos))
assertFalse(LiteralValue(DataType.UBYTE, 100, position=dummyPos) <= LiteralValue(DataType.UBYTE, 99, position=dummyPos))
assertFalse(LiteralValue(DataType.UWORD,wordvalue= 254, position=dummyPos) <= LiteralValue(DataType.UWORD,wordvalue= 253, position=dummyPos))
assertFalse(LiteralValue(DataType.FLOAT,floatvalue= 100.0, position=dummyPos) <= LiteralValue(DataType.FLOAT, floatvalue=99.9, position=dummyPos))
}