fix datatype conversion issues

This commit is contained in:
Irmen de Jong 2018-10-12 14:01:29 +02:00
parent cc54e3ec99
commit 7aec14524e
16 changed files with 358 additions and 140 deletions

View File

@ -37,7 +37,7 @@
_vm_gfx_text(8, 6, 1, "Spin") _vm_gfx_text(8, 6, 1, "Spin")
_vm_gfx_text(29, 11, 1, "to Win !") _vm_gfx_text(29, 11, 1, "to Win !")
for ubyte i in 0 to width//10 { for uword i in 0 to width//10 {
_vm_gfx_line(i*2+width//2-width//10, 130, i*10.w, 199, 6) _vm_gfx_line(i*2+width//2-width//10, 130, i*10.w, 199, 6)
} }

View File

@ -18,7 +18,7 @@
if attempts_left>1 _vm_write_str("es") if attempts_left>1 _vm_write_str("es")
_vm_write_str(" left. What is your next guess? ") _vm_write_str(" left. What is your next guess? ")
_vm_input_str(guess) _vm_input_str(guess)
ubyte guessednumber = str2byte(guess) ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber { if guessednumber==secretnumber {
_vm_write_str("\nYou guessed it, impressive!\n") _vm_write_str("\nYou guessed it, impressive!\n")
_vm_write_str("Thanks for playing.\n") _vm_write_str("Thanks for playing.\n")

View File

@ -21,10 +21,10 @@
} }
} }
sub screenx(x: float) -> uword { sub screenx(x: float) -> word {
return floor(x * flt(width)/4.1) + width // 2 return floor(x * flt(width)/4.1) + width // 2
} }
sub screeny(y: float) -> uword { sub screeny(y: float) -> word {
return floor(y * flt(height)/4.1) + height // 2 return floor(y * flt(height)/4.1) + height // 2
} }
} }

View File

@ -3,37 +3,31 @@
~ main { ~ main {
const uword width=320
const uword height=200
sub start() { sub start() {
byte[4] barr1 = -2 byte bvar = -88
byte[4] barr2 = 33 ubyte ubvar = 222
ubyte[4] barr4 = 2 word wvar = -12345
ubyte[4] barr5 = 44 uword uwvar = 55555
word[4] warr1 = 4444
word[4] warr2 = -5555
word[4] warr2b = -5522
float[4] farr1
float[4] farr2 = 23
float[4] farr3 = 55.636346
; byte b1 = 50 * 2
; byte b2 = -50 * 2 byte bv2
; ubyte ub1 = 50 * 2 ubyte ubv2
; word w1 = 999 * 2 word wv2
; word w2 = -999 * 2 uword uwv2
; uword uw1 = 999 * 2
; float f1 = 999*2
; float f2 = -999*2 bv2 = ub2b(ubvar)
ubv2 = b2ub(bvar)
wv2 = wrd(uwvar)
uwv2 = uwrd(wvar)
wv2 = wrd(ubvar)
wv2 = wrd(bvar)
uwv2 = uwrd(ubvar)
uwv2 = uwrd(bvar)
return return
} }
; sub toscreenx(x: float, z: float) -> word {
; return floor(x/(4.2+z) * flt(height)) + width // 2
; }
} }

View File

@ -9,7 +9,6 @@ import prog8.parser.ParsingFailedError
import prog8.parser.importModule import prog8.parser.importModule
import java.io.File import java.io.File
import java.io.PrintStream import java.io.PrintStream
import java.lang.IllegalArgumentException
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.system.exitProcess import kotlin.system.exitProcess

View File

@ -983,6 +983,7 @@ class LiteralValue(val type: DataType,
if(strvalue==null && heapId==null) throw FatalAstException("literal value missing strvalue/heapId") if(strvalue==null && heapId==null) throw FatalAstException("literal value missing strvalue/heapId")
in ArrayDatatypes -> in ArrayDatatypes ->
if(arrayvalue==null && heapId==null) throw FatalAstException("literal value missing arrayvalue/heapId") if(arrayvalue==null && heapId==null) throw FatalAstException("literal value missing arrayvalue/heapId")
else -> throw FatalAstException("invalid type $type")
} }
if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && strvalue==null && heapId==null) if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && strvalue==null && heapId==null)
throw FatalAstException("literal value without actual value") throw FatalAstException("literal value without actual value")

