mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
taking down the heapvalue mess, RuntimeValue class separation
This commit is contained in:
parent
8c3b43f3ed
commit
984d251a6d
@ -5,7 +5,6 @@ import prog8.ast.base.DataType
|
|||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.base.initvarsSubName
|
import prog8.ast.base.initvarsSubName
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.mangledStructMemberName
|
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package prog8.compiler
|
package prog8.compiler
|
||||||
|
|
||||||
import prog8.ast.base.ArrayDatatypes
|
|
||||||
import prog8.ast.base.DataType
|
|
||||||
import prog8.ast.base.StringDatatypes
|
|
||||||
import prog8.ast.expressions.AddressOf
|
import prog8.ast.expressions.AddressOf
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.*
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
enum class OutputType {
|
enum class OutputType {
|
||||||
@ -74,66 +70,3 @@ internal fun tryGetEmbeddedResource(name: String): InputStream? {
|
|||||||
return object{}.javaClass.getResourceAsStream("/prog8lib/$name")
|
return object{}.javaClass.getResourceAsStream("/prog8lib/$name")
|
||||||
}
|
}
|
||||||
|
|
||||||
class HeapValues {
|
|
||||||
data class HeapValue(val type: DataType, val str: String?, val array: Array<IntegerOrAddressOf>?, val doubleArray: DoubleArray?) {
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
other as HeapValue
|
|
||||||
return type==other.type && str==other.str && Arrays.equals(array, other.array) && Arrays.equals(doubleArray, other.doubleArray)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int = Objects.hash(str, array, doubleArray)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val heap = mutableMapOf<Int, HeapValue>()
|
|
||||||
private var heapId = 1
|
|
||||||
|
|
||||||
fun size(): Int = heap.size
|
|
||||||
|
|
||||||
fun addString(type: DataType, str: String): Int {
|
|
||||||
if (str.length > 255)
|
|
||||||
throw IllegalArgumentException("string length must be 0-255")
|
|
||||||
|
|
||||||
// strings are 'interned' and shared if they're the isSameAs
|
|
||||||
val value = HeapValue(type, str, null, null)
|
|
||||||
|
|
||||||
val existing = heap.filter { it.value==value }.map { it.key }.firstOrNull()
|
|
||||||
if(existing!=null)
|
|
||||||
return existing
|
|
||||||
val newId = heapId++
|
|
||||||
heap[newId] = value
|
|
||||||
return newId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addIntegerArray(type: DataType, array: Array<IntegerOrAddressOf>): Int {
|
|
||||||
// arrays are never shared, don't check for existing
|
|
||||||
if(type !in ArrayDatatypes)
|
|
||||||
throw CompilerException("wrong array type")
|
|
||||||
val newId = heapId++
|
|
||||||
heap[newId] = HeapValue(type, null, array, null)
|
|
||||||
return newId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addDoublesArray(darray: DoubleArray): Int {
|
|
||||||
// arrays are never shared, don't check for existing
|
|
||||||
val newId = heapId++
|
|
||||||
heap[newId] = HeapValue(DataType.ARRAY_F, null, null, darray)
|
|
||||||
return newId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateString(heapId: Int, str: String) {
|
|
||||||
val oldVal = heap[heapId] ?: throw IllegalArgumentException("heapId not found in heap")
|
|
||||||
if(oldVal.type in StringDatatypes) {
|
|
||||||
if (oldVal.str!!.length != str.length)
|
|
||||||
throw IllegalArgumentException("heap string length mismatch")
|
|
||||||
heap[heapId] = oldVal.copy(str = str)
|
|
||||||
}
|
|
||||||
else throw IllegalArgumentException("heap data type mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun get(heapId: Int): HeapValue {
|
|
||||||
return heap[heapId] ?:
|
|
||||||
throw IllegalArgumentException("heapId $heapId not found in heap")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
70
compiler/src/prog8/compiler/HeapValues.kt
Normal file
70
compiler/src/prog8/compiler/HeapValues.kt
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package prog8.compiler
|
||||||
|
|
||||||
|
import prog8.ast.base.ArrayDatatypes
|
||||||
|
import prog8.ast.base.DataType
|
||||||
|
import prog8.ast.base.StringDatatypes
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class HeapValues {
|
||||||
|
data class HeapValue(val type: DataType, val str: String?, val array: Array<IntegerOrAddressOf>?, val doubleArray: DoubleArray?) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
other as HeapValue
|
||||||
|
return type==other.type && str==other.str && Arrays.equals(array, other.array) && Arrays.equals(doubleArray, other.doubleArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = Objects.hash(str, array, doubleArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val heap = mutableMapOf<Int, HeapValue>()
|
||||||
|
private var heapId = 1
|
||||||
|
|
||||||
|
fun size(): Int = heap.size
|
||||||
|
|
||||||
|
fun addString(type: DataType, str: String): Int {
|
||||||
|
if (str.length > 255)
|
||||||
|
throw IllegalArgumentException("string length must be 0-255")
|
||||||
|
|
||||||
|
// strings are 'interned' and shared if they're the isSameAs
|
||||||
|
val value = HeapValue(type, str, null, null)
|
||||||
|
|
||||||
|
val existing = heap.filter { it.value==value }.map { it.key }.firstOrNull()
|
||||||
|
if(existing!=null)
|
||||||
|
return existing
|
||||||
|
val newId = heapId++
|
||||||
|
heap[newId] = value
|
||||||
|
return newId
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addIntegerArray(type: DataType, array: Array<IntegerOrAddressOf>): Int {
|
||||||
|
// arrays are never shared, don't check for existing
|
||||||
|
if(type !in ArrayDatatypes)
|
||||||
|
throw CompilerException("wrong array type")
|
||||||
|
val newId = heapId++
|
||||||
|
heap[newId] = HeapValue(type, null, array, null)
|
||||||
|
return newId
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addDoublesArray(darray: DoubleArray): Int {
|
||||||
|
// arrays are never shared, don't check for existing
|
||||||
|
val newId = heapId++
|
||||||
|
heap[newId] = HeapValue(DataType.ARRAY_F, null, null, darray)
|
||||||
|
return newId
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateString(heapId: Int, str: String) {
|
||||||
|
val oldVal = heap[heapId] ?: throw IllegalArgumentException("heapId not found in heap")
|
||||||
|
if(oldVal.type in StringDatatypes) {
|
||||||
|
if (oldVal.str!!.length != str.length)
|
||||||
|
throw IllegalArgumentException("heap string length mismatch")
|
||||||
|
heap[heapId] = oldVal.copy(str = str)
|
||||||
|
}
|
||||||
|
else throw IllegalArgumentException("heap data type mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(heapId: Int): HeapValue {
|
||||||
|
return heap[heapId] ?:
|
||||||
|
throw IllegalArgumentException("heapId $heapId not found in heap")
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@ import prog8.ast.base.WordDatatypes
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.AssignTarget
|
import prog8.ast.statements.AssignTarget
|
||||||
import prog8.ast.statements.FunctionCallStatement
|
import prog8.ast.statements.FunctionCallStatement
|
||||||
import prog8.compiler.target.c64.MachineDefinition
|
|
||||||
import prog8.compiler.target.c64.MachineDefinition.C64Zeropage
|
import prog8.compiler.target.c64.MachineDefinition.C64Zeropage
|
||||||
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_HEX
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_HEX
|
||||||
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package prog8.vm
|
package prog8.vm
|
||||||
|
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.ByteDatatypes
|
||||||
|
import prog8.ast.base.DataType
|
||||||
|
import prog8.ast.base.WordDatatypes
|
||||||
import prog8.ast.expressions.ArrayLiteralValue
|
import prog8.ast.expressions.ArrayLiteralValue
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.expressions.StringLiteralValue
|
import prog8.ast.expressions.StringLiteralValue
|
||||||
import prog8.compiler.target.c64.Petscii
|
import prog8.compiler.target.c64.Petscii
|
||||||
|
import prog8.vm.astvm.VmExecutionException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
@ -16,7 +19,13 @@ import kotlin.math.pow
|
|||||||
* It contains a value of a variable during run time of the program and provides arithmetic operations on the value.
|
* It contains a value of a variable during run time of the program and provides arithmetic operations on the value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=null, val array: Array<Number>?=null) {
|
abstract class RuntimeValueBase(val type: DataType) {
|
||||||
|
abstract fun numericValue(): Number
|
||||||
|
abstract fun integerValue(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||||
|
|
||||||
val byteval: Short?
|
val byteval: Short?
|
||||||
val wordval: Int?
|
val wordval: Int?
|
||||||
@ -24,37 +33,16 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
val asBoolean: Boolean
|
val asBoolean: Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromLv(literalValue: NumericLiteralValue): RuntimeValue {
|
fun fromLv(literalValue: NumericLiteralValue): RuntimeValueNumeric {
|
||||||
return RuntimeValue(literalValue.type, num = literalValue.number)
|
return RuntimeValueNumeric(literalValue.type, num = literalValue.number)
|
||||||
}
|
|
||||||
|
|
||||||
fun fromLv(string: StringLiteralValue): RuntimeValue {
|
|
||||||
return RuntimeValue(string.type, str = string.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fromLv(array: ArrayLiteralValue): RuntimeValue {
|
|
||||||
return if (array.type == DataType.ARRAY_F) {
|
|
||||||
val doubleArray = array.value.map { (it as NumericLiteralValue).number }.toTypedArray()
|
|
||||||
RuntimeValue(array.type, array = doubleArray)
|
|
||||||
} else {
|
|
||||||
val resultArray = mutableListOf<Number>()
|
|
||||||
for (elt in array.value.withIndex()) {
|
|
||||||
if (elt.value is NumericLiteralValue)
|
|
||||||
resultArray.add((elt.value as NumericLiteralValue).number.toInt())
|
|
||||||
else {
|
|
||||||
TODO("ADDRESSOF ${elt.value}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RuntimeValue(array.type, array = resultArray.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
when(type) {
|
when (type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
val inum = num!!.toInt()
|
val inum = num.toInt()
|
||||||
if(inum !in 0 .. 255)
|
if (inum !in 0..255)
|
||||||
throw IllegalArgumentException("invalid value for ubyte: $inum")
|
throw IllegalArgumentException("invalid value for ubyte: $inum")
|
||||||
byteval = inum.toShort()
|
byteval = inum.toShort()
|
||||||
wordval = null
|
wordval = null
|
||||||
@ -62,8 +50,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
asBoolean = byteval != 0.toShort()
|
asBoolean = byteval != 0.toShort()
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val inum = num!!.toInt()
|
val inum = num.toInt()
|
||||||
if(inum !in -128 .. 127)
|
if (inum !in -128..127)
|
||||||
throw IllegalArgumentException("invalid value for byte: $inum")
|
throw IllegalArgumentException("invalid value for byte: $inum")
|
||||||
byteval = inum.toShort()
|
byteval = inum.toShort()
|
||||||
wordval = null
|
wordval = null
|
||||||
@ -71,8 +59,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
asBoolean = byteval != 0.toShort()
|
asBoolean = byteval != 0.toShort()
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
val inum = num!!.toInt()
|
val inum = num.toInt()
|
||||||
if(inum !in 0 .. 65535)
|
if (inum !in 0..65535)
|
||||||
throw IllegalArgumentException("invalid value for uword: $inum")
|
throw IllegalArgumentException("invalid value for uword: $inum")
|
||||||
wordval = inum
|
wordval = inum
|
||||||
byteval = null
|
byteval = null
|
||||||
@ -80,8 +68,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
asBoolean = wordval != 0
|
asBoolean = wordval != 0
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val inum = num!!.toInt()
|
val inum = num.toInt()
|
||||||
if(inum !in -32768 .. 32767)
|
if (inum !in -32768..32767)
|
||||||
throw IllegalArgumentException("invalid value for word: $inum")
|
throw IllegalArgumentException("invalid value for word: $inum")
|
||||||
wordval = inum
|
wordval = inum
|
||||||
byteval = null
|
byteval = null
|
||||||
@ -89,50 +77,38 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
asBoolean = wordval != 0
|
asBoolean = wordval != 0
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
floatval = num!!.toDouble()
|
floatval = num.toDouble()
|
||||||
byteval = null
|
byteval = null
|
||||||
wordval = null
|
wordval = null
|
||||||
asBoolean = floatval != 0.0
|
asBoolean = floatval != 0.0
|
||||||
}
|
}
|
||||||
else -> {
|
else -> throw VmExecutionException("not a numeric value")
|
||||||
byteval = null
|
|
||||||
wordval = null
|
|
||||||
floatval = null
|
|
||||||
asBoolean = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> "ub:%02x".format(byteval)
|
DataType.UBYTE -> "ub:%02x".format(byteval)
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
if(byteval!!<0)
|
if (byteval!! < 0)
|
||||||
"b:-%02x".format(abs(byteval.toInt()))
|
"b:-%02x".format(abs(byteval.toInt()))
|
||||||
else
|
else
|
||||||
"b:%02x".format(byteval)
|
"b:%02x".format(byteval)
|
||||||
}
|
}
|
||||||
DataType.UWORD -> "uw:%04x".format(wordval)
|
DataType.UWORD -> "uw:%04x".format(wordval)
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
if(wordval!!<0)
|
if (wordval!! < 0)
|
||||||
"w:-%04x".format(abs(wordval))
|
"w:-%04x".format(abs(wordval))
|
||||||
else
|
else
|
||||||
"w:%04x".format(wordval)
|
"w:%04x".format(wordval)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> "f:$floatval"
|
DataType.FLOAT -> "f:$floatval"
|
||||||
DataType.STR -> "str:$str"
|
else -> "???"
|
||||||
DataType.STR_S -> "str_s:$str"
|
|
||||||
DataType.ARRAY_UB -> "array_ub:..."
|
|
||||||
DataType.ARRAY_B -> "array_b:..."
|
|
||||||
DataType.ARRAY_UW -> "array_uw:..."
|
|
||||||
DataType.ARRAY_W -> "array_w:..."
|
|
||||||
DataType.ARRAY_F -> "array_f:..."
|
|
||||||
DataType.STRUCT -> "struct:..."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun numericValue(): Number {
|
override fun numericValue(): Number {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
in ByteDatatypes -> byteval!!
|
in ByteDatatypes -> byteval!!
|
||||||
in WordDatatypes -> wordval!!
|
in WordDatatypes -> wordval!!
|
||||||
DataType.FLOAT -> floatval!!
|
DataType.FLOAT -> floatval!!
|
||||||
@ -140,8 +116,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun integerValue(): Int {
|
override fun integerValue(): Int {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
in ByteDatatypes -> byteval!!.toInt()
|
in ByteDatatypes -> byteval!!.toInt()
|
||||||
in WordDatatypes -> wordval!!
|
in WordDatatypes -> wordval!!
|
||||||
DataType.FLOAT -> throw ArithmeticException("float to integer loss of precision")
|
DataType.FLOAT -> throw ArithmeticException("float to integer loss of precision")
|
||||||
@ -152,73 +128,69 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
override fun hashCode(): Int = Objects.hash(byteval, wordval, floatval, type)
|
override fun hashCode(): Int = Objects.hash(byteval, wordval, floatval, type)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if(other==null || other !is RuntimeValue)
|
if (other == null || other !is RuntimeValueNumeric)
|
||||||
return false
|
return false
|
||||||
return compareTo(other)==0 // note: datatype doesn't matter
|
return compareTo(other) == 0 // note: datatype doesn't matter
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun compareTo(other: RuntimeValue): Int {
|
operator fun compareTo(other: RuntimeValueNumeric): Int = numericValue().toDouble().compareTo(other.numericValue().toDouble())
|
||||||
return if (type in NumericDatatypes && other.type in NumericDatatypes)
|
|
||||||
numericValue().toDouble().compareTo(other.numericValue().toDouble())
|
|
||||||
else throw ArithmeticException("comparison can only be done between two numeric values")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun arithResult(leftDt: DataType, result: Number, rightDt: DataType, op: String): RuntimeValue {
|
private fun arithResult(leftDt: DataType, result: Number, rightDt: DataType, op: String): RuntimeValueNumeric {
|
||||||
if(leftDt!=rightDt)
|
if (leftDt != rightDt)
|
||||||
throw ArithmeticException("left and right datatypes are not the same")
|
throw ArithmeticException("left and right datatypes are not the same")
|
||||||
if(result.toDouble() < 0 ) {
|
if (result.toDouble() < 0) {
|
||||||
return when(leftDt) {
|
return when (leftDt) {
|
||||||
DataType.UBYTE, DataType.UWORD -> {
|
DataType.UBYTE, DataType.UWORD -> {
|
||||||
// storing a negative number in an unsigned one is done by storing the 2's complement instead
|
// storing a negative number in an unsigned one is done by storing the 2's complement instead
|
||||||
val number = abs(result.toDouble().toInt())
|
val number = abs(result.toDouble().toInt())
|
||||||
if(leftDt== DataType.UBYTE)
|
if (leftDt == DataType.UBYTE)
|
||||||
RuntimeValue(DataType.UBYTE, (number xor 255) + 1)
|
RuntimeValueNumeric(DataType.UBYTE, (number xor 255) + 1)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.UWORD, (number xor 65535) + 1)
|
RuntimeValueNumeric(DataType.UWORD, (number xor 65535) + 1)
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
|
||||||
val v=result.toInt() and 255
|
|
||||||
if(v<128)
|
|
||||||
RuntimeValue(DataType.BYTE, v)
|
|
||||||
else
|
|
||||||
RuntimeValue(DataType.BYTE, v-256)
|
|
||||||
}
|
|
||||||
DataType.WORD -> {
|
|
||||||
val v=result.toInt() and 65535
|
|
||||||
if(v<32768)
|
|
||||||
RuntimeValue(DataType.WORD, v)
|
|
||||||
else
|
|
||||||
RuntimeValue(DataType.WORD, v-65536)
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, result)
|
|
||||||
else -> throw ArithmeticException("$op on non-numeric type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return when(leftDt) {
|
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, result.toInt() and 255)
|
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val v = result.toInt() and 255
|
val v = result.toInt() and 255
|
||||||
if(v<128)
|
if (v < 128)
|
||||||
RuntimeValue(DataType.BYTE, v)
|
RuntimeValueNumeric(DataType.BYTE, v)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.BYTE, v-256)
|
RuntimeValueNumeric(DataType.BYTE, v - 256)
|
||||||
}
|
}
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, result.toInt() and 65535)
|
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val v = result.toInt() and 65535
|
val v = result.toInt() and 65535
|
||||||
if(v<32768)
|
if (v < 32768)
|
||||||
RuntimeValue(DataType.WORD, v)
|
RuntimeValueNumeric(DataType.WORD, v)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.WORD, v-65536)
|
RuntimeValueNumeric(DataType.WORD, v - 65536)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, result)
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, result)
|
||||||
else -> throw ArithmeticException("$op on non-numeric type")
|
else -> throw ArithmeticException("$op on non-numeric type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(other: RuntimeValue): RuntimeValue {
|
return when (leftDt) {
|
||||||
if(other.type == DataType.FLOAT && (type!= DataType.FLOAT))
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, result.toInt() and 255)
|
||||||
|
DataType.BYTE -> {
|
||||||
|
val v = result.toInt() and 255
|
||||||
|
if (v < 128)
|
||||||
|
RuntimeValueNumeric(DataType.BYTE, v)
|
||||||
|
else
|
||||||
|
RuntimeValueNumeric(DataType.BYTE, v - 256)
|
||||||
|
}
|
||||||
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, result.toInt() and 65535)
|
||||||
|
DataType.WORD -> {
|
||||||
|
val v = result.toInt() and 65535
|
||||||
|
if (v < 32768)
|
||||||
|
RuntimeValueNumeric(DataType.WORD, v)
|
||||||
|
else
|
||||||
|
RuntimeValueNumeric(DataType.WORD, v - 65536)
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, result)
|
||||||
|
else -> throw ArithmeticException("$op on non-numeric type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
|
if (other.type == DataType.FLOAT && (type != DataType.FLOAT))
|
||||||
throw ArithmeticException("floating point loss of precision on type $type")
|
throw ArithmeticException("floating point loss of precision on type $type")
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
@ -226,8 +198,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
return arithResult(type, result, other.type, "add")
|
return arithResult(type, result, other.type, "add")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sub(other: RuntimeValue): RuntimeValue {
|
fun sub(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
if(other.type == DataType.FLOAT && (type!= DataType.FLOAT))
|
if (other.type == DataType.FLOAT && (type != DataType.FLOAT))
|
||||||
throw ArithmeticException("floating point loss of precision on type $type")
|
throw ArithmeticException("floating point loss of precision on type $type")
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
@ -235,8 +207,8 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
return arithResult(type, result, other.type, "sub")
|
return arithResult(type, result, other.type, "sub")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mul(other: RuntimeValue): RuntimeValue {
|
fun mul(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
if(other.type == DataType.FLOAT && (type!= DataType.FLOAT))
|
if (other.type == DataType.FLOAT && (type != DataType.FLOAT))
|
||||||
throw ArithmeticException("floating point loss of precision on type $type")
|
throw ArithmeticException("floating point loss of precision on type $type")
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
@ -244,317 +216,318 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
return arithResult(type, result, other.type, "mul")
|
return arithResult(type, result, other.type, "mul")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun div(other: RuntimeValue): RuntimeValue {
|
fun div(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
if(other.type == DataType.FLOAT && (type!= DataType.FLOAT))
|
if (other.type == DataType.FLOAT && (type != DataType.FLOAT))
|
||||||
throw ArithmeticException("floating point loss of precision on type $type")
|
throw ArithmeticException("floating point loss of precision on type $type")
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
if(v2.toDouble()==0.0) {
|
if (v2.toDouble() == 0.0) {
|
||||||
when (type) {
|
when (type) {
|
||||||
DataType.UBYTE -> return RuntimeValue(DataType.UBYTE, 255)
|
DataType.UBYTE -> return RuntimeValueNumeric(DataType.UBYTE, 255)
|
||||||
DataType.BYTE -> return RuntimeValue(DataType.BYTE, 127)
|
DataType.BYTE -> return RuntimeValueNumeric(DataType.BYTE, 127)
|
||||||
DataType.UWORD -> return RuntimeValue(DataType.UWORD, 65535)
|
DataType.UWORD -> return RuntimeValueNumeric(DataType.UWORD, 65535)
|
||||||
DataType.WORD -> return RuntimeValue(DataType.WORD, 32767)
|
DataType.WORD -> return RuntimeValueNumeric(DataType.WORD, 32767)
|
||||||
else -> {}
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val result = v1.toDouble() / v2.toDouble()
|
val result = v1.toDouble() / v2.toDouble()
|
||||||
// NOTE: integer division returns integer result!
|
// NOTE: integer division returns integer result!
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, result)
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, result)
|
||||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, result)
|
DataType.BYTE -> RuntimeValueNumeric(DataType.BYTE, result)
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, result)
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, result)
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, result)
|
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, result)
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, result)
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, result)
|
||||||
else -> throw ArithmeticException("div on non-numeric type")
|
else -> throw ArithmeticException("div on non-numeric type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remainder(other: RuntimeValue): RuntimeValue {
|
fun remainder(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
val result = v1.toDouble() % v2.toDouble()
|
val result = v1.toDouble() % v2.toDouble()
|
||||||
return arithResult(type, result, other.type, "remainder")
|
return arithResult(type, result, other.type, "remainder")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pow(other: RuntimeValue): RuntimeValue {
|
fun pow(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
val result = v1.toDouble().pow(v2.toDouble())
|
val result = v1.toDouble().pow(v2.toDouble())
|
||||||
return arithResult(type, result, other.type,"pow")
|
return arithResult(type, result, other.type, "pow")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shl(): RuntimeValue {
|
fun shl(): RuntimeValueNumeric {
|
||||||
val v = integerValue()
|
val v = integerValue()
|
||||||
return when (type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(type, (v shl 1) and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(type, (v shl 1) and 255)
|
||||||
DataType.UWORD -> RuntimeValue(type, (v shl 1) and 65535)
|
DataType.UWORD -> RuntimeValueNumeric(type, (v shl 1) and 65535)
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val value = v shl 1
|
val value = v shl 1
|
||||||
if(value<128)
|
if (value < 128)
|
||||||
RuntimeValue(type, value)
|
RuntimeValueNumeric(type, value)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, value-256)
|
RuntimeValueNumeric(type, value - 256)
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val value = v shl 1
|
val value = v shl 1
|
||||||
if(value<32768)
|
if (value < 32768)
|
||||||
RuntimeValue(type, value)
|
RuntimeValueNumeric(type, value)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, value-65536)
|
RuntimeValueNumeric(type, value - 65536)
|
||||||
}
|
}
|
||||||
else -> throw ArithmeticException("invalid type for shl: $type")
|
else -> throw ArithmeticException("invalid type for shl: $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shr(): RuntimeValue {
|
fun shr(): RuntimeValueNumeric {
|
||||||
val v = integerValue()
|
val v = integerValue()
|
||||||
return when(type){
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(type, v ushr 1)
|
DataType.UBYTE -> RuntimeValueNumeric(type, v ushr 1)
|
||||||
DataType.BYTE -> RuntimeValue(type, v shr 1)
|
DataType.BYTE -> RuntimeValueNumeric(type, v shr 1)
|
||||||
DataType.UWORD -> RuntimeValue(type, v ushr 1)
|
DataType.UWORD -> RuntimeValueNumeric(type, v ushr 1)
|
||||||
DataType.WORD -> RuntimeValue(type, v shr 1)
|
DataType.WORD -> RuntimeValueNumeric(type, v shr 1)
|
||||||
else -> throw ArithmeticException("invalid type for shr: $type")
|
else -> throw ArithmeticException("invalid type for shr: $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rol(carry: Boolean): Pair<RuntimeValue, Boolean> {
|
fun rol(carry: Boolean): Pair<RuntimeValueNumeric, Boolean> {
|
||||||
// 9 or 17 bit rotate left (with carry))
|
// 9 or 17 bit rotate left (with carry))
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
val v = byteval!!.toInt()
|
val v = byteval!!.toInt()
|
||||||
val newCarry = (v and 0x80) != 0
|
val newCarry = (v and 0x80) != 0
|
||||||
val newval = (v and 0x7f shl 1) or (if(carry) 1 else 0)
|
val newval = (v and 0x7f shl 1) or (if (carry) 1 else 0)
|
||||||
Pair(RuntimeValue(DataType.UBYTE, newval), newCarry)
|
Pair(RuntimeValueNumeric(DataType.UBYTE, newval), newCarry)
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
val v = wordval!!
|
val v = wordval!!
|
||||||
val newCarry = (v and 0x8000) != 0
|
val newCarry = (v and 0x8000) != 0
|
||||||
val newval = (v and 0x7fff shl 1) or (if(carry) 1 else 0)
|
val newval = (v and 0x7fff shl 1) or (if (carry) 1 else 0)
|
||||||
Pair(RuntimeValue(DataType.UWORD, newval), newCarry)
|
Pair(RuntimeValueNumeric(DataType.UWORD, newval), newCarry)
|
||||||
}
|
}
|
||||||
else -> throw ArithmeticException("rol can only work on byte/word")
|
else -> throw ArithmeticException("rol can only work on byte/word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ror(carry: Boolean): Pair<RuntimeValue, Boolean> {
|
fun ror(carry: Boolean): Pair<RuntimeValueNumeric, Boolean> {
|
||||||
// 9 or 17 bit rotate right (with carry)
|
// 9 or 17 bit rotate right (with carry)
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
val v = byteval!!.toInt()
|
val v = byteval!!.toInt()
|
||||||
val newCarry = v and 1 != 0
|
val newCarry = v and 1 != 0
|
||||||
val newval = (v ushr 1) or (if(carry) 0x80 else 0)
|
val newval = (v ushr 1) or (if (carry) 0x80 else 0)
|
||||||
Pair(RuntimeValue(DataType.UBYTE, newval), newCarry)
|
Pair(RuntimeValueNumeric(DataType.UBYTE, newval), newCarry)
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
val v = wordval!!
|
val v = wordval!!
|
||||||
val newCarry = v and 1 != 0
|
val newCarry = v and 1 != 0
|
||||||
val newval = (v ushr 1) or (if(carry) 0x8000 else 0)
|
val newval = (v ushr 1) or (if (carry) 0x8000 else 0)
|
||||||
Pair(RuntimeValue(DataType.UWORD, newval), newCarry)
|
Pair(RuntimeValueNumeric(DataType.UWORD, newval), newCarry)
|
||||||
}
|
}
|
||||||
else -> throw ArithmeticException("ror2 can only work on byte/word")
|
else -> throw ArithmeticException("ror2 can only work on byte/word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rol2(): RuntimeValue {
|
fun rol2(): RuntimeValueNumeric {
|
||||||
// 8 or 16 bit rotate left
|
// 8 or 16 bit rotate left
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
val v = byteval!!.toInt()
|
val v = byteval!!.toInt()
|
||||||
val carry = (v and 0x80) ushr 7
|
val carry = (v and 0x80) ushr 7
|
||||||
val newval = (v and 0x7f shl 1) or carry
|
val newval = (v and 0x7f shl 1) or carry
|
||||||
RuntimeValue(DataType.UBYTE, newval)
|
RuntimeValueNumeric(DataType.UBYTE, newval)
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
val v = wordval!!
|
val v = wordval!!
|
||||||
val carry = (v and 0x8000) ushr 15
|
val carry = (v and 0x8000) ushr 15
|
||||||
val newval = (v and 0x7fff shl 1) or carry
|
val newval = (v and 0x7fff shl 1) or carry
|
||||||
RuntimeValue(DataType.UWORD, newval)
|
RuntimeValueNumeric(DataType.UWORD, newval)
|
||||||
}
|
}
|
||||||
else -> throw ArithmeticException("rol2 can only work on byte/word")
|
else -> throw ArithmeticException("rol2 can only work on byte/word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ror2(): RuntimeValue {
|
fun ror2(): RuntimeValueNumeric {
|
||||||
// 8 or 16 bit rotate right
|
// 8 or 16 bit rotate right
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
val v = byteval!!.toInt()
|
val v = byteval!!.toInt()
|
||||||
val carry = v and 1 shl 7
|
val carry = v and 1 shl 7
|
||||||
val newval = (v ushr 1) or carry
|
val newval = (v ushr 1) or carry
|
||||||
RuntimeValue(DataType.UBYTE, newval)
|
RuntimeValueNumeric(DataType.UBYTE, newval)
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
val v = wordval!!
|
val v = wordval!!
|
||||||
val carry = v and 1 shl 15
|
val carry = v and 1 shl 15
|
||||||
val newval = (v ushr 1) or carry
|
val newval = (v ushr 1) or carry
|
||||||
RuntimeValue(DataType.UWORD, newval)
|
RuntimeValueNumeric(DataType.UWORD, newval)
|
||||||
}
|
}
|
||||||
else -> throw ArithmeticException("ror2 can only work on byte/word")
|
else -> throw ArithmeticException("ror2 can only work on byte/word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun neg(): RuntimeValue {
|
fun neg(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, -(byteval!!))
|
DataType.BYTE -> RuntimeValueNumeric(DataType.BYTE, -(byteval!!))
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, -(wordval!!))
|
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, -(wordval!!))
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, -(floatval)!!)
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, -(floatval)!!)
|
||||||
else -> throw ArithmeticException("neg can only work on byte/word/float")
|
else -> throw ArithmeticException("neg can only work on byte/word/float")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun abs(): RuntimeValue {
|
fun abs(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, abs(byteval!!.toInt()))
|
DataType.BYTE -> RuntimeValueNumeric(DataType.BYTE, abs(byteval!!.toInt()))
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, abs(wordval!!))
|
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, abs(wordval!!))
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, abs(floatval!!))
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, abs(floatval!!))
|
||||||
else -> throw ArithmeticException("abs can only work on byte/word/float")
|
else -> throw ArithmeticException("abs can only work on byte/word/float")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitand(other: RuntimeValue): RuntimeValue {
|
fun bitand(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
val v1 = integerValue()
|
val v1 = integerValue()
|
||||||
val v2 = other.integerValue()
|
val v2 = other.integerValue()
|
||||||
val result = v1 and v2
|
val result = v1 and v2
|
||||||
return RuntimeValue(type, result)
|
return RuntimeValueNumeric(type, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitor(other: RuntimeValue): RuntimeValue {
|
fun bitor(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
val v1 = integerValue()
|
val v1 = integerValue()
|
||||||
val v2 = other.integerValue()
|
val v2 = other.integerValue()
|
||||||
val result = v1 or v2
|
val result = v1 or v2
|
||||||
return RuntimeValue(type, result)
|
return RuntimeValueNumeric(type, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitxor(other: RuntimeValue): RuntimeValue {
|
fun bitxor(other: RuntimeValueNumeric): RuntimeValueNumeric {
|
||||||
val v1 = integerValue()
|
val v1 = integerValue()
|
||||||
val v2 = other.integerValue()
|
val v2 = other.integerValue()
|
||||||
val result = v1 xor v2
|
val result = v1 xor v2
|
||||||
return RuntimeValue(type, result)
|
return RuntimeValueNumeric(type, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun and(other: RuntimeValue) = RuntimeValue(DataType.UBYTE, if (this.asBoolean && other.asBoolean) 1 else 0)
|
fun and(other: RuntimeValueNumeric) = RuntimeValueNumeric(DataType.UBYTE, if (this.asBoolean && other.asBoolean) 1 else 0)
|
||||||
fun or(other: RuntimeValue) = RuntimeValue(DataType.UBYTE, if (this.asBoolean || other.asBoolean) 1 else 0)
|
fun or(other: RuntimeValueNumeric) = RuntimeValueNumeric(DataType.UBYTE, if (this.asBoolean || other.asBoolean) 1 else 0)
|
||||||
fun xor(other: RuntimeValue) = RuntimeValue(DataType.UBYTE, if (this.asBoolean xor other.asBoolean) 1 else 0)
|
fun xor(other: RuntimeValueNumeric) = RuntimeValueNumeric(DataType.UBYTE, if (this.asBoolean xor other.asBoolean) 1 else 0)
|
||||||
fun not() = RuntimeValue(DataType.UBYTE, if (this.asBoolean) 0 else 1)
|
fun not() = RuntimeValueNumeric(DataType.UBYTE, if (this.asBoolean) 0 else 1)
|
||||||
|
|
||||||
fun inv(): RuntimeValue {
|
fun inv(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(type, byteval!!.toInt().inv() and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(type, byteval!!.toInt().inv() and 255)
|
||||||
DataType.UWORD -> RuntimeValue(type, wordval!!.inv() and 65535)
|
DataType.UWORD -> RuntimeValueNumeric(type, wordval!!.inv() and 65535)
|
||||||
DataType.BYTE -> RuntimeValue(type, byteval!!.toInt().inv())
|
DataType.BYTE -> RuntimeValueNumeric(type, byteval!!.toInt().inv())
|
||||||
DataType.WORD -> RuntimeValue(type, wordval!!.inv())
|
DataType.WORD -> RuntimeValueNumeric(type, wordval!!.inv())
|
||||||
else -> throw ArithmeticException("inv can only work on byte/word")
|
else -> throw ArithmeticException("inv can only work on byte/word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inc(): RuntimeValue {
|
fun inc(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(type, (byteval!! + 1) and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(type, (byteval!! + 1) and 255)
|
||||||
DataType.UWORD -> RuntimeValue(type, (wordval!! + 1) and 65535)
|
DataType.UWORD -> RuntimeValueNumeric(type, (wordval!! + 1) and 65535)
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val newval = byteval!! + 1
|
val newval = byteval!! + 1
|
||||||
if(newval == 128)
|
if (newval == 128)
|
||||||
RuntimeValue(type, -128)
|
RuntimeValueNumeric(type, -128)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, newval)
|
RuntimeValueNumeric(type, newval)
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val newval = wordval!! + 1
|
val newval = wordval!! + 1
|
||||||
if(newval == 32768)
|
if (newval == 32768)
|
||||||
RuntimeValue(type, -32768)
|
RuntimeValueNumeric(type, -32768)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, newval)
|
RuntimeValueNumeric(type, newval)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, floatval!! + 1)
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, floatval!! + 1)
|
||||||
else -> throw ArithmeticException("inc can only work on numeric types")
|
else -> throw ArithmeticException("inc can only work on numeric types")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dec(): RuntimeValue {
|
fun dec(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> RuntimeValue(type, (byteval!! - 1) and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(type, (byteval!! - 1) and 255)
|
||||||
DataType.UWORD -> RuntimeValue(type, (wordval!! - 1) and 65535)
|
DataType.UWORD -> RuntimeValueNumeric(type, (wordval!! - 1) and 65535)
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val newval = byteval!! - 1
|
val newval = byteval!! - 1
|
||||||
if(newval == -129)
|
if (newval == -129)
|
||||||
RuntimeValue(type, 127)
|
RuntimeValueNumeric(type, 127)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, newval)
|
RuntimeValueNumeric(type, newval)
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val newval = wordval!! - 1
|
val newval = wordval!! - 1
|
||||||
if(newval == -32769)
|
if (newval == -32769)
|
||||||
RuntimeValue(type, 32767)
|
RuntimeValueNumeric(type, 32767)
|
||||||
else
|
else
|
||||||
RuntimeValue(type, newval)
|
RuntimeValueNumeric(type, newval)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, floatval!! - 1)
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, floatval!! - 1)
|
||||||
else -> throw ArithmeticException("dec can only work on numeric types")
|
else -> throw ArithmeticException("dec can only work on numeric types")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun msb(): RuntimeValue {
|
fun msb(): RuntimeValueNumeric {
|
||||||
return when(type) {
|
return when (type) {
|
||||||
in ByteDatatypes -> RuntimeValue(DataType.UBYTE, 0)
|
in ByteDatatypes -> RuntimeValueNumeric(DataType.UBYTE, 0)
|
||||||
in WordDatatypes -> RuntimeValue(DataType.UBYTE, wordval!! ushr 8 and 255)
|
in WordDatatypes -> RuntimeValueNumeric(DataType.UBYTE, wordval!! ushr 8 and 255)
|
||||||
else -> throw ArithmeticException("msb can only work on (u)byte/(u)word")
|
else -> throw ArithmeticException("msb can only work on (u)byte/(u)word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cast(targetType: DataType): RuntimeValue {
|
fun cast(targetType: DataType): RuntimeValueNumeric {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (targetType) {
|
when (targetType) {
|
||||||
DataType.UBYTE -> this
|
DataType.UBYTE -> this
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val nval=byteval!!.toInt()
|
val nval = byteval!!.toInt()
|
||||||
if(nval<128)
|
if (nval < 128)
|
||||||
RuntimeValue(DataType.BYTE, nval)
|
RuntimeValueNumeric(DataType.BYTE, nval)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.BYTE, nval-256)
|
RuntimeValueNumeric(DataType.BYTE, nval - 256)
|
||||||
}
|
}
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, numericValue())
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, numericValue())
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val nval = numericValue().toInt()
|
val nval = numericValue().toInt()
|
||||||
if(nval<32768)
|
if (nval < 32768)
|
||||||
RuntimeValue(DataType.WORD, nval)
|
RuntimeValueNumeric(DataType.WORD, nval)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.WORD, nval-65536)
|
RuntimeValueNumeric(DataType.WORD, nval - 65536)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, numericValue())
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, numericValue())
|
||||||
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
when (targetType) {
|
when (targetType) {
|
||||||
DataType.BYTE -> this
|
DataType.BYTE -> this
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, integerValue() and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, integerValue() and 255)
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, integerValue() and 65535)
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, integerValue() and 65535)
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, integerValue())
|
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, integerValue())
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, numericValue())
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, numericValue())
|
||||||
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
when (targetType) {
|
when (targetType) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val v=integerValue()
|
val v = integerValue()
|
||||||
if(v<128)
|
if (v < 128)
|
||||||
RuntimeValue(DataType.BYTE, v)
|
RuntimeValueNumeric(DataType.BYTE, v)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.BYTE, v-256)
|
RuntimeValueNumeric(DataType.BYTE, v - 256)
|
||||||
}
|
}
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, integerValue() and 255)
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, integerValue() and 255)
|
||||||
DataType.UWORD -> this
|
DataType.UWORD -> this
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val v=integerValue()
|
val v = integerValue()
|
||||||
if(v<32768)
|
if (v < 32768)
|
||||||
RuntimeValue(DataType.WORD, v)
|
RuntimeValueNumeric(DataType.WORD, v)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.WORD, v-65536)
|
RuntimeValueNumeric(DataType.WORD, v - 65536)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, numericValue())
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, numericValue())
|
||||||
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -562,33 +535,33 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
when (targetType) {
|
when (targetType) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val v = integerValue() and 255
|
val v = integerValue() and 255
|
||||||
if(v<128)
|
if (v < 128)
|
||||||
RuntimeValue(DataType.BYTE, v)
|
RuntimeValueNumeric(DataType.BYTE, v)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.BYTE, v-256)
|
RuntimeValueNumeric(DataType.BYTE, v - 256)
|
||||||
}
|
}
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, integerValue() and 65535)
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, integerValue() and 65535)
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, integerValue())
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, integerValue())
|
||||||
DataType.WORD -> this
|
DataType.WORD -> this
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, numericValue())
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, numericValue())
|
||||||
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
when (targetType) {
|
when (targetType) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val integer=numericValue().toInt()
|
val integer = numericValue().toInt()
|
||||||
if(integer in -128..127)
|
if (integer in -128..127)
|
||||||
RuntimeValue(DataType.BYTE, integer)
|
RuntimeValueNumeric(DataType.BYTE, integer)
|
||||||
else
|
else
|
||||||
throw ArithmeticException("overflow when casting float to byte: $this")
|
throw ArithmeticException("overflow when casting float to byte: $this")
|
||||||
}
|
}
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, numericValue().toInt())
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, numericValue().toInt())
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, numericValue().toInt())
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, numericValue().toInt())
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val integer=numericValue().toInt()
|
val integer = numericValue().toInt()
|
||||||
if(integer in -32768..32767)
|
if (integer in -32768..32767)
|
||||||
RuntimeValue(DataType.WORD, integer)
|
RuntimeValueNumeric(DataType.WORD, integer)
|
||||||
else
|
else
|
||||||
throw ArithmeticException("overflow when casting float to word: $this")
|
throw ArithmeticException("overflow when casting float to word: $this")
|
||||||
}
|
}
|
||||||
@ -599,22 +572,97 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
else -> throw ArithmeticException("invalid type cast from $type to $targetType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open fun iterator(): Iterator<Number> {
|
|
||||||
|
class RuntimeValueString(type: DataType, val str: String): RuntimeValueBase(type) {
|
||||||
|
companion object {
|
||||||
|
fun fromLv(string: StringLiteralValue): RuntimeValueString {
|
||||||
|
return RuntimeValueString(string.type, str = string.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
in StringDatatypes -> {
|
DataType.STR -> "str:$str"
|
||||||
Petscii.encodePetscii(str!!, true).iterator()
|
DataType.STR_S -> "str_s:$str"
|
||||||
|
else -> "???"
|
||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
|
||||||
array!!.iterator()
|
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("cannot iterate over $this")
|
|
||||||
|
override fun hashCode(): Int = Objects.hash(type, str)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other == null || other !is RuntimeValueString)
|
||||||
|
return false
|
||||||
|
return type == other.type && str == other.str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun iterator(): Iterator<Number> = Petscii.encodePetscii(str, true).iterator()
|
||||||
|
|
||||||
|
override fun numericValue(): Number {
|
||||||
|
throw VmExecutionException("string is not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun integerValue(): Int {
|
||||||
|
throw VmExecutionException("string is not a number")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValue(type, array=range.toList().toTypedArray()) {
|
open class RuntimeValueArray(type: DataType, val array: Array<Number>): RuntimeValueBase(type) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromLv(array: ArrayLiteralValue): RuntimeValueArray {
|
||||||
|
return if (array.type == DataType.ARRAY_F) {
|
||||||
|
val doubleArray = array.value.map { (it as NumericLiteralValue).number }.toTypedArray()
|
||||||
|
RuntimeValueArray(array.type, array = doubleArray)
|
||||||
|
} else {
|
||||||
|
val resultArray = mutableListOf<Number>()
|
||||||
|
for (elt in array.value.withIndex()) {
|
||||||
|
if (elt.value is NumericLiteralValue)
|
||||||
|
resultArray.add((elt.value as NumericLiteralValue).number.toInt())
|
||||||
|
else {
|
||||||
|
TODO("ADDRESSOF ${elt.value}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RuntimeValueArray(array.type, array = resultArray.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return when (type) {
|
||||||
|
DataType.ARRAY_UB -> "array_ub:..."
|
||||||
|
DataType.ARRAY_B -> "array_b:..."
|
||||||
|
DataType.ARRAY_UW -> "array_uw:..."
|
||||||
|
DataType.ARRAY_W -> "array_w:..."
|
||||||
|
DataType.ARRAY_F -> "array_f:..."
|
||||||
|
else -> "???"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = Objects.hash(type, array)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other == null || other !is RuntimeValueArray)
|
||||||
|
return false
|
||||||
|
return type == other.type && array.contentEquals(other.array)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun iterator(): Iterator<Number> = array.iterator()
|
||||||
|
|
||||||
|
override fun numericValue(): Number {
|
||||||
|
throw VmExecutionException("array is not a number")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun integerValue(): Int {
|
||||||
|
throw VmExecutionException("array is not a number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValueArray(type, range.toList().toTypedArray()) {
|
||||||
override fun iterator(): Iterator<Number> {
|
override fun iterator(): Iterator<Number> {
|
||||||
return range.iterator()
|
return range.iterator()
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ import prog8.ast.statements.*
|
|||||||
import prog8.compiler.IntegerOrAddressOf
|
import prog8.compiler.IntegerOrAddressOf
|
||||||
import prog8.compiler.target.c64.MachineDefinition
|
import prog8.compiler.target.c64.MachineDefinition
|
||||||
import prog8.compiler.target.c64.Petscii
|
import prog8.compiler.target.c64.Petscii
|
||||||
import prog8.vm.RuntimeValue
|
import prog8.vm.*
|
||||||
import prog8.vm.RuntimeValueRange
|
|
||||||
import java.awt.EventQueue
|
import java.awt.EventQueue
|
||||||
import java.io.CharConversionException
|
import java.io.CharConversionException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -72,7 +71,7 @@ class StatusFlags {
|
|||||||
|
|
||||||
|
|
||||||
class RuntimeVariables {
|
class RuntimeVariables {
|
||||||
fun define(scope: INameScope, name: String, initialValue: RuntimeValue) {
|
fun define(scope: INameScope, name: String, initialValue: RuntimeValueBase) {
|
||||||
val where = vars.getValue(scope)
|
val where = vars.getValue(scope)
|
||||||
where[name] = initialValue
|
where[name] = initialValue
|
||||||
vars[scope] = where
|
vars[scope] = where
|
||||||
@ -84,7 +83,7 @@ class RuntimeVariables {
|
|||||||
memvars[scope] = where
|
memvars[scope] = where
|
||||||
}
|
}
|
||||||
|
|
||||||
fun set(scope: INameScope, name: String, value: RuntimeValue) {
|
fun set(scope: INameScope, name: String, value: RuntimeValueBase) {
|
||||||
val where = vars.getValue(scope)
|
val where = vars.getValue(scope)
|
||||||
val existing = where[name]
|
val existing = where[name]
|
||||||
if(existing==null) {
|
if(existing==null) {
|
||||||
@ -98,7 +97,7 @@ class RuntimeVariables {
|
|||||||
vars[scope] = where
|
vars[scope] = where
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(scope: INameScope, name: String): RuntimeValue {
|
fun get(scope: INameScope, name: String): RuntimeValueBase {
|
||||||
val where = vars.getValue(scope)
|
val where = vars.getValue(scope)
|
||||||
return where[name] ?: throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
return where[name] ?: throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||||
}
|
}
|
||||||
@ -117,7 +116,7 @@ class RuntimeVariables {
|
|||||||
set(scope2, name2, v1)
|
set(scope2, name2, v1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val vars = mutableMapOf<INameScope, MutableMap<String, RuntimeValue>>().withDefault { mutableMapOf() }
|
private val vars = mutableMapOf<INameScope, MutableMap<String, RuntimeValueBase>>().withDefault { mutableMapOf() }
|
||||||
private val memvars = mutableMapOf<INameScope, MutableMap<String, Int>>().withDefault { mutableMapOf() }
|
private val memvars = mutableMapOf<INameScope, MutableMap<String, Int>>().withDefault { mutableMapOf() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,9 +133,9 @@ class AstVm(val program: Program) {
|
|||||||
|
|
||||||
private val rnd = Random(0)
|
private val rnd = Random(0)
|
||||||
private val statusFlagsSave = Stack<StatusFlags>()
|
private val statusFlagsSave = Stack<StatusFlags>()
|
||||||
private val registerXsave = Stack<RuntimeValue>()
|
private val registerXsave = Stack<RuntimeValueNumeric>()
|
||||||
private val registerYsave = Stack<RuntimeValue>()
|
private val registerYsave = Stack<RuntimeValueNumeric>()
|
||||||
private val registerAsave = Stack<RuntimeValue>()
|
private val registerAsave = Stack<RuntimeValueNumeric>()
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -182,7 +181,7 @@ class AstVm(val program: Program) {
|
|||||||
|
|
||||||
fun run() {
|
fun run() {
|
||||||
try {
|
try {
|
||||||
val init = VariablesCreator(runtimeVariables, program.heap)
|
val init = VariablesCreator(runtimeVariables)
|
||||||
init.visit(program)
|
init.visit(program)
|
||||||
|
|
||||||
// initialize all global variables
|
// initialize all global variables
|
||||||
@ -263,11 +262,11 @@ class AstVm(val program: Program) {
|
|||||||
|
|
||||||
class LoopControlBreak : Exception()
|
class LoopControlBreak : Exception()
|
||||||
class LoopControlContinue : Exception()
|
class LoopControlContinue : Exception()
|
||||||
class LoopControlReturn(val returnvalue: RuntimeValue?) : Exception()
|
class LoopControlReturn(val returnvalue: RuntimeValueNumeric?) : Exception()
|
||||||
class LoopControlJump(val identifier: IdentifierReference?, val address: Int?, val generatedLabel: String?) : Exception()
|
class LoopControlJump(val identifier: IdentifierReference?, val address: Int?, val generatedLabel: String?) : Exception()
|
||||||
|
|
||||||
|
|
||||||
internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValue>, startAtLabel: Label?=null): RuntimeValue? {
|
internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValueNumeric>, startAtLabel: Label?=null): RuntimeValueNumeric? {
|
||||||
if(sub.isAsmSubroutine) {
|
if(sub.isAsmSubroutine) {
|
||||||
return performSyscall(sub, arguments)
|
return performSyscall(sub, arguments)
|
||||||
}
|
}
|
||||||
@ -335,7 +334,7 @@ class AstVm(val program: Program) {
|
|||||||
val target = stmt.target.targetStatement(program.namespace)
|
val target = stmt.target.targetStatement(program.namespace)
|
||||||
when (target) {
|
when (target) {
|
||||||
is Subroutine -> {
|
is Subroutine -> {
|
||||||
val args = evaluate(stmt.arglist)
|
val args = evaluate(stmt.arglist).map { it as RuntimeValueNumeric }
|
||||||
if (target.isAsmSubroutine) {
|
if (target.isAsmSubroutine) {
|
||||||
performSyscall(target, args)
|
performSyscall(target, args)
|
||||||
} else {
|
} else {
|
||||||
@ -348,7 +347,7 @@ class AstVm(val program: Program) {
|
|||||||
// swap cannot be implemented as a function, so inline it here
|
// swap cannot be implemented as a function, so inline it here
|
||||||
executeSwap(stmt)
|
executeSwap(stmt)
|
||||||
} else {
|
} else {
|
||||||
val args = evaluate(stmt.arglist)
|
val args = evaluate(stmt.arglist).map { it as RuntimeValueNumeric }
|
||||||
performBuiltinFunction(target.name, args, statusflags)
|
performBuiltinFunction(target.name, args, statusflags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,7 +361,7 @@ class AstVm(val program: Program) {
|
|||||||
if(stmt.value==null)
|
if(stmt.value==null)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
evaluate(stmt.value!!, evalCtx)
|
evaluate(stmt.value!!, evalCtx) as RuntimeValueNumeric
|
||||||
throw LoopControlReturn(value)
|
throw LoopControlReturn(value)
|
||||||
}
|
}
|
||||||
is Continue -> throw LoopControlContinue()
|
is Continue -> throw LoopControlContinue()
|
||||||
@ -380,10 +379,10 @@ class AstVm(val program: Program) {
|
|||||||
val identScope = ident.definingScope()
|
val identScope = ident.definingScope()
|
||||||
when(ident.type){
|
when(ident.type){
|
||||||
VarDeclType.VAR -> {
|
VarDeclType.VAR -> {
|
||||||
var value = runtimeVariables.get(identScope, ident.name)
|
var value = runtimeVariables.get(identScope, ident.name) as RuntimeValueNumeric
|
||||||
value = when {
|
value = when {
|
||||||
stmt.operator == "++" -> value.add(RuntimeValue(value.type, 1))
|
stmt.operator == "++" -> value.add(RuntimeValueNumeric(value.type, 1))
|
||||||
stmt.operator == "--" -> value.sub(RuntimeValue(value.type, 1))
|
stmt.operator == "--" -> value.sub(RuntimeValueNumeric(value.type, 1))
|
||||||
else -> throw VmExecutionException("strange postincdec operator $stmt")
|
else -> throw VmExecutionException("strange postincdec operator $stmt")
|
||||||
}
|
}
|
||||||
runtimeVariables.set(identScope, ident.name, value)
|
runtimeVariables.set(identScope, ident.name, value)
|
||||||
@ -401,7 +400,7 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stmt.target.memoryAddress != null -> {
|
stmt.target.memoryAddress != null -> {
|
||||||
val addr = evaluate(stmt.target.memoryAddress!!.addressExpression, evalCtx).integerValue()
|
val addr = (evaluate(stmt.target.memoryAddress!!.addressExpression, evalCtx) as RuntimeValueNumeric).integerValue()
|
||||||
val newval = when {
|
val newval = when {
|
||||||
stmt.operator == "++" -> mem.getUByte(addr)+1 and 255
|
stmt.operator == "++" -> mem.getUByte(addr)+1 and 255
|
||||||
stmt.operator == "--" -> mem.getUByte(addr)-1 and 255
|
stmt.operator == "--" -> mem.getUByte(addr)-1 and 255
|
||||||
@ -411,12 +410,12 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
stmt.target.arrayindexed != null -> {
|
stmt.target.arrayindexed != null -> {
|
||||||
val arrayvar = stmt.target.arrayindexed!!.identifier.targetVarDecl(program.namespace)!!
|
val arrayvar = stmt.target.arrayindexed!!.identifier.targetVarDecl(program.namespace)!!
|
||||||
val arrayvalue = runtimeVariables.get(arrayvar.definingScope(), arrayvar.name)
|
val arrayvalue = runtimeVariables.get(arrayvar.definingScope(), arrayvar.name) as RuntimeValueArray
|
||||||
val index = evaluate(stmt.target.arrayindexed!!.arrayspec.index, evalCtx).integerValue()
|
val index = (evaluate(stmt.target.arrayindexed!!.arrayspec.index, evalCtx) as RuntimeValueNumeric).integerValue()
|
||||||
val elementType = stmt.target.arrayindexed!!.inferType(program)
|
val elementType = stmt.target.arrayindexed!!.inferType(program)
|
||||||
if(!elementType.isKnown)
|
if(!elementType.isKnown)
|
||||||
throw VmExecutionException("unknown/void elt type")
|
throw VmExecutionException("unknown/void elt type")
|
||||||
var value = RuntimeValue(elementType.typeOrElse(DataType.BYTE), arrayvalue.array!![index].toInt())
|
var value = RuntimeValueNumeric(elementType.typeOrElse(DataType.BYTE), arrayvalue.array[index].toInt())
|
||||||
value = when {
|
value = when {
|
||||||
stmt.operator == "++" -> value.inc()
|
stmt.operator == "++" -> value.inc()
|
||||||
stmt.operator == "--" -> value.dec()
|
stmt.operator == "--" -> value.dec()
|
||||||
@ -425,10 +424,10 @@ class AstVm(val program: Program) {
|
|||||||
arrayvalue.array[index] = value.numericValue()
|
arrayvalue.array[index] = value.numericValue()
|
||||||
}
|
}
|
||||||
stmt.target.register != null -> {
|
stmt.target.register != null -> {
|
||||||
var value = runtimeVariables.get(program.namespace, stmt.target.register!!.name)
|
var value = runtimeVariables.get(program.namespace, stmt.target.register!!.name) as RuntimeValueNumeric
|
||||||
value = when {
|
value = when {
|
||||||
stmt.operator == "++" -> value.add(RuntimeValue(value.type, 1))
|
stmt.operator == "++" -> value.add(RuntimeValueNumeric(value.type, 1))
|
||||||
stmt.operator == "--" -> value.sub(RuntimeValue(value.type, 1))
|
stmt.operator == "--" -> value.sub(RuntimeValueNumeric(value.type, 1))
|
||||||
else -> throw VmExecutionException("strange postincdec operator $stmt")
|
else -> throw VmExecutionException("strange postincdec operator $stmt")
|
||||||
}
|
}
|
||||||
runtimeVariables.set(program.namespace, stmt.target.register!!.name, value)
|
runtimeVariables.set(program.namespace, stmt.target.register!!.name, value)
|
||||||
@ -439,7 +438,7 @@ class AstVm(val program: Program) {
|
|||||||
is Jump -> throw LoopControlJump(stmt.identifier, stmt.address, stmt.generatedLabel)
|
is Jump -> throw LoopControlJump(stmt.identifier, stmt.address, stmt.generatedLabel)
|
||||||
is InlineAssembly -> {
|
is InlineAssembly -> {
|
||||||
if (sub is Subroutine) {
|
if (sub is Subroutine) {
|
||||||
val args = sub.parameters.map { runtimeVariables.get(sub, it.name) }
|
val args = sub.parameters.map { runtimeVariables.get(sub, it.name) as RuntimeValueNumeric }
|
||||||
performSyscall(sub, args)
|
performSyscall(sub, args)
|
||||||
throw LoopControlReturn(null)
|
throw LoopControlReturn(null)
|
||||||
}
|
}
|
||||||
@ -447,7 +446,7 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
is AnonymousScope -> executeAnonymousScope(stmt)
|
is AnonymousScope -> executeAnonymousScope(stmt)
|
||||||
is IfStatement -> {
|
is IfStatement -> {
|
||||||
val condition = evaluate(stmt.condition, evalCtx)
|
val condition = evaluate(stmt.condition, evalCtx) as RuntimeValueNumeric
|
||||||
if (condition.asBoolean)
|
if (condition.asBoolean)
|
||||||
executeAnonymousScope(stmt.truepart)
|
executeAnonymousScope(stmt.truepart)
|
||||||
else
|
else
|
||||||
@ -478,7 +477,13 @@ class AstVm(val program: Program) {
|
|||||||
loopvarDt = dt.typeOrElse(DataType.UBYTE)
|
loopvarDt = dt.typeOrElse(DataType.UBYTE)
|
||||||
loopvar = stmt.loopVar!!
|
loopvar = stmt.loopVar!!
|
||||||
}
|
}
|
||||||
val iterator = iterable.iterator()
|
val iterator =
|
||||||
|
when (iterable) {
|
||||||
|
is RuntimeValueRange -> iterable.iterator()
|
||||||
|
is RuntimeValueArray -> iterable.iterator()
|
||||||
|
is RuntimeValueString -> iterable.iterator()
|
||||||
|
else -> throw VmExecutionException("not iterable")
|
||||||
|
}
|
||||||
for (loopvalue in iterator) {
|
for (loopvalue in iterator) {
|
||||||
try {
|
try {
|
||||||
oneForCycle(stmt, loopvarDt, loopvalue, loopvar)
|
oneForCycle(stmt, loopvarDt, loopvalue, loopvar)
|
||||||
@ -490,11 +495,11 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is WhileLoop -> {
|
is WhileLoop -> {
|
||||||
var condition = evaluate(stmt.condition, evalCtx)
|
var condition = evaluate(stmt.condition, evalCtx) as RuntimeValueNumeric
|
||||||
while (condition.asBoolean) {
|
while (condition.asBoolean) {
|
||||||
try {
|
try {
|
||||||
executeAnonymousScope(stmt.body)
|
executeAnonymousScope(stmt.body)
|
||||||
condition = evaluate(stmt.condition, evalCtx)
|
condition = evaluate(stmt.condition, evalCtx) as RuntimeValueNumeric
|
||||||
} catch (b: LoopControlBreak) {
|
} catch (b: LoopControlBreak) {
|
||||||
break
|
break
|
||||||
} catch (c: LoopControlContinue) {
|
} catch (c: LoopControlContinue) {
|
||||||
@ -504,7 +509,7 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
is RepeatLoop -> {
|
is RepeatLoop -> {
|
||||||
do {
|
do {
|
||||||
val condition = evaluate(stmt.untilCondition, evalCtx)
|
val condition = evaluate(stmt.untilCondition, evalCtx) as RuntimeValueNumeric
|
||||||
try {
|
try {
|
||||||
executeAnonymousScope(stmt.body)
|
executeAnonymousScope(stmt.body)
|
||||||
} catch (b: LoopControlBreak) {
|
} catch (b: LoopControlBreak) {
|
||||||
@ -515,7 +520,7 @@ class AstVm(val program: Program) {
|
|||||||
} while (!condition.asBoolean)
|
} while (!condition.asBoolean)
|
||||||
}
|
}
|
||||||
is WhenStatement -> {
|
is WhenStatement -> {
|
||||||
val condition=evaluate(stmt.condition, evalCtx)
|
val condition=evaluate(stmt.condition, evalCtx) as RuntimeValueNumeric
|
||||||
for(choice in stmt.choices) {
|
for(choice in stmt.choices) {
|
||||||
if(choice.values==null) {
|
if(choice.values==null) {
|
||||||
// the 'else' choice
|
// the 'else' choice
|
||||||
@ -523,7 +528,7 @@ class AstVm(val program: Program) {
|
|||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
val value = choice.values!!.single().constValue(evalCtx.program) ?: throw VmExecutionException("can only use const values in when choices ${choice.position}")
|
val value = choice.values!!.single().constValue(evalCtx.program) ?: throw VmExecutionException("can only use const values in when choices ${choice.position}")
|
||||||
val rtval = RuntimeValue.fromLv(value)
|
val rtval = RuntimeValueNumeric.fromLv(value)
|
||||||
if(condition==rtval) {
|
if(condition==rtval) {
|
||||||
executeAnonymousScope(choice.statements)
|
executeAnonymousScope(choice.statements)
|
||||||
break
|
break
|
||||||
@ -548,7 +553,7 @@ class AstVm(val program: Program) {
|
|||||||
performAssignment(target2, value1, swap, evalCtx)
|
performAssignment(target2, value1, swap, evalCtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun performAssignment(target: AssignTarget, value: RuntimeValue, contextStmt: Statement, evalCtx: EvalContext) {
|
fun performAssignment(target: AssignTarget, value: RuntimeValueBase, contextStmt: Statement, evalCtx: EvalContext) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIndexed = target.arrayindexed
|
val targetArrayIndexed = target.arrayindexed
|
||||||
when {
|
when {
|
||||||
@ -558,27 +563,27 @@ class AstVm(val program: Program) {
|
|||||||
if (decl.type == VarDeclType.MEMORY) {
|
if (decl.type == VarDeclType.MEMORY) {
|
||||||
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
||||||
when (decl.datatype) {
|
when (decl.datatype) {
|
||||||
DataType.UBYTE -> mem.setUByte(address, value.byteval!!)
|
DataType.UBYTE -> mem.setUByte(address, (value as RuntimeValueNumeric).byteval!!)
|
||||||
DataType.BYTE -> mem.setSByte(address, value.byteval!!)
|
DataType.BYTE -> mem.setSByte(address, (value as RuntimeValueNumeric).byteval!!)
|
||||||
DataType.UWORD -> mem.setUWord(address, value.wordval!!)
|
DataType.UWORD -> mem.setUWord(address, (value as RuntimeValueNumeric).wordval!!)
|
||||||
DataType.WORD -> mem.setSWord(address, value.wordval!!)
|
DataType.WORD -> mem.setSWord(address, (value as RuntimeValueNumeric).wordval!!)
|
||||||
DataType.FLOAT -> mem.setFloat(address, value.floatval!!)
|
DataType.FLOAT -> mem.setFloat(address, (value as RuntimeValueNumeric).floatval!!)
|
||||||
DataType.STR -> mem.setString(address, value.str!!)
|
DataType.STR -> mem.setString(address, (value as RuntimeValueString).str)
|
||||||
DataType.STR_S -> mem.setScreencodeString(address, value.str!!)
|
DataType.STR_S -> mem.setScreencodeString(address, (value as RuntimeValueString).str)
|
||||||
else -> throw VmExecutionException("weird memaddress type $decl")
|
else -> throw VmExecutionException("weird memaddress type $decl")
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
target.memoryAddress != null -> {
|
||||||
val address = evaluate(target.memoryAddress.addressExpression, evalCtx).wordval!!
|
val address = (evaluate(target.memoryAddress.addressExpression, evalCtx) as RuntimeValueNumeric).wordval!!
|
||||||
evalCtx.mem.setUByte(address, value.byteval!!)
|
evalCtx.mem.setUByte(address, (value as RuntimeValueNumeric).byteval!!)
|
||||||
}
|
}
|
||||||
targetArrayIndexed != null -> {
|
targetArrayIndexed != null -> {
|
||||||
val vardecl = targetArrayIndexed.identifier.targetVarDecl(program.namespace)!!
|
val vardecl = targetArrayIndexed.identifier.targetVarDecl(program.namespace)!!
|
||||||
if(vardecl.type==VarDeclType.VAR) {
|
if(vardecl.type==VarDeclType.VAR) {
|
||||||
val array = evaluate(targetArrayIndexed.identifier, evalCtx)
|
val array = evaluate(targetArrayIndexed.identifier, evalCtx)
|
||||||
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx)
|
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx) as RuntimeValueNumeric
|
||||||
when (array.type) {
|
when (array.type) {
|
||||||
DataType.ARRAY_UB -> {
|
DataType.ARRAY_UB -> {
|
||||||
if (value.type != DataType.UBYTE)
|
if (value.type != DataType.UBYTE)
|
||||||
@ -607,20 +612,21 @@ class AstVm(val program: Program) {
|
|||||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||||
}
|
}
|
||||||
if (array.type in ArrayDatatypes)
|
if (array.type in ArrayDatatypes)
|
||||||
array.array!![index.integerValue()] = value.numericValue()
|
(array as RuntimeValueArray).array[index.integerValue()] = value.numericValue()
|
||||||
else if (array.type in StringDatatypes) {
|
else if (array.type in StringDatatypes) {
|
||||||
val indexInt = index.integerValue()
|
val indexInt = index.integerValue()
|
||||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||||
val newstr = array.str!!.replaceRange(indexInt, indexInt + 1, newchr)
|
val newstr = (array as RuntimeValueString).str.replaceRange(indexInt, indexInt + 1, newchr)
|
||||||
val ident = contextStmt.definingScope().lookup(targetArrayIndexed.identifier.nameInSource, contextStmt) as? VarDecl
|
val ident = contextStmt.definingScope().lookup(targetArrayIndexed.identifier.nameInSource, contextStmt) as? VarDecl
|
||||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||||
val identScope = ident.definingScope()
|
val identScope = ident.definingScope()
|
||||||
runtimeVariables.set(identScope, ident.name, RuntimeValue(array.type, str = newstr))
|
runtimeVariables.set(identScope, ident.name, RuntimeValueString(array.type, newstr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
value as RuntimeValueNumeric
|
||||||
val address = (vardecl.value as NumericLiteralValue).number.toInt()
|
val address = (vardecl.value as NumericLiteralValue).number.toInt()
|
||||||
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx).integerValue()
|
val index = (evaluate(targetArrayIndexed.arrayspec.index, evalCtx) as RuntimeValueNumeric).integerValue()
|
||||||
val elementType = targetArrayIndexed.inferType(program)
|
val elementType = targetArrayIndexed.inferType(program)
|
||||||
if(!elementType.isKnown)
|
if(!elementType.isKnown)
|
||||||
throw VmExecutionException("unknown/void array elt type $targetArrayIndexed")
|
throw VmExecutionException("unknown/void array elt type $targetArrayIndexed")
|
||||||
@ -644,14 +650,14 @@ class AstVm(val program: Program) {
|
|||||||
private fun oneForCycle(stmt: ForLoop, loopvarDt: DataType, loopValue: Number, loopVar: IdentifierReference) {
|
private fun oneForCycle(stmt: ForLoop, loopvarDt: DataType, loopValue: Number, loopVar: IdentifierReference) {
|
||||||
// assign the new loop value to the loopvar, and run the code
|
// assign the new loop value to the loopvar, and run the code
|
||||||
performAssignment(AssignTarget(null, loopVar, null, null, loopVar.position),
|
performAssignment(AssignTarget(null, loopVar, null, null, loopVar.position),
|
||||||
RuntimeValue(loopvarDt, loopValue), stmt.body.statements.first(), evalCtx)
|
RuntimeValueNumeric(loopvarDt, loopValue), stmt.body.statements.first(), evalCtx)
|
||||||
executeAnonymousScope(stmt.body)
|
executeAnonymousScope(stmt.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluate(args: List<Expression>) = args.map { evaluate(it, evalCtx) }
|
private fun evaluate(args: List<Expression>) = args.map { evaluate(it, evalCtx) }
|
||||||
|
|
||||||
private fun performSyscall(sub: Subroutine, args: List<RuntimeValue>): RuntimeValue? {
|
private fun performSyscall(sub: Subroutine, args: List<RuntimeValueNumeric>): RuntimeValueNumeric? {
|
||||||
var result: RuntimeValue? = null
|
var result: RuntimeValueNumeric? = null
|
||||||
when (sub.scopedname) {
|
when (sub.scopedname) {
|
||||||
"c64scr.print" -> {
|
"c64scr.print" -> {
|
||||||
// if the argument is an UWORD, consider it to be the "address" of the string (=heapId)
|
// if the argument is an UWORD, consider it to be the "address" of the string (=heapId)
|
||||||
@ -659,7 +665,7 @@ class AstVm(val program: Program) {
|
|||||||
val str = program.heap.get(args[0].wordval!!).str!!
|
val str = program.heap.get(args[0].wordval!!).str!!
|
||||||
dialog.canvas.printText(str, true)
|
dialog.canvas.printText(str, true)
|
||||||
} else
|
} else
|
||||||
dialog.canvas.printText(args[0].str!!, true)
|
throw VmExecutionException("print non-heap string")
|
||||||
}
|
}
|
||||||
"c64scr.print_ub" -> {
|
"c64scr.print_ub" -> {
|
||||||
dialog.canvas.printText(args[0].byteval!!.toString(), true)
|
dialog.canvas.printText(args[0].byteval!!.toString(), true)
|
||||||
@ -735,7 +741,7 @@ class AstVm(val program: Program) {
|
|||||||
val origStr = program.heap.get(heapId).str!!
|
val origStr = program.heap.get(heapId).str!!
|
||||||
val paddedStr=inputStr.padEnd(origStr.length+1, '\u0000').substring(0, origStr.length)
|
val paddedStr=inputStr.padEnd(origStr.length+1, '\u0000').substring(0, origStr.length)
|
||||||
program.heap.updateString(heapId, paddedStr)
|
program.heap.updateString(heapId, paddedStr)
|
||||||
result = RuntimeValue(DataType.UBYTE, paddedStr.indexOf('\u0000'))
|
result = RuntimeValueNumeric(DataType.UBYTE, paddedStr.indexOf('\u0000'))
|
||||||
}
|
}
|
||||||
"c64flt.print_f" -> {
|
"c64flt.print_f" -> {
|
||||||
dialog.canvas.printText(args[0].floatval.toString(), false)
|
dialog.canvas.printText(args[0].floatval.toString(), false)
|
||||||
@ -751,13 +757,13 @@ class AstVm(val program: Program) {
|
|||||||
Thread.sleep(10)
|
Thread.sleep(10)
|
||||||
}
|
}
|
||||||
val char=dialog.keyboardBuffer.pop()
|
val char=dialog.keyboardBuffer.pop()
|
||||||
result = RuntimeValue(DataType.UBYTE, char.toShort())
|
result = RuntimeValueNumeric(DataType.UBYTE, char.toShort())
|
||||||
}
|
}
|
||||||
"c64utils.str2uword" -> {
|
"c64utils.str2uword" -> {
|
||||||
val heapId = args[0].wordval!!
|
val heapId = args[0].wordval!!
|
||||||
val argString = program.heap.get(heapId).str!!
|
val argString = program.heap.get(heapId).str!!
|
||||||
val numericpart = argString.takeWhile { it.isDigit() }
|
val numericpart = argString.takeWhile { it.isDigit() }
|
||||||
result = RuntimeValue(DataType.UWORD, numericpart.toInt() and 65535)
|
result = RuntimeValueNumeric(DataType.UWORD, numericpart.toInt() and 65535)
|
||||||
}
|
}
|
||||||
else -> TODO("syscall ${sub.scopedname} $sub")
|
else -> TODO("syscall ${sub.scopedname} $sub")
|
||||||
}
|
}
|
||||||
@ -765,120 +771,120 @@ class AstVm(val program: Program) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun performBuiltinFunction(name: String, args: List<RuntimeValue>, statusflags: StatusFlags): RuntimeValue? {
|
private fun performBuiltinFunction(name: String, args: List<RuntimeValueBase>, statusflags: StatusFlags): RuntimeValueNumeric? {
|
||||||
return when (name) {
|
return when (name) {
|
||||||
"rnd" -> RuntimeValue(DataType.UBYTE, rnd.nextInt() and 255)
|
"rnd" -> RuntimeValueNumeric(DataType.UBYTE, rnd.nextInt() and 255)
|
||||||
"rndw" -> RuntimeValue(DataType.UWORD, rnd.nextInt() and 65535)
|
"rndw" -> RuntimeValueNumeric(DataType.UWORD, rnd.nextInt() and 65535)
|
||||||
"rndf" -> RuntimeValue(DataType.FLOAT, rnd.nextDouble())
|
"rndf" -> RuntimeValueNumeric(DataType.FLOAT, rnd.nextDouble())
|
||||||
"lsb" -> RuntimeValue(DataType.UBYTE, args[0].integerValue() and 255)
|
"lsb" -> RuntimeValueNumeric(DataType.UBYTE, args[0].integerValue() and 255)
|
||||||
"msb" -> RuntimeValue(DataType.UBYTE, (args[0].integerValue() ushr 8) and 255)
|
"msb" -> RuntimeValueNumeric(DataType.UBYTE, (args[0].integerValue() ushr 8) and 255)
|
||||||
"sin" -> RuntimeValue(DataType.FLOAT, sin(args[0].numericValue().toDouble()))
|
"sin" -> RuntimeValueNumeric(DataType.FLOAT, sin(args[0].numericValue().toDouble()))
|
||||||
"sin8" -> {
|
"sin8" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.BYTE, (127.0 * sin(rad)).toShort())
|
RuntimeValueNumeric(DataType.BYTE, (127.0 * sin(rad)).toShort())
|
||||||
}
|
}
|
||||||
"sin8u" -> {
|
"sin8u" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.UBYTE, (128.0 + 127.5 * sin(rad)).toShort())
|
RuntimeValueNumeric(DataType.UBYTE, (128.0 + 127.5 * sin(rad)).toShort())
|
||||||
}
|
}
|
||||||
"sin16" -> {
|
"sin16" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.BYTE, (32767.0 * sin(rad)).toShort())
|
RuntimeValueNumeric(DataType.BYTE, (32767.0 * sin(rad)).toShort())
|
||||||
}
|
}
|
||||||
"sin16u" -> {
|
"sin16u" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.UBYTE, (32768.0 + 32767.5 * sin(rad)).toShort())
|
RuntimeValueNumeric(DataType.UBYTE, (32768.0 + 32767.5 * sin(rad)).toShort())
|
||||||
}
|
}
|
||||||
"cos" -> RuntimeValue(DataType.FLOAT, cos(args[0].numericValue().toDouble()))
|
"cos" -> RuntimeValueNumeric(DataType.FLOAT, cos(args[0].numericValue().toDouble()))
|
||||||
"cos8" -> {
|
"cos8" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.BYTE, (127.0 * cos(rad)).toShort())
|
RuntimeValueNumeric(DataType.BYTE, (127.0 * cos(rad)).toShort())
|
||||||
}
|
}
|
||||||
"cos8u" -> {
|
"cos8u" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.UBYTE, (128.0 + 127.5 * cos(rad)).toShort())
|
RuntimeValueNumeric(DataType.UBYTE, (128.0 + 127.5 * cos(rad)).toShort())
|
||||||
}
|
}
|
||||||
"cos16" -> {
|
"cos16" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.BYTE, (32767.0 * cos(rad)).toShort())
|
RuntimeValueNumeric(DataType.BYTE, (32767.0 * cos(rad)).toShort())
|
||||||
}
|
}
|
||||||
"cos16u" -> {
|
"cos16u" -> {
|
||||||
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
val rad = args[0].numericValue().toDouble() / 256.0 * 2.0 * PI
|
||||||
RuntimeValue(DataType.UBYTE, (32768.0 + 32767.5 * cos(rad)).toShort())
|
RuntimeValueNumeric(DataType.UBYTE, (32768.0 + 32767.5 * cos(rad)).toShort())
|
||||||
}
|
}
|
||||||
"tan" -> RuntimeValue(DataType.FLOAT, tan(args[0].numericValue().toDouble()))
|
"tan" -> RuntimeValueNumeric(DataType.FLOAT, tan(args[0].numericValue().toDouble()))
|
||||||
"atan" -> RuntimeValue(DataType.FLOAT, atan(args[0].numericValue().toDouble()))
|
"atan" -> RuntimeValueNumeric(DataType.FLOAT, atan(args[0].numericValue().toDouble()))
|
||||||
"ln" -> RuntimeValue(DataType.FLOAT, ln(args[0].numericValue().toDouble()))
|
"ln" -> RuntimeValueNumeric(DataType.FLOAT, ln(args[0].numericValue().toDouble()))
|
||||||
"log2" -> RuntimeValue(DataType.FLOAT, log2(args[0].numericValue().toDouble()))
|
"log2" -> RuntimeValueNumeric(DataType.FLOAT, log2(args[0].numericValue().toDouble()))
|
||||||
"sqrt" -> RuntimeValue(DataType.FLOAT, sqrt(args[0].numericValue().toDouble()))
|
"sqrt" -> RuntimeValueNumeric(DataType.FLOAT, sqrt(args[0].numericValue().toDouble()))
|
||||||
"sqrt16" -> RuntimeValue(DataType.UBYTE, sqrt(args[0].wordval!!.toDouble()).toInt())
|
"sqrt16" -> RuntimeValueNumeric(DataType.UBYTE, sqrt((args[0] as RuntimeValueNumeric).wordval!!.toDouble()).toInt())
|
||||||
"rad" -> RuntimeValue(DataType.FLOAT, Math.toRadians(args[0].numericValue().toDouble()))
|
"rad" -> RuntimeValueNumeric(DataType.FLOAT, Math.toRadians(args[0].numericValue().toDouble()))
|
||||||
"deg" -> RuntimeValue(DataType.FLOAT, Math.toDegrees(args[0].numericValue().toDouble()))
|
"deg" -> RuntimeValueNumeric(DataType.FLOAT, Math.toDegrees(args[0].numericValue().toDouble()))
|
||||||
"round" -> RuntimeValue(DataType.FLOAT, round(args[0].numericValue().toDouble()))
|
"round" -> RuntimeValueNumeric(DataType.FLOAT, round(args[0].numericValue().toDouble()))
|
||||||
"floor" -> RuntimeValue(DataType.FLOAT, floor(args[0].numericValue().toDouble()))
|
"floor" -> RuntimeValueNumeric(DataType.FLOAT, floor(args[0].numericValue().toDouble()))
|
||||||
"ceil" -> RuntimeValue(DataType.FLOAT, ceil(args[0].numericValue().toDouble()))
|
"ceil" -> RuntimeValueNumeric(DataType.FLOAT, ceil(args[0].numericValue().toDouble()))
|
||||||
"rol" -> {
|
"rol" -> {
|
||||||
val (result, newCarry) = args[0].rol(statusflags.carry)
|
val (result, newCarry) = (args[0] as RuntimeValueNumeric).rol(statusflags.carry)
|
||||||
statusflags.carry = newCarry
|
statusflags.carry = newCarry
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
"rol2" -> args[0].rol2()
|
"rol2" -> (args[0] as RuntimeValueNumeric).rol2()
|
||||||
"ror" -> {
|
"ror" -> {
|
||||||
val (result, newCarry) = args[0].ror(statusflags.carry)
|
val (result, newCarry) = (args[0] as RuntimeValueNumeric).ror(statusflags.carry)
|
||||||
statusflags.carry = newCarry
|
statusflags.carry = newCarry
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
"ror2" -> args[0].ror2()
|
"ror2" -> (args[0] as RuntimeValueNumeric).ror2()
|
||||||
"lsl" -> args[0].shl()
|
"lsl" -> (args[0] as RuntimeValueNumeric).shl()
|
||||||
"lsr" -> args[0].shr()
|
"lsr" -> (args[0] as RuntimeValueNumeric).shr()
|
||||||
"abs" -> {
|
"abs" -> {
|
||||||
when (args[0].type) {
|
when (args[0].type) {
|
||||||
DataType.UBYTE -> args[0]
|
DataType.UBYTE -> (args[0] as RuntimeValueNumeric)
|
||||||
DataType.BYTE -> RuntimeValue(DataType.UBYTE, abs(args[0].numericValue().toDouble()))
|
DataType.BYTE -> RuntimeValueNumeric(DataType.UBYTE, abs(args[0].numericValue().toDouble()))
|
||||||
DataType.UWORD -> args[0]
|
DataType.UWORD -> (args[0] as RuntimeValueNumeric)
|
||||||
DataType.WORD -> RuntimeValue(DataType.UWORD, abs(args[0].numericValue().toDouble()))
|
DataType.WORD -> RuntimeValueNumeric(DataType.UWORD, abs(args[0].numericValue().toDouble()))
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, abs(args[0].numericValue().toDouble()))
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, abs(args[0].numericValue().toDouble()))
|
||||||
else -> throw VmExecutionException("strange abs type ${args[0]}")
|
else -> throw VmExecutionException("strange abs type ${args[0]}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"max" -> {
|
"max" -> {
|
||||||
val numbers = args.single().array!!.map { it.toDouble() }
|
val numbers = (args.single() as RuntimeValueArray).array.map { it.toDouble() }
|
||||||
RuntimeValue(ArrayElementTypes.getValue(args[0].type), numbers.max())
|
RuntimeValueNumeric(ArrayElementTypes.getValue(args[0].type), numbers.max()!!)
|
||||||
}
|
}
|
||||||
"min" -> {
|
"min" -> {
|
||||||
val numbers = args.single().array!!.map { it.toDouble() }
|
val numbers = (args.single() as RuntimeValueArray).array.map { it.toDouble() }
|
||||||
RuntimeValue(ArrayElementTypes.getValue(args[0].type), numbers.min())
|
RuntimeValueNumeric(ArrayElementTypes.getValue(args[0].type), numbers.min()!!)
|
||||||
}
|
}
|
||||||
"sum" -> {
|
"sum" -> {
|
||||||
val sum = args.single().array!!.map { it.toDouble() }.sum()
|
val sum = (args.single() as RuntimeValueArray).array.map { it.toDouble() }.sum()
|
||||||
when (args[0].type) {
|
when (args[0].type) {
|
||||||
DataType.ARRAY_UB -> RuntimeValue(DataType.UWORD, sum)
|
DataType.ARRAY_UB -> RuntimeValueNumeric(DataType.UWORD, sum)
|
||||||
DataType.ARRAY_B -> RuntimeValue(DataType.WORD, sum)
|
DataType.ARRAY_B -> RuntimeValueNumeric(DataType.WORD, sum)
|
||||||
DataType.ARRAY_UW -> RuntimeValue(DataType.UWORD, sum)
|
DataType.ARRAY_UW -> RuntimeValueNumeric(DataType.UWORD, sum)
|
||||||
DataType.ARRAY_W -> RuntimeValue(DataType.WORD, sum)
|
DataType.ARRAY_W -> RuntimeValueNumeric(DataType.WORD, sum)
|
||||||
DataType.ARRAY_F -> RuntimeValue(DataType.FLOAT, sum)
|
DataType.ARRAY_F -> RuntimeValueNumeric(DataType.FLOAT, sum)
|
||||||
else -> throw VmExecutionException("weird sum type ${args[0]}")
|
else -> throw VmExecutionException("weird sum type ${args[0]}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"any" -> {
|
"any" -> {
|
||||||
val numbers = args.single().array!!.map { it.toDouble() }
|
val numbers = (args.single() as RuntimeValueArray).array.map { it.toDouble() }
|
||||||
RuntimeValue(DataType.UBYTE, if (numbers.any { it != 0.0 }) 1 else 0)
|
RuntimeValueNumeric(DataType.UBYTE, if (numbers.any { it != 0.0 }) 1 else 0)
|
||||||
}
|
}
|
||||||
"all" -> {
|
"all" -> {
|
||||||
val numbers = args.single().array!!.map { it.toDouble() }
|
val numbers = (args.single() as RuntimeValueArray).array.map { it.toDouble() }
|
||||||
RuntimeValue(DataType.UBYTE, if (numbers.all { it != 0.0 }) 1 else 0)
|
RuntimeValueNumeric(DataType.UBYTE, if (numbers.all { it != 0.0 }) 1 else 0)
|
||||||
}
|
}
|
||||||
"swap" ->
|
"swap" ->
|
||||||
throw VmExecutionException("swap() cannot be implemented as a function")
|
throw VmExecutionException("swap() cannot be implemented as a function")
|
||||||
"strlen" -> {
|
"strlen" -> {
|
||||||
val zeroIndex = args[0].str!!.indexOf(0.toChar())
|
val zeroIndex = (args[0] as RuntimeValueString).str.indexOf(0.toChar())
|
||||||
if (zeroIndex >= 0)
|
if (zeroIndex >= 0)
|
||||||
RuntimeValue(DataType.UBYTE, zeroIndex)
|
RuntimeValueNumeric(DataType.UBYTE, zeroIndex)
|
||||||
else
|
else
|
||||||
RuntimeValue(DataType.UBYTE, args[0].str!!.length)
|
RuntimeValueNumeric(DataType.UBYTE, (args[0] as RuntimeValueString).str.length)
|
||||||
}
|
}
|
||||||
"memset" -> {
|
"memset" -> {
|
||||||
val heapId = args[0].wordval!!
|
val heapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||||
val amount = args[1].integerValue()
|
val amount = args[1].integerValue()
|
||||||
val value = args[2].integerValue()
|
val value = args[2].integerValue()
|
||||||
@ -888,7 +894,7 @@ class AstVm(val program: Program) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
"memsetw" -> {
|
"memsetw" -> {
|
||||||
val heapId = args[0].wordval!!
|
val heapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||||
val amount = args[1].integerValue()
|
val amount = args[1].integerValue()
|
||||||
val value = args[2].integerValue()
|
val value = args[2].integerValue()
|
||||||
@ -899,8 +905,8 @@ class AstVm(val program: Program) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
"memcopy" -> {
|
"memcopy" -> {
|
||||||
val sourceHeapId = args[0].wordval!!
|
val sourceHeapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||||
val destHeapId = args[1].wordval!!
|
val destHeapId = (args[1] as RuntimeValueNumeric).wordval!!
|
||||||
val source = program.heap.get(sourceHeapId).array!!
|
val source = program.heap.get(sourceHeapId).array!!
|
||||||
val dest = program.heap.get(destHeapId).array!!
|
val dest = program.heap.get(destHeapId).array!!
|
||||||
val amount = args[2].integerValue()
|
val amount = args[2].integerValue()
|
||||||
@ -911,7 +917,7 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
"mkword" -> {
|
"mkword" -> {
|
||||||
val result = (args[1].integerValue() shl 8) or args[0].integerValue()
|
val result = (args[1].integerValue() shl 8) or args[0].integerValue()
|
||||||
RuntimeValue(DataType.UWORD, result)
|
RuntimeValueNumeric(DataType.UWORD, result)
|
||||||
}
|
}
|
||||||
"set_carry" -> {
|
"set_carry" -> {
|
||||||
statusflags.carry=true
|
statusflags.carry=true
|
||||||
@ -934,13 +940,13 @@ class AstVm(val program: Program) {
|
|||||||
val zero = if(statusflags.zero) 2 else 0
|
val zero = if(statusflags.zero) 2 else 0
|
||||||
val irqd = if(statusflags.irqd) 4 else 0
|
val irqd = if(statusflags.irqd) 4 else 0
|
||||||
val negative = if(statusflags.negative) 128 else 0
|
val negative = if(statusflags.negative) 128 else 0
|
||||||
RuntimeValue(DataType.UBYTE, carry or zero or irqd or negative)
|
RuntimeValueNumeric(DataType.UBYTE, carry or zero or irqd or negative)
|
||||||
}
|
}
|
||||||
"rsave" -> {
|
"rsave" -> {
|
||||||
statusFlagsSave.push(statusflags)
|
statusFlagsSave.push(statusflags)
|
||||||
registerAsave.push(runtimeVariables.get(program.namespace, Register.A.name))
|
registerAsave.push(runtimeVariables.get(program.namespace, Register.A.name) as RuntimeValueNumeric)
|
||||||
registerXsave.push(runtimeVariables.get(program.namespace, Register.X.name))
|
registerXsave.push(runtimeVariables.get(program.namespace, Register.X.name) as RuntimeValueNumeric)
|
||||||
registerYsave.push(runtimeVariables.get(program.namespace, Register.Y.name))
|
registerYsave.push(runtimeVariables.get(program.namespace, Register.Y.name) as RuntimeValueNumeric)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
"rrestore" -> {
|
"rrestore" -> {
|
||||||
@ -955,21 +961,21 @@ class AstVm(val program: Program) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
"sort" -> {
|
"sort" -> {
|
||||||
val array=args.single()
|
val array=args.single() as RuntimeValueArray
|
||||||
array.array!!.sort()
|
array.array.sort()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
"reverse" -> {
|
"reverse" -> {
|
||||||
val array=args.single()
|
val array=args.single() as RuntimeValueArray
|
||||||
array.array!!.reverse()
|
array.array.reverse()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
"sgn" -> {
|
"sgn" -> {
|
||||||
val value = args.single().numericValue().toDouble()
|
val value = args.single().numericValue().toDouble()
|
||||||
when {
|
when {
|
||||||
value<0.0 -> RuntimeValue(DataType.BYTE, -1)
|
value<0.0 -> RuntimeValueNumeric(DataType.BYTE, -1)
|
||||||
value==0.0 -> RuntimeValue(DataType.BYTE, 0)
|
value==0.0 -> RuntimeValueNumeric(DataType.BYTE, 0)
|
||||||
else -> RuntimeValue(DataType.BYTE, 1)
|
else -> RuntimeValueNumeric(DataType.BYTE, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> TODO("builtin function $name")
|
else -> TODO("builtin function $name")
|
||||||
|
@ -10,12 +10,11 @@ import prog8.ast.statements.BuiltinFunctionStatementPlaceholder
|
|||||||
import prog8.ast.statements.Label
|
import prog8.ast.statements.Label
|
||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
import prog8.vm.RuntimeValue
|
import prog8.vm.*
|
||||||
import prog8.vm.RuntimeValueRange
|
|
||||||
|
|
||||||
|
|
||||||
typealias BuiltinfunctionCaller = (name: String, args: List<RuntimeValue>, flags: StatusFlags) -> RuntimeValue?
|
typealias BuiltinfunctionCaller = (name: String, args: List<RuntimeValueNumeric>, flags: StatusFlags) -> RuntimeValueNumeric?
|
||||||
typealias SubroutineCaller = (sub: Subroutine, args: List<RuntimeValue>, startAtLabel: Label?) -> RuntimeValue?
|
typealias SubroutineCaller = (sub: Subroutine, args: List<RuntimeValueNumeric>, startAtLabel: Label?) -> RuntimeValueNumeric?
|
||||||
|
|
||||||
|
|
||||||
class EvalContext(val program: Program, val mem: Memory, val statusflags: StatusFlags,
|
class EvalContext(val program: Program, val mem: Memory, val statusflags: StatusFlags,
|
||||||
@ -23,34 +22,34 @@ class EvalContext(val program: Program, val mem: Memory, val statusflags: Status
|
|||||||
val performBuiltinFunction: BuiltinfunctionCaller,
|
val performBuiltinFunction: BuiltinfunctionCaller,
|
||||||
val executeSubroutine: SubroutineCaller)
|
val executeSubroutine: SubroutineCaller)
|
||||||
|
|
||||||
fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValue {
|
fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValueBase {
|
||||||
val constval = expr.constValue(ctx.program)
|
val constval = expr.constValue(ctx.program)
|
||||||
if(constval!=null)
|
if(constval!=null)
|
||||||
return RuntimeValue.fromLv(constval)
|
return RuntimeValueNumeric.fromLv(constval)
|
||||||
|
|
||||||
when(expr) {
|
when(expr) {
|
||||||
is NumericLiteralValue -> return RuntimeValue.fromLv(expr)
|
is NumericLiteralValue -> return RuntimeValueNumeric.fromLv(expr)
|
||||||
is StringLiteralValue -> return RuntimeValue.fromLv(expr)
|
is StringLiteralValue -> return RuntimeValueString.fromLv(expr)
|
||||||
is ArrayLiteralValue -> return RuntimeValue.fromLv(expr)
|
is ArrayLiteralValue -> return RuntimeValueArray.fromLv(expr)
|
||||||
is PrefixExpression -> {
|
is PrefixExpression -> {
|
||||||
return when(expr.operator) {
|
return when(expr.operator) {
|
||||||
"-" -> evaluate(expr.expression, ctx).neg()
|
"-" -> (evaluate(expr.expression, ctx) as RuntimeValueNumeric).neg()
|
||||||
"~" -> evaluate(expr.expression, ctx).inv()
|
"~" -> (evaluate(expr.expression, ctx) as RuntimeValueNumeric).inv()
|
||||||
"not" -> evaluate(expr.expression, ctx).not()
|
"not" -> (evaluate(expr.expression, ctx) as RuntimeValueNumeric).not()
|
||||||
// unary '+' should have been optimized away
|
// unary '+' should have been optimized away
|
||||||
else -> throw VmExecutionException("unsupported prefix operator "+expr.operator)
|
else -> throw VmExecutionException("unsupported prefix operator "+expr.operator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BinaryExpression -> {
|
is BinaryExpression -> {
|
||||||
val left = evaluate(expr.left, ctx)
|
val left = evaluate(expr.left, ctx) as RuntimeValueNumeric
|
||||||
val right = evaluate(expr.right, ctx)
|
val right = evaluate(expr.right, ctx) as RuntimeValueNumeric
|
||||||
return when(expr.operator) {
|
return when(expr.operator) {
|
||||||
"<" -> RuntimeValue(DataType.UBYTE, if (left < right) 1 else 0)
|
"<" -> RuntimeValueNumeric(DataType.UBYTE, if (left < right) 1 else 0)
|
||||||
"<=" -> RuntimeValue(DataType.UBYTE, if (left <= right) 1 else 0)
|
"<=" -> RuntimeValueNumeric(DataType.UBYTE, if (left <= right) 1 else 0)
|
||||||
">" -> RuntimeValue(DataType.UBYTE, if (left > right) 1 else 0)
|
">" -> RuntimeValueNumeric(DataType.UBYTE, if (left > right) 1 else 0)
|
||||||
">=" -> RuntimeValue(DataType.UBYTE, if (left >= right) 1 else 0)
|
">=" -> RuntimeValueNumeric(DataType.UBYTE, if (left >= right) 1 else 0)
|
||||||
"==" -> RuntimeValue(DataType.UBYTE, if (left == right) 1 else 0)
|
"==" -> RuntimeValueNumeric(DataType.UBYTE, if (left == right) 1 else 0)
|
||||||
"!=" -> RuntimeValue(DataType.UBYTE, if (left != right) 1 else 0)
|
"!=" -> RuntimeValueNumeric(DataType.UBYTE, if (left != right) 1 else 0)
|
||||||
"+" -> left.add(right)
|
"+" -> left.add(right)
|
||||||
"-" -> left.sub(right)
|
"-" -> left.sub(right)
|
||||||
"*" -> left.mul(right)
|
"*" -> left.mul(right)
|
||||||
@ -78,32 +77,36 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValue {
|
|||||||
}
|
}
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
val array = evaluate(expr.identifier, ctx)
|
val array = evaluate(expr.identifier, ctx)
|
||||||
val index = evaluate(expr.arrayspec.index, ctx)
|
val index = evaluate(expr.arrayspec.index, ctx) as RuntimeValueNumeric
|
||||||
return if(array.array!=null) {
|
return when (array) {
|
||||||
|
is RuntimeValueString -> {
|
||||||
|
val value = array.str[index.integerValue()]
|
||||||
|
RuntimeValueNumeric(ArrayElementTypes.getValue(array.type), value.toShort())
|
||||||
|
}
|
||||||
|
is RuntimeValueArray -> {
|
||||||
val value = array.array[index.integerValue()]
|
val value = array.array[index.integerValue()]
|
||||||
RuntimeValue(ArrayElementTypes.getValue(array.type), value)
|
RuntimeValueNumeric(ArrayElementTypes.getValue(array.type), value)
|
||||||
} else {
|
}
|
||||||
val value = array.str!![index.integerValue()]
|
else -> throw VmExecutionException("weird type")
|
||||||
RuntimeValue(ArrayElementTypes.getValue(array.type), value.toShort())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is TypecastExpression -> {
|
is TypecastExpression -> {
|
||||||
return evaluate(expr.expression, ctx).cast(expr.type)
|
return (evaluate(expr.expression, ctx) as RuntimeValueNumeric).cast(expr.type)
|
||||||
}
|
}
|
||||||
is AddressOf -> {
|
is AddressOf -> {
|
||||||
// we support: address of heap var -> the heap id
|
// we support: address of heap var -> the heap id
|
||||||
return try {
|
return try {
|
||||||
val heapId = expr.identifier.heapId(ctx.program.namespace)
|
val heapId = expr.identifier.heapId(ctx.program.namespace)
|
||||||
RuntimeValue(DataType.UWORD, heapId)
|
RuntimeValueNumeric(DataType.UWORD, heapId)
|
||||||
} catch( f: FatalAstException) {
|
} catch( f: FatalAstException) {
|
||||||
// fallback: use the hash of the name, so we have at least *a* value...
|
// fallback: use the hash of the name, so we have at least *a* value...
|
||||||
val address = expr.identifier.hashCode() and 65535
|
val address = expr.identifier.hashCode() and 65535
|
||||||
RuntimeValue(DataType.UWORD, address)
|
RuntimeValueNumeric(DataType.UWORD, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is DirectMemoryRead -> {
|
is DirectMemoryRead -> {
|
||||||
val address = evaluate(expr.addressExpression, ctx).wordval!!
|
val address = (evaluate(expr.addressExpression, ctx) as RuntimeValueNumeric).wordval!!
|
||||||
return RuntimeValue(DataType.UBYTE, ctx.mem.getUByte(address))
|
return RuntimeValueNumeric(DataType.UBYTE, ctx.mem.getUByte(address))
|
||||||
}
|
}
|
||||||
is RegisterExpr -> return ctx.runtimeVars.get(ctx.program.namespace, expr.register.name)
|
is RegisterExpr -> return ctx.runtimeVars.get(ctx.program.namespace, expr.register.name)
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
@ -116,13 +119,13 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValue {
|
|||||||
else -> {
|
else -> {
|
||||||
val address = ctx.runtimeVars.getMemoryAddress(variable.definingScope(), variable.name)
|
val address = ctx.runtimeVars.getMemoryAddress(variable.definingScope(), variable.name)
|
||||||
return when(variable.datatype) {
|
return when(variable.datatype) {
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, ctx.mem.getUByte(address))
|
DataType.UBYTE -> RuntimeValueNumeric(DataType.UBYTE, ctx.mem.getUByte(address))
|
||||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, ctx.mem.getSByte(address))
|
DataType.BYTE -> RuntimeValueNumeric(DataType.BYTE, ctx.mem.getSByte(address))
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, ctx.mem.getUWord(address))
|
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, ctx.mem.getUWord(address))
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, ctx.mem.getSWord(address))
|
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, ctx.mem.getSWord(address))
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, ctx.mem.getFloat(address))
|
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, ctx.mem.getFloat(address))
|
||||||
DataType.STR -> RuntimeValue(DataType.STR, str = ctx.mem.getString(address))
|
DataType.STR -> RuntimeValueString(DataType.STR, ctx.mem.getString(address))
|
||||||
DataType.STR_S -> RuntimeValue(DataType.STR_S, str = ctx.mem.getScreencodeString(address))
|
DataType.STR_S -> RuntimeValueString(DataType.STR_S, ctx.mem.getScreencodeString(address)!!)
|
||||||
else -> throw VmExecutionException("unexpected datatype $variable")
|
else -> throw VmExecutionException("unexpected datatype $variable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +135,7 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValue {
|
|||||||
}
|
}
|
||||||
is FunctionCall -> {
|
is FunctionCall -> {
|
||||||
val sub = expr.target.targetStatement(ctx.program.namespace)
|
val sub = expr.target.targetStatement(ctx.program.namespace)
|
||||||
val args = expr.arglist.map { evaluate(it, ctx) }
|
val args = expr.arglist.map { evaluate(it, ctx) as RuntimeValueNumeric }
|
||||||
return when(sub) {
|
return when(sub) {
|
||||||
is Subroutine -> {
|
is Subroutine -> {
|
||||||
val result = ctx.executeSubroutine(sub, args, null)
|
val result = ctx.executeSubroutine(sub, args, null)
|
||||||
@ -158,9 +161,9 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValue {
|
|||||||
else
|
else
|
||||||
throw VmExecutionException("couldn't determine datatype")
|
throw VmExecutionException("couldn't determine datatype")
|
||||||
}
|
}
|
||||||
val fromVal = evaluate(expr.from, ctx).integerValue()
|
val fromVal = (evaluate(expr.from, ctx) as RuntimeValueNumeric).integerValue()
|
||||||
val toVal = evaluate(expr.to, ctx).integerValue()
|
val toVal = (evaluate(expr.to, ctx) as RuntimeValueNumeric).integerValue()
|
||||||
val stepVal = evaluate(expr.step, ctx).integerValue()
|
val stepVal = (evaluate(expr.step, ctx) as RuntimeValueNumeric).integerValue()
|
||||||
val range = makeRange(fromVal, toVal, stepVal)
|
val range = makeRange(fromVal, toVal, stepVal)
|
||||||
val dt = expr.inferType(ctx.program)
|
val dt = expr.inferType(ctx.program)
|
||||||
if(dt.isKnown)
|
if(dt.isKnown)
|
||||||
|
@ -13,16 +13,17 @@ import prog8.ast.statements.Statement
|
|||||||
import prog8.ast.statements.StructDecl
|
import prog8.ast.statements.StructDecl
|
||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
import prog8.ast.statements.ZeropageWish
|
import prog8.ast.statements.ZeropageWish
|
||||||
import prog8.compiler.HeapValues
|
import prog8.vm.RuntimeValueArray
|
||||||
import prog8.vm.RuntimeValue
|
import prog8.vm.RuntimeValueNumeric
|
||||||
|
import prog8.vm.RuntimeValueString
|
||||||
|
|
||||||
class VariablesCreator(private val runtimeVariables: RuntimeVariables, private val heap: HeapValues) : IAstModifyingVisitor {
|
class VariablesCreator(private val runtimeVariables: RuntimeVariables) : IAstModifyingVisitor {
|
||||||
|
|
||||||
override fun visit(program: Program) {
|
override fun visit(program: Program) {
|
||||||
// define the three registers as global variables
|
// define the three registers as global variables
|
||||||
runtimeVariables.define(program.namespace, Register.A.name, RuntimeValue(DataType.UBYTE, 0))
|
runtimeVariables.define(program.namespace, Register.A.name, RuntimeValueNumeric(DataType.UBYTE, 0))
|
||||||
runtimeVariables.define(program.namespace, Register.X.name, RuntimeValue(DataType.UBYTE, 255))
|
runtimeVariables.define(program.namespace, Register.X.name, RuntimeValueNumeric(DataType.UBYTE, 255))
|
||||||
runtimeVariables.define(program.namespace, Register.Y.name, RuntimeValue(DataType.UBYTE, 0))
|
runtimeVariables.define(program.namespace, Register.Y.name, RuntimeValueNumeric(DataType.UBYTE, 0))
|
||||||
|
|
||||||
val globalpos = Position("<<global>>", 0, 0, 0)
|
val globalpos = Position("<<global>>", 0, 0, 0)
|
||||||
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.DONTCARE, null, Register.A.name, null,
|
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.DONTCARE, null, Register.A.name, null,
|
||||||
@ -49,12 +50,12 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
|||||||
if(decl.datatype!=DataType.STRUCT) {
|
if(decl.datatype!=DataType.STRUCT) {
|
||||||
val numericLv = decl.value as? NumericLiteralValue
|
val numericLv = decl.value as? NumericLiteralValue
|
||||||
val value = if(numericLv!=null) {
|
val value = if(numericLv!=null) {
|
||||||
RuntimeValue.fromLv(numericLv)
|
RuntimeValueNumeric.fromLv(numericLv)
|
||||||
} else {
|
} else {
|
||||||
if(decl.value is StringLiteralValue)
|
if(decl.value is StringLiteralValue)
|
||||||
RuntimeValue.fromLv(decl.value as StringLiteralValue)
|
RuntimeValueString.fromLv(decl.value as StringLiteralValue)
|
||||||
else
|
else
|
||||||
RuntimeValue.fromLv(decl.value as ArrayLiteralValue)
|
RuntimeValueArray.fromLv(decl.value as ArrayLiteralValue)
|
||||||
}
|
}
|
||||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||||
}
|
}
|
||||||
|
@ -3,66 +3,66 @@ package prog8tests
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.DataType
|
||||||
import prog8.vm.RuntimeValue
|
import prog8.vm.RuntimeValueNumeric
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
private fun sameValueAndType(v1: RuntimeValue, v2: RuntimeValue): Boolean {
|
private fun sameValueAndType(v1: RuntimeValueNumeric, v2: RuntimeValueNumeric): Boolean {
|
||||||
return v1.type==v2.type && v1==v2
|
return v1.type==v2.type && v1==v2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
class TestRuntimeValue {
|
class TestRuntimeValueNumeric {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testValueRanges() {
|
fun testValueRanges() {
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 0).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 0).integerValue())
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 255).integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 255).integerValue())
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.UBYTE, -1)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.UBYTE, -1)}
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.UBYTE, 256)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.UBYTE, 256)}
|
||||||
|
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 0).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 0).integerValue())
|
||||||
assertEquals(-128, RuntimeValue(DataType.BYTE, -128).integerValue())
|
assertEquals(-128, RuntimeValueNumeric(DataType.BYTE, -128).integerValue())
|
||||||
assertEquals(127, RuntimeValue(DataType.BYTE, 127).integerValue())
|
assertEquals(127, RuntimeValueNumeric(DataType.BYTE, 127).integerValue())
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.BYTE, -129)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.BYTE, -129)}
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.BYTE, 128)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.BYTE, 128)}
|
||||||
|
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 0).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 0).integerValue())
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 65535).integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 65535).integerValue())
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.UWORD, -1)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.UWORD, -1)}
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.UWORD, 65536)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.UWORD, 65536)}
|
||||||
|
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 0).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 0).integerValue())
|
||||||
assertEquals(-32768, RuntimeValue(DataType.WORD, -32768).integerValue())
|
assertEquals(-32768, RuntimeValueNumeric(DataType.WORD, -32768).integerValue())
|
||||||
assertEquals(32767, RuntimeValue(DataType.WORD, 32767).integerValue())
|
assertEquals(32767, RuntimeValueNumeric(DataType.WORD, 32767).integerValue())
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.WORD, -32769)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.WORD, -32769)}
|
||||||
assertFailsWith<IllegalArgumentException> { RuntimeValue(DataType.WORD, 32768)}
|
assertFailsWith<IllegalArgumentException> { RuntimeValueNumeric(DataType.WORD, 32768)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTruthiness()
|
fun testTruthiness()
|
||||||
{
|
{
|
||||||
assertFalse(RuntimeValue(DataType.BYTE, 0).asBoolean)
|
assertFalse(RuntimeValueNumeric(DataType.BYTE, 0).asBoolean)
|
||||||
assertFalse(RuntimeValue(DataType.UBYTE, 0).asBoolean)
|
assertFalse(RuntimeValueNumeric(DataType.UBYTE, 0).asBoolean)
|
||||||
assertFalse(RuntimeValue(DataType.WORD, 0).asBoolean)
|
assertFalse(RuntimeValueNumeric(DataType.WORD, 0).asBoolean)
|
||||||
assertFalse(RuntimeValue(DataType.UWORD, 0).asBoolean)
|
assertFalse(RuntimeValueNumeric(DataType.UWORD, 0).asBoolean)
|
||||||
assertFalse(RuntimeValue(DataType.FLOAT, 0.0).asBoolean)
|
assertFalse(RuntimeValueNumeric(DataType.FLOAT, 0.0).asBoolean)
|
||||||
|
|
||||||
assertTrue(RuntimeValue(DataType.BYTE, 42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.BYTE, 42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.UBYTE, 42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.UBYTE, 42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.WORD, 42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.WORD, 42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.UWORD, 42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.UWORD, 42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, 42.0).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, 42.0).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.BYTE, -42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.BYTE, -42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.WORD, -42).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.WORD, -42).asBoolean)
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, -42.0).asBoolean)
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, -42.0).asBoolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testIdentity() {
|
fun testIdentity() {
|
||||||
val v = RuntimeValue(DataType.UWORD, 12345)
|
val v = RuntimeValueNumeric(DataType.UWORD, 12345)
|
||||||
assertEquals(v, v)
|
assertEquals(v, v)
|
||||||
assertFalse(v != v)
|
assertFalse(v != v)
|
||||||
assertTrue(v<=v)
|
assertTrue(v<=v)
|
||||||
@ -70,283 +70,283 @@ class TestRuntimeValue {
|
|||||||
assertFalse(v<v)
|
assertFalse(v<v)
|
||||||
assertFalse(v>v)
|
assertFalse(v>v)
|
||||||
|
|
||||||
assertTrue(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UBYTE, 100)))
|
assertTrue(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UBYTE, 100)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEqualsAndNotEquals() {
|
fun testEqualsAndNotEquals() {
|
||||||
assertEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UBYTE, 100))
|
assertEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UWORD, 100))
|
assertEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UWORD, 100))
|
||||||
assertEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.FLOAT, 100))
|
assertEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.FLOAT, 100))
|
||||||
assertEquals(RuntimeValue(DataType.UWORD, 254), RuntimeValue(DataType.UBYTE, 254))
|
assertEquals(RuntimeValueNumeric(DataType.UWORD, 254), RuntimeValueNumeric(DataType.UBYTE, 254))
|
||||||
assertEquals(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.UWORD, 12345))
|
assertEquals(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.UWORD, 12345))
|
||||||
assertEquals(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.FLOAT, 12345))
|
assertEquals(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.FLOAT, 12345))
|
||||||
assertEquals(RuntimeValue(DataType.FLOAT, 100.0), RuntimeValue(DataType.UBYTE, 100))
|
assertEquals(RuntimeValueNumeric(DataType.FLOAT, 100.0), RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertEquals(RuntimeValue(DataType.FLOAT, 22239.0), RuntimeValue(DataType.UWORD, 22239))
|
assertEquals(RuntimeValueNumeric(DataType.FLOAT, 22239.0), RuntimeValueNumeric(DataType.UWORD, 22239))
|
||||||
assertEquals(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.FLOAT, 9.99))
|
assertEquals(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.FLOAT, 9.99))
|
||||||
|
|
||||||
assertTrue(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UBYTE, 100)))
|
assertTrue(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UBYTE, 100)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UWORD, 100)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UWORD, 100)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.FLOAT, 100)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.FLOAT, 100)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UWORD, 254), RuntimeValue(DataType.UBYTE, 254)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 254), RuntimeValueNumeric(DataType.UBYTE, 254)))
|
||||||
assertTrue(sameValueAndType(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.UWORD, 12345)))
|
assertTrue(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.UWORD, 12345)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.FLOAT, 12345)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.FLOAT, 12345)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.FLOAT, 100.0), RuntimeValue(DataType.UBYTE, 100)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 100.0), RuntimeValueNumeric(DataType.UBYTE, 100)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.FLOAT, 22239.0), RuntimeValue(DataType.UWORD, 22239)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 22239.0), RuntimeValueNumeric(DataType.UWORD, 22239)))
|
||||||
assertTrue(sameValueAndType(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.FLOAT, 9.99)))
|
assertTrue(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.FLOAT, 9.99)))
|
||||||
|
|
||||||
assertNotEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UBYTE, 101))
|
assertNotEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UBYTE, 101))
|
||||||
assertNotEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UWORD, 101))
|
assertNotEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UWORD, 101))
|
||||||
assertNotEquals(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.FLOAT, 101))
|
assertNotEquals(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.FLOAT, 101))
|
||||||
assertNotEquals(RuntimeValue(DataType.UWORD, 245), RuntimeValue(DataType.UBYTE, 246))
|
assertNotEquals(RuntimeValueNumeric(DataType.UWORD, 245), RuntimeValueNumeric(DataType.UBYTE, 246))
|
||||||
assertNotEquals(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.UWORD, 12346))
|
assertNotEquals(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.UWORD, 12346))
|
||||||
assertNotEquals(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.FLOAT, 12346))
|
assertNotEquals(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.FLOAT, 12346))
|
||||||
assertNotEquals(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.UBYTE, 9))
|
assertNotEquals(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.UBYTE, 9))
|
||||||
assertNotEquals(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.UWORD, 9))
|
assertNotEquals(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.UWORD, 9))
|
||||||
assertNotEquals(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.FLOAT, 9.0))
|
assertNotEquals(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.FLOAT, 9.0))
|
||||||
|
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UBYTE, 101)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UBYTE, 101)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.UWORD, 101)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.UWORD, 101)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UBYTE, 100), RuntimeValue(DataType.FLOAT, 101)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UBYTE, 100), RuntimeValueNumeric(DataType.FLOAT, 101)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UWORD, 245), RuntimeValue(DataType.UBYTE, 246)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 245), RuntimeValueNumeric(DataType.UBYTE, 246)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.UWORD, 12346)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.UWORD, 12346)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.UWORD, 12345), RuntimeValue(DataType.FLOAT, 12346)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.UWORD, 12345), RuntimeValueNumeric(DataType.FLOAT, 12346)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.UBYTE, 9)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.UBYTE, 9)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.UWORD, 9)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.UWORD, 9)))
|
||||||
assertFalse(sameValueAndType(RuntimeValue(DataType.FLOAT, 9.99), RuntimeValue(DataType.FLOAT, 9.0)))
|
assertFalse(sameValueAndType(RuntimeValueNumeric(DataType.FLOAT, 9.99), RuntimeValueNumeric(DataType.FLOAT, 9.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGreaterThan(){
|
fun testGreaterThan(){
|
||||||
assertTrue(RuntimeValue(DataType.UBYTE, 100) > RuntimeValue(DataType.UBYTE, 99))
|
assertTrue(RuntimeValueNumeric(DataType.UBYTE, 100) > RuntimeValueNumeric(DataType.UBYTE, 99))
|
||||||
assertTrue(RuntimeValue(DataType.UWORD, 254) > RuntimeValue(DataType.UWORD, 253))
|
assertTrue(RuntimeValueNumeric(DataType.UWORD, 254) > RuntimeValueNumeric(DataType.UWORD, 253))
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, 100.0) > RuntimeValue(DataType.FLOAT, 99.9))
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, 100.0) > RuntimeValueNumeric(DataType.FLOAT, 99.9))
|
||||||
|
|
||||||
assertTrue(RuntimeValue(DataType.UBYTE, 100) >= RuntimeValue(DataType.UBYTE, 100))
|
assertTrue(RuntimeValueNumeric(DataType.UBYTE, 100) >= RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertTrue(RuntimeValue(DataType.UWORD, 254) >= RuntimeValue(DataType.UWORD, 254))
|
assertTrue(RuntimeValueNumeric(DataType.UWORD, 254) >= RuntimeValueNumeric(DataType.UWORD, 254))
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, 100.0) >= RuntimeValue(DataType.FLOAT, 100.0))
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, 100.0) >= RuntimeValueNumeric(DataType.FLOAT, 100.0))
|
||||||
|
|
||||||
assertFalse(RuntimeValue(DataType.UBYTE, 100) > RuntimeValue(DataType.UBYTE, 100))
|
assertFalse(RuntimeValueNumeric(DataType.UBYTE, 100) > RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertFalse(RuntimeValue(DataType.UWORD, 254) > RuntimeValue(DataType.UWORD, 254))
|
assertFalse(RuntimeValueNumeric(DataType.UWORD, 254) > RuntimeValueNumeric(DataType.UWORD, 254))
|
||||||
assertFalse(RuntimeValue(DataType.FLOAT, 100.0) > RuntimeValue(DataType.FLOAT, 100.0))
|
assertFalse(RuntimeValueNumeric(DataType.FLOAT, 100.0) > RuntimeValueNumeric(DataType.FLOAT, 100.0))
|
||||||
|
|
||||||
assertFalse(RuntimeValue(DataType.UBYTE, 100) >= RuntimeValue(DataType.UBYTE, 101))
|
assertFalse(RuntimeValueNumeric(DataType.UBYTE, 100) >= RuntimeValueNumeric(DataType.UBYTE, 101))
|
||||||
assertFalse(RuntimeValue(DataType.UWORD, 254) >= RuntimeValue(DataType.UWORD, 255))
|
assertFalse(RuntimeValueNumeric(DataType.UWORD, 254) >= RuntimeValueNumeric(DataType.UWORD, 255))
|
||||||
assertFalse(RuntimeValue(DataType.FLOAT, 100.0) >= RuntimeValue(DataType.FLOAT, 100.1))
|
assertFalse(RuntimeValueNumeric(DataType.FLOAT, 100.0) >= RuntimeValueNumeric(DataType.FLOAT, 100.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLessThan() {
|
fun testLessThan() {
|
||||||
assertTrue(RuntimeValue(DataType.UBYTE, 100) < RuntimeValue(DataType.UBYTE, 101))
|
assertTrue(RuntimeValueNumeric(DataType.UBYTE, 100) < RuntimeValueNumeric(DataType.UBYTE, 101))
|
||||||
assertTrue(RuntimeValue(DataType.UWORD, 254) < RuntimeValue(DataType.UWORD, 255))
|
assertTrue(RuntimeValueNumeric(DataType.UWORD, 254) < RuntimeValueNumeric(DataType.UWORD, 255))
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, 100.0) < RuntimeValue(DataType.FLOAT, 100.1))
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, 100.0) < RuntimeValueNumeric(DataType.FLOAT, 100.1))
|
||||||
|
|
||||||
assertTrue(RuntimeValue(DataType.UBYTE, 100) <= RuntimeValue(DataType.UBYTE, 100))
|
assertTrue(RuntimeValueNumeric(DataType.UBYTE, 100) <= RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertTrue(RuntimeValue(DataType.UWORD, 254) <= RuntimeValue(DataType.UWORD, 254))
|
assertTrue(RuntimeValueNumeric(DataType.UWORD, 254) <= RuntimeValueNumeric(DataType.UWORD, 254))
|
||||||
assertTrue(RuntimeValue(DataType.FLOAT, 100.0) <= RuntimeValue(DataType.FLOAT, 100.0))
|
assertTrue(RuntimeValueNumeric(DataType.FLOAT, 100.0) <= RuntimeValueNumeric(DataType.FLOAT, 100.0))
|
||||||
|
|
||||||
assertFalse(RuntimeValue(DataType.UBYTE, 100) < RuntimeValue(DataType.UBYTE, 100))
|
assertFalse(RuntimeValueNumeric(DataType.UBYTE, 100) < RuntimeValueNumeric(DataType.UBYTE, 100))
|
||||||
assertFalse(RuntimeValue(DataType.UWORD, 254) < RuntimeValue(DataType.UWORD, 254))
|
assertFalse(RuntimeValueNumeric(DataType.UWORD, 254) < RuntimeValueNumeric(DataType.UWORD, 254))
|
||||||
assertFalse(RuntimeValue(DataType.FLOAT, 100.0) < RuntimeValue(DataType.FLOAT, 100.0))
|
assertFalse(RuntimeValueNumeric(DataType.FLOAT, 100.0) < RuntimeValueNumeric(DataType.FLOAT, 100.0))
|
||||||
|
|
||||||
assertFalse(RuntimeValue(DataType.UBYTE, 100) <= RuntimeValue(DataType.UBYTE, 99))
|
assertFalse(RuntimeValueNumeric(DataType.UBYTE, 100) <= RuntimeValueNumeric(DataType.UBYTE, 99))
|
||||||
assertFalse(RuntimeValue(DataType.UWORD, 254) <= RuntimeValue(DataType.UWORD, 253))
|
assertFalse(RuntimeValueNumeric(DataType.UWORD, 254) <= RuntimeValueNumeric(DataType.UWORD, 253))
|
||||||
assertFalse(RuntimeValue(DataType.FLOAT, 100.0) <= RuntimeValue(DataType.FLOAT, 99.9))
|
assertFalse(RuntimeValueNumeric(DataType.FLOAT, 100.0) <= RuntimeValueNumeric(DataType.FLOAT, 99.9))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNoDtConversion() {
|
fun testNoDtConversion() {
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UWORD, 100).add(RuntimeValue(DataType.UBYTE, 120))
|
RuntimeValueNumeric(DataType.UWORD, 100).add(RuntimeValueNumeric(DataType.UBYTE, 120))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UBYTE, 100).add(RuntimeValue(DataType.UWORD, 120))
|
RuntimeValueNumeric(DataType.UBYTE, 100).add(RuntimeValueNumeric(DataType.UWORD, 120))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.FLOAT, 100.22).add(RuntimeValue(DataType.UWORD, 120))
|
RuntimeValueNumeric(DataType.FLOAT, 100.22).add(RuntimeValueNumeric(DataType.UWORD, 120))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UWORD, 1002).add(RuntimeValue(DataType.FLOAT, 120.22))
|
RuntimeValueNumeric(DataType.UWORD, 1002).add(RuntimeValueNumeric(DataType.FLOAT, 120.22))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.FLOAT, 100.22).add(RuntimeValue(DataType.UBYTE, 120))
|
RuntimeValueNumeric(DataType.FLOAT, 100.22).add(RuntimeValueNumeric(DataType.UBYTE, 120))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UBYTE, 12).add(RuntimeValue(DataType.FLOAT, 120.22))
|
RuntimeValueNumeric(DataType.UBYTE, 12).add(RuntimeValueNumeric(DataType.FLOAT, 120.22))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNoAutoFloatConversion() {
|
fun testNoAutoFloatConversion() {
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UBYTE, 233).add(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UBYTE, 233).add(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UWORD, 233).add(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UWORD, 233).add(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UBYTE, 233).mul(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UBYTE, 233).mul(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UWORD, 233).mul(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UWORD, 233).mul(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UBYTE, 233).div(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UBYTE, 233).div(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
assertFailsWith<ArithmeticException> {
|
assertFailsWith<ArithmeticException> {
|
||||||
RuntimeValue(DataType.UWORD, 233).div(RuntimeValue(DataType.FLOAT, 1.234))
|
RuntimeValueNumeric(DataType.UWORD, 233).div(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
val result = RuntimeValue(DataType.FLOAT, 233.333).add(RuntimeValue(DataType.FLOAT, 1.234))
|
val result = RuntimeValueNumeric(DataType.FLOAT, 233.333).add(RuntimeValueNumeric(DataType.FLOAT, 1.234))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun arithmetictestUbyte() {
|
fun arithmetictestUbyte() {
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 200).add(RuntimeValue(DataType.UBYTE, 55)).integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 200).add(RuntimeValueNumeric(DataType.UBYTE, 55)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 200).add(RuntimeValue(DataType.UBYTE, 56)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 200).add(RuntimeValueNumeric(DataType.UBYTE, 56)).integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.UBYTE, 200).add(RuntimeValue(DataType.UBYTE, 57)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UBYTE, 200).add(RuntimeValueNumeric(DataType.UBYTE, 57)).integerValue())
|
||||||
|
|
||||||
assertEquals(1, RuntimeValue(DataType.UBYTE, 2).sub(RuntimeValue(DataType.UBYTE, 1)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UBYTE, 2).sub(RuntimeValueNumeric(DataType.UBYTE, 1)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 2).sub(RuntimeValue(DataType.UBYTE, 2)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 2).sub(RuntimeValueNumeric(DataType.UBYTE, 2)).integerValue())
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 2).sub(RuntimeValue(DataType.UBYTE, 3)).integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 2).sub(RuntimeValueNumeric(DataType.UBYTE, 3)).integerValue())
|
||||||
|
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 254).inc().integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 254).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 255).inc().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 255).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 1).dec().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 1).dec().integerValue())
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 0).dec().integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 0).dec().integerValue())
|
||||||
|
|
||||||
assertEquals(255, RuntimeValue(DataType.UBYTE, 0).inv().integerValue())
|
assertEquals(255, RuntimeValueNumeric(DataType.UBYTE, 0).inv().integerValue())
|
||||||
assertEquals(0b00110011, RuntimeValue(DataType.UBYTE, 0b11001100).inv().integerValue())
|
assertEquals(0b00110011, RuntimeValueNumeric(DataType.UBYTE, 0b11001100).inv().integerValue())
|
||||||
// assertEquals(0, RuntimeValue(DataType.UBYTE, 0).neg().integerValue())
|
// assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 0).neg().integerValue())
|
||||||
// assertEquals(0, RuntimeValue(DataType.UBYTE, 0).neg().integerValue())
|
// assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 0).neg().integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.UBYTE, 0).not().integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UBYTE, 0).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 1).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 1).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 111).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 111).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UBYTE, 255).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UBYTE, 255).not().integerValue())
|
||||||
|
|
||||||
assertEquals(200, RuntimeValue(DataType.UBYTE, 20).mul(RuntimeValue(DataType.UBYTE, 10)).integerValue())
|
assertEquals(200, RuntimeValueNumeric(DataType.UBYTE, 20).mul(RuntimeValueNumeric(DataType.UBYTE, 10)).integerValue())
|
||||||
assertEquals(144, RuntimeValue(DataType.UBYTE, 20).mul(RuntimeValue(DataType.UBYTE, 20)).integerValue())
|
assertEquals(144, RuntimeValueNumeric(DataType.UBYTE, 20).mul(RuntimeValueNumeric(DataType.UBYTE, 20)).integerValue())
|
||||||
|
|
||||||
assertEquals(25, RuntimeValue(DataType.UBYTE, 5).pow(RuntimeValue(DataType.UBYTE, 2)).integerValue())
|
assertEquals(25, RuntimeValueNumeric(DataType.UBYTE, 5).pow(RuntimeValueNumeric(DataType.UBYTE, 2)).integerValue())
|
||||||
assertEquals(125, RuntimeValue(DataType.UBYTE, 5).pow(RuntimeValue(DataType.UBYTE, 3)).integerValue())
|
assertEquals(125, RuntimeValueNumeric(DataType.UBYTE, 5).pow(RuntimeValueNumeric(DataType.UBYTE, 3)).integerValue())
|
||||||
assertEquals(113, RuntimeValue(DataType.UBYTE, 5).pow(RuntimeValue(DataType.UBYTE, 4)).integerValue())
|
assertEquals(113, RuntimeValueNumeric(DataType.UBYTE, 5).pow(RuntimeValueNumeric(DataType.UBYTE, 4)).integerValue())
|
||||||
|
|
||||||
assertEquals(100, RuntimeValue(DataType.UBYTE, 50).shl().integerValue())
|
assertEquals(100, RuntimeValueNumeric(DataType.UBYTE, 50).shl().integerValue())
|
||||||
assertEquals(200, RuntimeValue(DataType.UBYTE, 100).shl().integerValue())
|
assertEquals(200, RuntimeValueNumeric(DataType.UBYTE, 100).shl().integerValue())
|
||||||
assertEquals(144, RuntimeValue(DataType.UBYTE, 200).shl().integerValue())
|
assertEquals(144, RuntimeValueNumeric(DataType.UBYTE, 200).shl().integerValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun arithmetictestUWord() {
|
fun arithmetictestUWord() {
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 60000).add(RuntimeValue(DataType.UWORD, 5535)).integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 60000).add(RuntimeValueNumeric(DataType.UWORD, 5535)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 60000).add(RuntimeValue(DataType.UWORD, 5536)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 60000).add(RuntimeValueNumeric(DataType.UWORD, 5536)).integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.UWORD, 60000).add(RuntimeValue(DataType.UWORD, 5537)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UWORD, 60000).add(RuntimeValueNumeric(DataType.UWORD, 5537)).integerValue())
|
||||||
|
|
||||||
assertEquals(1, RuntimeValue(DataType.UWORD, 2).sub(RuntimeValue(DataType.UWORD, 1)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UWORD, 2).sub(RuntimeValueNumeric(DataType.UWORD, 1)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 2).sub(RuntimeValue(DataType.UWORD, 2)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 2).sub(RuntimeValueNumeric(DataType.UWORD, 2)).integerValue())
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 2).sub(RuntimeValue(DataType.UWORD, 3)).integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 2).sub(RuntimeValueNumeric(DataType.UWORD, 3)).integerValue())
|
||||||
|
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 65534).inc().integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 65534).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 65535).inc().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 65535).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 1).dec().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 1).dec().integerValue())
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 0).dec().integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 0).dec().integerValue())
|
||||||
|
|
||||||
assertEquals(65535, RuntimeValue(DataType.UWORD, 0).inv().integerValue())
|
assertEquals(65535, RuntimeValueNumeric(DataType.UWORD, 0).inv().integerValue())
|
||||||
assertEquals(0b0011001101010101, RuntimeValue(DataType.UWORD, 0b1100110010101010).inv().integerValue())
|
assertEquals(0b0011001101010101, RuntimeValueNumeric(DataType.UWORD, 0b1100110010101010).inv().integerValue())
|
||||||
// assertEquals(0, RuntimeValue(DataType.UWORD, 0).neg().integerValue())
|
// assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 0).neg().integerValue())
|
||||||
// assertEquals(0, RuntimeValue(DataType.UWORD, 0).neg().integerValue())
|
// assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 0).neg().integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.UWORD, 0).not().integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.UWORD, 0).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 1).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 1).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 11111).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 11111).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.UWORD, 65535).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.UWORD, 65535).not().integerValue())
|
||||||
|
|
||||||
assertEquals(2000, RuntimeValue(DataType.UWORD, 200).mul(RuntimeValue(DataType.UWORD, 10)).integerValue())
|
assertEquals(2000, RuntimeValueNumeric(DataType.UWORD, 200).mul(RuntimeValueNumeric(DataType.UWORD, 10)).integerValue())
|
||||||
assertEquals(40000, RuntimeValue(DataType.UWORD, 200).mul(RuntimeValue(DataType.UWORD, 200)).integerValue())
|
assertEquals(40000, RuntimeValueNumeric(DataType.UWORD, 200).mul(RuntimeValueNumeric(DataType.UWORD, 200)).integerValue())
|
||||||
assertEquals(14464, RuntimeValue(DataType.UWORD, 200).mul(RuntimeValue(DataType.UWORD, 400)).integerValue())
|
assertEquals(14464, RuntimeValueNumeric(DataType.UWORD, 200).mul(RuntimeValueNumeric(DataType.UWORD, 400)).integerValue())
|
||||||
|
|
||||||
assertEquals(15625, RuntimeValue(DataType.UWORD, 5).pow(RuntimeValue(DataType.UWORD, 6)).integerValue())
|
assertEquals(15625, RuntimeValueNumeric(DataType.UWORD, 5).pow(RuntimeValueNumeric(DataType.UWORD, 6)).integerValue())
|
||||||
assertEquals(12589, RuntimeValue(DataType.UWORD, 5).pow(RuntimeValue(DataType.UWORD, 7)).integerValue())
|
assertEquals(12589, RuntimeValueNumeric(DataType.UWORD, 5).pow(RuntimeValueNumeric(DataType.UWORD, 7)).integerValue())
|
||||||
|
|
||||||
assertEquals(10000, RuntimeValue(DataType.UWORD, 5000).shl().integerValue())
|
assertEquals(10000, RuntimeValueNumeric(DataType.UWORD, 5000).shl().integerValue())
|
||||||
assertEquals(60000, RuntimeValue(DataType.UWORD, 30000).shl().integerValue())
|
assertEquals(60000, RuntimeValueNumeric(DataType.UWORD, 30000).shl().integerValue())
|
||||||
assertEquals(14464, RuntimeValue(DataType.UWORD, 40000).shl().integerValue())
|
assertEquals(14464, RuntimeValueNumeric(DataType.UWORD, 40000).shl().integerValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun arithmetictestByte() {
|
fun arithmetictestByte() {
|
||||||
assertEquals(127, RuntimeValue(DataType.BYTE, 100).add(RuntimeValue(DataType.BYTE, 27)).integerValue())
|
assertEquals(127, RuntimeValueNumeric(DataType.BYTE, 100).add(RuntimeValueNumeric(DataType.BYTE, 27)).integerValue())
|
||||||
assertEquals(-128, RuntimeValue(DataType.BYTE, 100).add(RuntimeValue(DataType.BYTE, 28)).integerValue())
|
assertEquals(-128, RuntimeValueNumeric(DataType.BYTE, 100).add(RuntimeValueNumeric(DataType.BYTE, 28)).integerValue())
|
||||||
assertEquals(-127, RuntimeValue(DataType.BYTE, 100).add(RuntimeValue(DataType.BYTE, 29)).integerValue())
|
assertEquals(-127, RuntimeValueNumeric(DataType.BYTE, 100).add(RuntimeValueNumeric(DataType.BYTE, 29)).integerValue())
|
||||||
|
|
||||||
assertEquals(1, RuntimeValue(DataType.BYTE, 2).sub(RuntimeValue(DataType.BYTE, 1)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.BYTE, 2).sub(RuntimeValueNumeric(DataType.BYTE, 1)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 2).sub(RuntimeValue(DataType.BYTE, 2)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 2).sub(RuntimeValueNumeric(DataType.BYTE, 2)).integerValue())
|
||||||
assertEquals(-1, RuntimeValue(DataType.BYTE, 2).sub(RuntimeValue(DataType.BYTE, 3)).integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.BYTE, 2).sub(RuntimeValueNumeric(DataType.BYTE, 3)).integerValue())
|
||||||
assertEquals(-128, RuntimeValue(DataType.BYTE, -100).sub(RuntimeValue(DataType.BYTE, 28)).integerValue())
|
assertEquals(-128, RuntimeValueNumeric(DataType.BYTE, -100).sub(RuntimeValueNumeric(DataType.BYTE, 28)).integerValue())
|
||||||
assertEquals(127, RuntimeValue(DataType.BYTE, -100).sub(RuntimeValue(DataType.BYTE, 29)).integerValue())
|
assertEquals(127, RuntimeValueNumeric(DataType.BYTE, -100).sub(RuntimeValueNumeric(DataType.BYTE, 29)).integerValue())
|
||||||
|
|
||||||
assertEquals(127, RuntimeValue(DataType.BYTE, 126).inc().integerValue())
|
assertEquals(127, RuntimeValueNumeric(DataType.BYTE, 126).inc().integerValue())
|
||||||
assertEquals(-128, RuntimeValue(DataType.BYTE, 127).inc().integerValue())
|
assertEquals(-128, RuntimeValueNumeric(DataType.BYTE, 127).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 1).dec().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 1).dec().integerValue())
|
||||||
assertEquals(-1, RuntimeValue(DataType.BYTE, 0).dec().integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.BYTE, 0).dec().integerValue())
|
||||||
assertEquals(-128, RuntimeValue(DataType.BYTE, -127).dec().integerValue())
|
assertEquals(-128, RuntimeValueNumeric(DataType.BYTE, -127).dec().integerValue())
|
||||||
assertEquals(127, RuntimeValue(DataType.BYTE, -128).dec().integerValue())
|
assertEquals(127, RuntimeValueNumeric(DataType.BYTE, -128).dec().integerValue())
|
||||||
|
|
||||||
assertEquals(-1, RuntimeValue(DataType.BYTE, 0).inv().integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.BYTE, 0).inv().integerValue())
|
||||||
assertEquals(-103, RuntimeValue(DataType.BYTE, 0b01100110).inv().integerValue())
|
assertEquals(-103, RuntimeValueNumeric(DataType.BYTE, 0b01100110).inv().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 0).neg().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 0).neg().integerValue())
|
||||||
assertEquals(-2, RuntimeValue(DataType.BYTE, 2).neg().integerValue())
|
assertEquals(-2, RuntimeValueNumeric(DataType.BYTE, 2).neg().integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.BYTE, 0).not().integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.BYTE, 0).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 1).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 1).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, 111).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, 111).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.BYTE, -33).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.BYTE, -33).not().integerValue())
|
||||||
|
|
||||||
assertEquals(100, RuntimeValue(DataType.BYTE, 10).mul(RuntimeValue(DataType.BYTE, 10)).integerValue())
|
assertEquals(100, RuntimeValueNumeric(DataType.BYTE, 10).mul(RuntimeValueNumeric(DataType.BYTE, 10)).integerValue())
|
||||||
assertEquals(-56, RuntimeValue(DataType.BYTE, 20).mul(RuntimeValue(DataType.BYTE, 10)).integerValue())
|
assertEquals(-56, RuntimeValueNumeric(DataType.BYTE, 20).mul(RuntimeValueNumeric(DataType.BYTE, 10)).integerValue())
|
||||||
|
|
||||||
assertEquals(25, RuntimeValue(DataType.BYTE, 5).pow(RuntimeValue(DataType.BYTE, 2)).integerValue())
|
assertEquals(25, RuntimeValueNumeric(DataType.BYTE, 5).pow(RuntimeValueNumeric(DataType.BYTE, 2)).integerValue())
|
||||||
assertEquals(125, RuntimeValue(DataType.BYTE, 5).pow(RuntimeValue(DataType.BYTE, 3)).integerValue())
|
assertEquals(125, RuntimeValueNumeric(DataType.BYTE, 5).pow(RuntimeValueNumeric(DataType.BYTE, 3)).integerValue())
|
||||||
assertEquals(113, RuntimeValue(DataType.BYTE, 5).pow(RuntimeValue(DataType.BYTE, 4)).integerValue())
|
assertEquals(113, RuntimeValueNumeric(DataType.BYTE, 5).pow(RuntimeValueNumeric(DataType.BYTE, 4)).integerValue())
|
||||||
|
|
||||||
assertEquals(100, RuntimeValue(DataType.BYTE, 50).shl().integerValue())
|
assertEquals(100, RuntimeValueNumeric(DataType.BYTE, 50).shl().integerValue())
|
||||||
assertEquals(-56, RuntimeValue(DataType.BYTE, 100).shl().integerValue())
|
assertEquals(-56, RuntimeValueNumeric(DataType.BYTE, 100).shl().integerValue())
|
||||||
assertEquals(-2, RuntimeValue(DataType.BYTE, -1).shl().integerValue())
|
assertEquals(-2, RuntimeValueNumeric(DataType.BYTE, -1).shl().integerValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun arithmetictestWorrd() {
|
fun arithmetictestWorrd() {
|
||||||
assertEquals(32767, RuntimeValue(DataType.WORD, 32700).add(RuntimeValue(DataType.WORD, 67)).integerValue())
|
assertEquals(32767, RuntimeValueNumeric(DataType.WORD, 32700).add(RuntimeValueNumeric(DataType.WORD, 67)).integerValue())
|
||||||
assertEquals(-32768, RuntimeValue(DataType.WORD, 32700).add(RuntimeValue(DataType.WORD, 68)).integerValue())
|
assertEquals(-32768, RuntimeValueNumeric(DataType.WORD, 32700).add(RuntimeValueNumeric(DataType.WORD, 68)).integerValue())
|
||||||
assertEquals(-32767, RuntimeValue(DataType.WORD, 32700).add(RuntimeValue(DataType.WORD, 69)).integerValue())
|
assertEquals(-32767, RuntimeValueNumeric(DataType.WORD, 32700).add(RuntimeValueNumeric(DataType.WORD, 69)).integerValue())
|
||||||
|
|
||||||
assertEquals(1, RuntimeValue(DataType.WORD, 2).sub(RuntimeValue(DataType.WORD, 1)).integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.WORD, 2).sub(RuntimeValueNumeric(DataType.WORD, 1)).integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 2).sub(RuntimeValue(DataType.WORD, 2)).integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 2).sub(RuntimeValueNumeric(DataType.WORD, 2)).integerValue())
|
||||||
assertEquals(-1, RuntimeValue(DataType.WORD, 2).sub(RuntimeValue(DataType.WORD, 3)).integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.WORD, 2).sub(RuntimeValueNumeric(DataType.WORD, 3)).integerValue())
|
||||||
assertEquals(-32768, RuntimeValue(DataType.WORD, -32700).sub(RuntimeValue(DataType.WORD, 68)).integerValue())
|
assertEquals(-32768, RuntimeValueNumeric(DataType.WORD, -32700).sub(RuntimeValueNumeric(DataType.WORD, 68)).integerValue())
|
||||||
assertEquals(32767, RuntimeValue(DataType.WORD, -32700).sub(RuntimeValue(DataType.WORD, 69)).integerValue())
|
assertEquals(32767, RuntimeValueNumeric(DataType.WORD, -32700).sub(RuntimeValueNumeric(DataType.WORD, 69)).integerValue())
|
||||||
|
|
||||||
assertEquals(32767, RuntimeValue(DataType.WORD, 32766).inc().integerValue())
|
assertEquals(32767, RuntimeValueNumeric(DataType.WORD, 32766).inc().integerValue())
|
||||||
assertEquals(-32768, RuntimeValue(DataType.WORD, 32767).inc().integerValue())
|
assertEquals(-32768, RuntimeValueNumeric(DataType.WORD, 32767).inc().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 1).dec().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 1).dec().integerValue())
|
||||||
assertEquals(-1, RuntimeValue(DataType.WORD, 0).dec().integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.WORD, 0).dec().integerValue())
|
||||||
assertEquals(-32768, RuntimeValue(DataType.WORD, -32767).dec().integerValue())
|
assertEquals(-32768, RuntimeValueNumeric(DataType.WORD, -32767).dec().integerValue())
|
||||||
assertEquals(32767, RuntimeValue(DataType.WORD, -32768).dec().integerValue())
|
assertEquals(32767, RuntimeValueNumeric(DataType.WORD, -32768).dec().integerValue())
|
||||||
|
|
||||||
assertEquals(-1, RuntimeValue(DataType.WORD, 0).inv().integerValue())
|
assertEquals(-1, RuntimeValueNumeric(DataType.WORD, 0).inv().integerValue())
|
||||||
assertEquals(-103, RuntimeValue(DataType.WORD, 0b01100110).inv().integerValue())
|
assertEquals(-103, RuntimeValueNumeric(DataType.WORD, 0b01100110).inv().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 0).neg().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 0).neg().integerValue())
|
||||||
assertEquals(-2, RuntimeValue(DataType.WORD, 2).neg().integerValue())
|
assertEquals(-2, RuntimeValueNumeric(DataType.WORD, 2).neg().integerValue())
|
||||||
assertEquals(1, RuntimeValue(DataType.WORD, 0).not().integerValue())
|
assertEquals(1, RuntimeValueNumeric(DataType.WORD, 0).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 1).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 1).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, 111).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, 111).not().integerValue())
|
||||||
assertEquals(0, RuntimeValue(DataType.WORD, -33).not().integerValue())
|
assertEquals(0, RuntimeValueNumeric(DataType.WORD, -33).not().integerValue())
|
||||||
|
|
||||||
assertEquals(10000, RuntimeValue(DataType.WORD, 100).mul(RuntimeValue(DataType.WORD, 100)).integerValue())
|
assertEquals(10000, RuntimeValueNumeric(DataType.WORD, 100).mul(RuntimeValueNumeric(DataType.WORD, 100)).integerValue())
|
||||||
assertEquals(-25536, RuntimeValue(DataType.WORD, 200).mul(RuntimeValue(DataType.WORD, 200)).integerValue())
|
assertEquals(-25536, RuntimeValueNumeric(DataType.WORD, 200).mul(RuntimeValueNumeric(DataType.WORD, 200)).integerValue())
|
||||||
|
|
||||||
assertEquals(15625, RuntimeValue(DataType.WORD, 5).pow(RuntimeValue(DataType.WORD, 6)).integerValue())
|
assertEquals(15625, RuntimeValueNumeric(DataType.WORD, 5).pow(RuntimeValueNumeric(DataType.WORD, 6)).integerValue())
|
||||||
assertEquals(-6487, RuntimeValue(DataType.WORD, 9).pow(RuntimeValue(DataType.WORD, 5)).integerValue())
|
assertEquals(-6487, RuntimeValueNumeric(DataType.WORD, 9).pow(RuntimeValueNumeric(DataType.WORD, 5)).integerValue())
|
||||||
|
|
||||||
assertEquals(18000, RuntimeValue(DataType.WORD, 9000).shl().integerValue())
|
assertEquals(18000, RuntimeValueNumeric(DataType.WORD, 9000).shl().integerValue())
|
||||||
assertEquals(-25536, RuntimeValue(DataType.WORD, 20000).shl().integerValue())
|
assertEquals(-25536, RuntimeValueNumeric(DataType.WORD, 20000).shl().integerValue())
|
||||||
assertEquals(-2, RuntimeValue(DataType.WORD, -1).shl().integerValue())
|
assertEquals(-2, RuntimeValueNumeric(DataType.WORD, -1).shl().integerValue())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE
|
|||||||
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE
|
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE
|
||||||
import prog8.compiler.target.c64.MachineDefinition.Mflpt5
|
import prog8.compiler.target.c64.MachineDefinition.Mflpt5
|
||||||
import prog8.compiler.target.c64.Petscii
|
import prog8.compiler.target.c64.Petscii
|
||||||
import prog8.vm.RuntimeValue
|
import prog8.vm.RuntimeValueNumeric
|
||||||
import java.io.CharConversionException
|
import java.io.CharConversionException
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@ -380,8 +380,8 @@ class TestPetscii {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testStackvmValueComparisons() {
|
fun testStackvmValueComparisons() {
|
||||||
val ten = RuntimeValue(DataType.FLOAT, 10)
|
val ten = RuntimeValueNumeric(DataType.FLOAT, 10)
|
||||||
val nine = RuntimeValue(DataType.UWORD, 9)
|
val nine = RuntimeValueNumeric(DataType.UWORD, 9)
|
||||||
assertEquals(ten, ten)
|
assertEquals(ten, ten)
|
||||||
assertNotEquals(ten, nine)
|
assertNotEquals(ten, nine)
|
||||||
assertFalse(ten != ten)
|
assertFalse(ten != ten)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user