View File

@ -93,8 +93,9 @@ class AstChecker(private val namespace: INameScope,
} }
for (rv in expectedReturnValues.withIndex().zip(returnStmt.values)) { for (rv in expectedReturnValues.withIndex().zip(returnStmt.values)) {
if(rv.first.value!=rv.second.resultingDatatype(namespace, heap)) val valueDt=rv.second.resultingDatatype(namespace, heap)
checkResult.add(ExpressionError("type of return value #${rv.first.index+1} doesn't match subroutine return type ${rv.first.value}", rv.second.position)) if(rv.first.value!=valueDt)
checkResult.add(ExpressionError("type $valueDt of return value #${rv.first.index+1} doesn't match subroutine return type ${rv.first.value}", rv.second.position))
} }
return super.process(returnStmt) return super.process(returnStmt)
} }

View File

@ -950,6 +950,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
private fun translateFunctionCall(funcname: String, args: List<IExpression>) { private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
// some functions are implemented as vm opcodes // some functions are implemented as vm opcodes
// note: the arguments of the call have already been translated and put on the eval stack!
when (funcname) { when (funcname) {
"flt" -> { "flt" -> {
// 1 argument, type determines the exact opcode to use // 1 argument, type determines the exact opcode to use
@ -965,8 +966,8 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
} }
"msb" -> stackvmProg.instr(Opcode.MSB) "msb" -> stackvmProg.instr(Opcode.MSB)
"lsb" -> stackvmProg.instr(Opcode.LSB) "lsb" -> stackvmProg.instr(Opcode.LSB)
"wrd" -> stackvmProg.instr(Opcode.B2WORD) "b2ub" -> stackvmProg.instr(Opcode.B2UB)
"wrdhi" -> stackvmProg.instr(Opcode.MSB2WORD) "ub2b" -> stackvmProg.instr(Opcode.UB2B)
"lsl" -> { "lsl" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { when (arg.resultingDatatype(namespace, heap)) {

View File

@ -6,7 +6,7 @@ import kotlin.math.log2
class BuiltinFunctionParam(val name: String, val possibleDatatypes: List<DataType>) class BuiltinFunctionParam(val name: String, val possibleDatatypes: Set<DataType>)
class FunctionSignature(val pure: Boolean, // does it have side effects? class FunctionSignature(val pure: Boolean, // does it have side effects?
val parameters: List<BuiltinFunctionParam>, val parameters: List<BuiltinFunctionParam>,
@ -15,43 +15,42 @@ class FunctionSignature(val pure: Boolean, // does it have side effects?
val BuiltinFunctions = mapOf( val BuiltinFunctions = mapOf(
"rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.UBYTE, DataType.UWORD))), null), "lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) }, "sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) },
"cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) }, "cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) },
"acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) }, "acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) },
"asin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::asin) }, "asin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::asin) },
"tan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::tan) }, "tan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::tan) },
"atan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::atan) }, "atan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::atan) },
"ln" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log) }, "ln" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log) },
"log2" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, ::log2) }, "log2" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, ::log2) },
"log10" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log10) }, "log10" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log10) },
"sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) }, "sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) },
"rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) }, "rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) },
"deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) }, "deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) },
"avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.FLOAT, ::builtinAvg), "avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.FLOAT, ::builtinAvg),
"abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT, ::builtinAbs), "abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT, ::builtinAbs),
"round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) }, "round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) },
"floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) }, "floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) },
"ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) }, "ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) },
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args "max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args "min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args "sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
"len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes.toList())), DataType.UWORD, ::builtinLen), "len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), DataType.UWORD, ::builtinLen),
"any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }}, "any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }},
"all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes.toList())), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }}, "all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }},
"lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }}, "lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }},
"msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}}, "msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}},
"flt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes.toList())), DataType.FLOAT, ::builtinFlt), "flt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes)), DataType.FLOAT, ::builtinFlt),
"uwrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE, DataType.WORD))), DataType.UWORD, ::builtinUwrd), "uwrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UBYTE, DataType.BYTE, DataType.WORD))), DataType.UWORD, ::builtinUwrd),
"wrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD))), DataType.WORD, ::builtinWrd), "wrd" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD))), DataType.WORD, ::builtinWrd),
"uwrdhi" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE, DataType.BYTE))), DataType.UWORD, ::builtinWrdHi), "b2ub" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.BYTE))), DataType.UBYTE, ::builtinB2ub),
"b2ub" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE))), DataType.UBYTE, ::builtinB2ub), "ub2b" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinUb2b),
"ub2b" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.UBYTE))), DataType.BYTE, ::builtinUb2b),
"rnd" to FunctionSignature(true, emptyList(), DataType.UBYTE), "rnd" to FunctionSignature(true, emptyList(), DataType.UBYTE),
"rndw" to FunctionSignature(true, emptyList(), DataType.UWORD), "rndw" to FunctionSignature(true, emptyList(), DataType.UWORD),
"rndf" to FunctionSignature(true, emptyList(), DataType.FLOAT), "rndf" to FunctionSignature(true, emptyList(), DataType.FLOAT),
@ -59,33 +58,33 @@ val BuiltinFunctions = mapOf(
"clear_carry" to FunctionSignature(false, emptyList(), null), "clear_carry" to FunctionSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null), "set_irqd" to FunctionSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null), "clear_irqd" to FunctionSignature(false, emptyList(), null),
"str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.BYTE), "str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.BYTE),
"str2ubyte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.UBYTE), "str2ubyte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UBYTE),
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.WORD), "str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD),
"str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.UWORD), "str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD),
"str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), DataType.FLOAT), "str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.FLOAT),
"_vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.UWORD))), null), "_vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"_vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", listOf(DataType.UWORD))), null), "_vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"_vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes.toList())), null), "_vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null),
"_vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", listOf(DataType.UBYTE))), null), "_vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", setOf(DataType.UBYTE))), null),
"_vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", StringDatatypes.toList())), null), "_vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", StringDatatypes)), null),
"_vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", StringDatatypes.toList())), null), "_vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", StringDatatypes)), null),
"_vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", listOf(DataType.UBYTE))), null), "_vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", setOf(DataType.UBYTE))), null),
"_vm_gfx_pixel" to FunctionSignature(false, listOf( "_vm_gfx_pixel" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", IntegerDatatypes.toList()), BuiltinFunctionParam("x", IntegerDatatypes),
BuiltinFunctionParam("y", IntegerDatatypes.toList()), BuiltinFunctionParam("y", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes.toList())), null), BuiltinFunctionParam("color", IntegerDatatypes)), null),
"_vm_gfx_line" to FunctionSignature(false, listOf( "_vm_gfx_line" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x1", IntegerDatatypes.toList()), BuiltinFunctionParam("x1", IntegerDatatypes),
BuiltinFunctionParam("y1", IntegerDatatypes.toList()), BuiltinFunctionParam("y1", IntegerDatatypes),
BuiltinFunctionParam("x2", IntegerDatatypes.toList()), BuiltinFunctionParam("x2", IntegerDatatypes),
BuiltinFunctionParam("y2", IntegerDatatypes.toList()), BuiltinFunctionParam("y2", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes.toList())), null), BuiltinFunctionParam("color", IntegerDatatypes)), null),
"_vm_gfx_text" to FunctionSignature(false, listOf( "_vm_gfx_text" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", IntegerDatatypes.toList()), BuiltinFunctionParam("x", IntegerDatatypes),
BuiltinFunctionParam("y", IntegerDatatypes.toList()), BuiltinFunctionParam("y", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes.toList()), BuiltinFunctionParam("color", IntegerDatatypes),
BuiltinFunctionParam("text", StringDatatypes.toList())), BuiltinFunctionParam("text", StringDatatypes)),
null) null)
) )
@ -272,17 +271,6 @@ private fun builtinUwrd(args: List<IExpression>, position: Position, namespace:I
return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt(), position = position) return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt(), position = position)
} }
private fun builtinWrdHi(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 arg, convert to word (in hi byte)
if(args.size!=1)
throw SyntaxError("wrdhi requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE)
throw SyntaxError("wrdhi requires one byte argument", position)
return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt() shl 8, position = position)
}
private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue { private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 byte arg, convert to ubyte // 1 byte arg, convert to ubyte
if(args.size!=1) if(args.size!=1)
@ -291,7 +279,7 @@ private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:I
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException() val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE) if(constval.type!=DataType.BYTE)
throw SyntaxError("b2ub requires one argument of type byte", position) throw SyntaxError("b2ub requires one argument of type byte", position)
return LiteralValue(DataType.UBYTE, bytevalue=constval.bytevalue!!, position = position) return LiteralValue(DataType.UBYTE, bytevalue=(constval.bytevalue!!.toInt() and 255).toShort(), position = position)
} }
private fun builtinUb2b(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue { private fun builtinUb2b(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -302,7 +290,7 @@ private fun builtinUb2b(args: List<IExpression>, position: Position, namespace:I
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException() val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE) if(constval.type!=DataType.UBYTE)
throw SyntaxError("ub2b requires one argument of type ubyte", position) throw SyntaxError("ub2b requires one argument of type ubyte", position)
return LiteralValue(DataType.BYTE, bytevalue=constval.bytevalue!!, position = position) return LiteralValue(DataType.BYTE, bytevalue=(constval.bytevalue!!.toInt() and 255).toShort(), position = position)
} }
private fun builtinAbs(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue { private fun builtinAbs(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {

View File

@ -35,6 +35,16 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
val constTrue = LiteralValue.fromBoolean(true, expr.position) val constTrue = LiteralValue.fromBoolean(true, expr.position)
val constFalse = LiteralValue.fromBoolean(false, expr.position) val constFalse = LiteralValue.fromBoolean(false, expr.position)
val leftDt = expr.left.resultingDatatype(namespace, heap)
val rightDt = expr.right.resultingDatatype(namespace, heap)
if(leftDt!=null && rightDt!=null && leftDt!=rightDt) {
// try to convert a datatype into the other
if(adjustDatatypes(expr, leftVal, leftDt, rightVal, rightDt)) {
optimizationsDone++
return expr
}
}
// simplify logical expressions when a term is constant and determines the outcome // simplify logical expressions when a term is constant and determines the outcome
when(expr.operator) { when(expr.operator) {
"or" -> { "or" -> {
@ -112,6 +122,87 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
return expr return expr
} }
private fun adjustDatatypes(expr: BinaryExpression,
leftConstVal: LiteralValue?, leftDt: DataType,
rightConstVal: LiteralValue?, rightDt: DataType): Boolean {
fun adjust(value: LiteralValue, targetDt: DataType): Pair<Boolean, LiteralValue>{
if(value.type==targetDt)
return Pair(false, value)
when(value.type) {
DataType.UBYTE -> {
if (targetDt == DataType.BYTE) {
if(value.bytevalue!! < 127)
return Pair(true, LiteralValue(targetDt, value.bytevalue, position=value.position))
}
else if (targetDt == DataType.UWORD || targetDt == DataType.WORD)
return Pair(true, LiteralValue(targetDt, wordvalue = value.bytevalue!!.toInt(), position=value.position))
}
DataType.BYTE -> {
if (targetDt == DataType.UBYTE) {
if(value.bytevalue!! >= 0)
return Pair(true, LiteralValue(targetDt, value.bytevalue, position=value.position))
}
else if (targetDt == DataType.UWORD) {
if(value.bytevalue!! >= 0)
return Pair(true, LiteralValue(targetDt, wordvalue=value.bytevalue.toInt(), position=value.position))
}
else if (targetDt == DataType.WORD) return Pair(true, LiteralValue(targetDt, wordvalue=value.bytevalue!!.toInt(), position=value.position))
}
DataType.UWORD -> {
if (targetDt == DataType.UBYTE) {
if(value.wordvalue!! <= 255)
return Pair(true, LiteralValue(targetDt, value.wordvalue.toShort(), position=value.position))
}
else if (targetDt == DataType.BYTE) {
if(value.wordvalue!! <= 127)
return Pair(true, LiteralValue(targetDt, value.wordvalue.toShort(), position=value.position))
}
else if (targetDt == DataType.WORD) {
if(value.wordvalue!! <= 32767)
return Pair(true, LiteralValue(targetDt, wordvalue=value.wordvalue, position=value.position))
}
}
DataType.WORD -> {
if (targetDt == DataType.UBYTE) {
if(value.wordvalue!! in 0..255)
return Pair(true, LiteralValue(targetDt, value.wordvalue.toShort(), position=value.position))
}
else if (targetDt == DataType.BYTE) {
if(value.wordvalue!! in -128..127)
return Pair(true, LiteralValue(targetDt, value.wordvalue.toShort(), position=value.position))
}
else if (targetDt == DataType.UWORD) {
if(value.wordvalue!! >= 0)
return Pair(true, LiteralValue(targetDt, value.wordvalue.toShort(), position=value.position))
}
}
else -> {}
}
return Pair(false, value)
}
if(leftConstVal==null && rightConstVal!=null) {
val (adjusted, newValue) = adjust(rightConstVal, leftDt)
if(adjusted) {
expr.right = newValue
optimizationsDone++
return true
}
return false
} else if(leftConstVal!=null && rightConstVal==null) {
val (adjusted, newValue) = adjust(leftConstVal, rightDt)
if(adjusted) {
expr.left = newValue
optimizationsDone++
return true
}
return false
} else {
throw AstException("binary expression with 2 const values should have been evaluated")
}
}
private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?) private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?)
private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr { private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr {

View File

@ -1,13 +1,12 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser; package prog8.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Lexer extends Lexer { public class prog8Lexer extends Lexer {

View File

@ -1,13 +1,15 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser; package prog8.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*; import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.tree.*; import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.List; import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Parser extends Parser { public class prog8Parser extends Parser {

View File

@ -1,6 +1,8 @@
package prog8.stackvm package prog8.stackvm
import prog8.ast.* import prog8.ast.DataType
import prog8.ast.IterableDatatypes
import prog8.ast.NumericDatatypes
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.target.c64.Petscii import prog8.compiler.target.c64.Petscii
import java.io.File import java.io.File
@ -130,7 +132,9 @@ enum class Opcode {
// numeric type conversions // numeric type conversions
LSB, LSB,
MSB, MSB,
B2WORD, // convert a byte into a word where it is the lower eight bits $00xx with sign extension B2UB,
UB2B,
B2WORD, // convert a byte into a word where it is the lower eight bits $ssxx with sign extension
UB2UWORD, // convert a byte into a word where it is the lower eight bits $00xx UB2UWORD, // convert a byte into a word where it is the lower eight bits $00xx
MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00 MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00
B2FLOAT, // convert byte into floating point B2FLOAT, // convert byte into floating point
@ -284,9 +288,13 @@ enum class Syscall(val callNr: Short) {
FUNC_RND(89), // push a random byte on the stack FUNC_RND(89), // push a random byte on the stack
FUNC_RNDW(90), // push a random word on the stack FUNC_RNDW(90), // push a random word on the stack
FUNC_RNDF(91), // push a random float on the stack (between 0.0 and 1.0) FUNC_RNDF(91), // push a random float on the stack (between 0.0 and 1.0)
FUNC_STR2BYTE(92), FUNC_WRD(92),
FUNC_STR2WORD(93), FUNC_UWRD(93),
FUNC_STR2FLOAT(94) FUNC_STR2BYTE(100),
FUNC_STR2UBYTE(101),
FUNC_STR2WORD(102),
FUNC_STR2UWORD(103),
FUNC_STR2FLOAT(104)
// note: not all builtin functions of the Prog8 language are present as functions: // note: not all builtin functions of the Prog8 language are present as functions:
// some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)! // some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)!
@ -1064,7 +1072,7 @@ class StackVm(private var traceOutputFile: String?) {
} }
Opcode.PUSH_VAR_WORD -> { Opcode.PUSH_VAR_WORD -> {
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(value, setOf(DataType.UWORD, DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.MATRIX_UB)) checkDt(value, setOf(DataType.UWORD, DataType.WORD, DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.MATRIX_UB))
evalstack.push(value) evalstack.push(value)
} }
Opcode.PUSH_VAR_FLOAT -> { Opcode.PUSH_VAR_FLOAT -> {
@ -1452,6 +1460,19 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(second, DataType.FLOAT) checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.UBYTE, if(second != top) 1 else 0)) evalstack.push(Value(DataType.UBYTE, if(second != top) 1 else 0))
} }
Opcode.B2UB -> {
val byte = evalstack.pop()
checkDt(byte, DataType.BYTE)
evalstack.push(Value(DataType.UBYTE, byte.integerValue() and 255))
}
Opcode.UB2B -> {
val byte = evalstack.pop()
checkDt(byte, DataType.UBYTE)
if(byte.integerValue() > 127) {
evalstack.push(Value(DataType.BYTE, -((byte.integerValue() xor 255) + 1)))
} else
evalstack.push(Value(DataType.BYTE, byte.integerValue()))
}
Opcode.B2WORD -> { Opcode.B2WORD -> {
val byte = evalstack.pop() val byte = evalstack.pop()
checkDt(byte, DataType.BYTE) checkDt(byte, DataType.BYTE)
@ -1787,19 +1808,67 @@ class StackVm(private var traceOutputFile: String?) {
val strvar = evalstack.pop() val strvar = evalstack.pop()
val str = heap.get(strvar.heapId) val str = heap.get(strvar.heapId)
val y = str.str!!.trim().trimEnd('\u0000') val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.UBYTE, y.toShort())) evalstack.push(Value(DataType.BYTE, y.toShort()))
}
Syscall.FUNC_STR2UBYTE -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = (y.toInt() and 255).toShort()
evalstack.push(Value(DataType.UBYTE, number))
} }
Syscall.FUNC_STR2WORD -> { Syscall.FUNC_STR2WORD -> {
val strvar = evalstack.pop() val strvar = evalstack.pop()
val str = heap.get(strvar.heapId) val str = heap.get(strvar.heapId)
val y = str.str!!.trim().trimEnd('\u0000') val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.UBYTE, y.toInt())) evalstack.push(Value(DataType.WORD, y.toInt()))
}
Syscall.FUNC_STR2UWORD -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = y.toInt() and 65535
evalstack.push(Value(DataType.UWORD, number))
} }
Syscall.FUNC_STR2FLOAT -> { Syscall.FUNC_STR2FLOAT -> {
val strvar = evalstack.pop() val strvar = evalstack.pop()
val str = heap.get(strvar.heapId) val str = heap.get(strvar.heapId)
val y = str.str!!.trim().trimEnd('\u0000') val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.UBYTE, y.toDouble())) evalstack.push(Value(DataType.FLOAT, y.toDouble()))
}
Syscall.FUNC_WRD -> {
val value = evalstack.pop()
checkDt(value, setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD))
when(value.type) {
DataType.UBYTE, DataType.BYTE -> evalstack.push(Value(DataType.WORD, value.integerValue()))
DataType.UWORD -> {
val v2=
if(value.integerValue() <= 32767)
Value(DataType.WORD, value.integerValue())
else
Value(DataType.WORD, -((value.integerValue() xor 65535)+1))
evalstack.push(v2)
}
DataType.WORD -> evalstack.push(value)
else -> {}
}
}
Syscall.FUNC_UWRD -> {
val value = evalstack.pop()
checkDt(value, setOf(DataType.UBYTE, DataType.BYTE, DataType.WORD))
when(value.type) {
DataType.UBYTE -> evalstack.push(Value(DataType.UWORD, value.integerValue()))
DataType.UWORD -> evalstack.push(value)
DataType.BYTE, DataType.WORD -> {
val v2 =
if(value.integerValue()>=0)
Value(DataType.UWORD, value.integerValue())
else
Value(DataType.UWORD, (abs(value.integerValue()) xor 65535)+1)
evalstack.push(v2)
}
else -> {}
}
} }
} }
} }

View File

@ -119,7 +119,14 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
throw VmExecutionException("left and right datatypes are not the same") throw VmExecutionException("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 -> throw VmExecutionException("arithmetic error: cannot store a negative value in a $leftDt") DataType.UBYTE, DataType.UWORD -> {
// storing a negative number in an unsigned one is done by storing the 2's complement instead
val number = abs(result.toDouble().toInt())
if(leftDt==DataType.UBYTE)
Value(DataType.UBYTE, (number xor 255) +1)
else
Value(DataType.UBYTE, (number xor 65535) +1)
}
DataType.BYTE -> Value(DataType.BYTE, result.toInt()) DataType.BYTE -> Value(DataType.BYTE, result.toInt())
DataType.WORD -> Value(DataType.WORD, result.toInt()) DataType.WORD -> Value(DataType.WORD, result.toInt())
DataType.FLOAT -> Value(DataType.FLOAT, result) DataType.FLOAT -> Value(DataType.FLOAT, result)

View File

@ -509,6 +509,36 @@ class TestStackVmOpcodes {
} }
} }
@Test
fun testB2Ub() {
val ins = mutableListOf(
Instruction(Opcode.PUSH_BYTE, Value(DataType.BYTE, -88)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.BYTE, 127)),
Instruction(Opcode.B2UB),
Instruction(Opcode.B2UB)
)
vm.load(makeProg(ins), null)
vm.step(3)
assertEquals(Value(DataType.UBYTE, 127), vm.evalstack.pop())
vm.step(1)
assertEquals(Value(DataType.UBYTE, 168), vm.evalstack.pop())
}
@Test
fun testUB2b() {
val ins = mutableListOf(
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 168)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 127)),
Instruction(Opcode.UB2B),
Instruction(Opcode.UB2B)
)
vm.load(makeProg(ins), null)
vm.step(3)
assertEquals(Value(DataType.BYTE, 127), vm.evalstack.pop())
vm.step(1)
assertEquals(Value(DataType.BYTE, -88), vm.evalstack.pop())
}
@Test @Test
fun testB2Word() { fun testB2Word() {
val ins = mutableListOf( val ins = mutableListOf(
@ -703,11 +733,17 @@ class TestStackVmOpcodes {
@Test @Test
fun testLess() { fun testLess() {
testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.LESS_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.LESS_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.LESS_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.LESS_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESS_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.BYTE, -2), Opcode.LESS_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 2), Opcode.LESS_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 2), Opcode.LESS_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 20), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 20), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESS_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.WORD, -2), Opcode.LESS_W, Value(DataType.WORD, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.001), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.001), Value(DataType.UBYTE, 1))
} }
@ -716,10 +752,16 @@ class TestStackVmOpcodes {
fun testLessEq() { fun testLessEq() {
testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.LESSEQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.LESSEQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.LESSEQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.LESSEQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESSEQ_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, -2), Opcode.LESSEQ_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 2), Opcode.LESSEQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 2), Opcode.LESSEQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 20), Opcode.LESSEQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 20), Opcode.LESSEQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESSEQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESSEQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESSEQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.LESSEQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESSEQ_W, Value(DataType.WORD, 20), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.WORD, -2), Opcode.LESSEQ_W, Value(DataType.WORD, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 20.999), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 20.999), Value(DataType.UBYTE, 0))
} }
@ -728,10 +770,16 @@ class TestStackVmOpcodes {
fun testGreater() { fun testGreater() {
testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.GREATER_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.GREATER_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.GREATER_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.GREATER_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATER_B, Value(DataType.BYTE, -1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, -1), Opcode.GREATER_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 2), Opcode.GREATER_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 2), Opcode.GREATER_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 20), Opcode.GREATER_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 20), Opcode.GREATER_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATER_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATER_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATER_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATER_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATER_W, Value(DataType.WORD, -21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.WORD, -2), Opcode.GREATER_W, Value(DataType.WORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 20.999), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 20.999), Value(DataType.UBYTE, 1))
} }
@ -740,10 +788,16 @@ class TestStackVmOpcodes {
fun testGreaterEq() { fun testGreaterEq() {
testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.GREATEREQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UBYTE, 0), Opcode.GREATEREQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.GREATEREQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UBYTE, 1), Opcode.GREATEREQ_UB, Value(DataType.UBYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATEREQ_B, Value(DataType.BYTE, 1), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.BYTE, -11), Opcode.GREATEREQ_B, Value(DataType.BYTE, 11), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 2), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 2), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 20), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.UWORD, 20), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 20), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.UWORD, 21), Opcode.GREATEREQ_UW, Value(DataType.UWORD, 21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.WORD, -21), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.UBYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 1)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.UBYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.001), Value(DataType.UBYTE, 0)) testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.001), Value(DataType.UBYTE, 0))
} }

View File

@ -567,15 +567,21 @@ flt(x)
This is required if you want calculations to have floating point precision when the values aren't float already. This is required if you want calculations to have floating point precision when the values aren't float already.
wrd(x) wrd(x)
Explicitly convert the byte x to a word. Explicitly convert the value x to a signed word (sign extended).
This is required if you want calculations to have word precision when the values are bytes. This is required if you want calculations to have word precision when the values are different types.
wrdhi(x) uwrd(x)
Explicitly convert the byte x to a word, where x will be the high byte (msb) in the word. Explicitly convert the byte x to an unsigned word.
This can be useful in calculations with word precision when the values are bytes. This is required if you want calculations to have unsigned word precision when the values are different types.
b2ub(x)
Convert signed byte to unsinged byte. Uses 2's complement if dealing with a negative number.
ub2b(x)
Convert an unsigned byte to a signed byte. Uses 2's complement to deal with negative numbers.
any(x) any(x)
1 ('true') if any of the values in the non-scalar (array or matrix) value x is 'true' (not zero), else 0 ('false') 1 ('true') if any of the values in the non-scalar (array or matrix) value x is 'true' (not zero), else 0 ('false')
all(x) all(x)
1 ('true') if all of the values in the non-scalar (array or matrix) value x are 'true' (not zero), else 0 ('false') 1 ('true') if all of the values in the non-scalar (array or matrix) value x are 'true' (not zero), else 0 ('false')
@ -590,10 +596,16 @@ rndf()
returns a pseudo-random float between 0.0 and 1.0 returns a pseudo-random float between 0.0 and 1.0
str2byte(s) str2byte(s)
converts string s into the numeric value that s represents (byte). converts string s into the numeric value that s represents (signed byte).
str2ubyte(s)
converts string s into the numeric value that s represents (unsigned byte).
str2word(s) str2word(s)
converts string s into the numeric value that s represents (word). converts string s into the numeric value that s represents (signed word).
str2uword(s)
converts string s into the numeric value that s represents (unsigned word).
str2float(s) str2float(s)
converts string s into the numeric value that s represents (float). converts string s into the numeric value that s represents (float).