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(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)
}

View File

@ -18,7 +18,7 @@
if attempts_left>1 _vm_write_str("es")
_vm_write_str(" left. What is your next guess? ")
_vm_input_str(guess)
ubyte guessednumber = str2byte(guess)
ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber {
_vm_write_str("\nYou guessed it, impressive!\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
}
sub screeny(y: float) -> uword {
sub screeny(y: float) -> word {
return floor(y * flt(height)/4.1) + height // 2
}
}

View File

@ -3,37 +3,31 @@
~ main {
const uword width=320
const uword height=200
sub start() {
byte[4] barr1 = -2
byte[4] barr2 = 33
ubyte[4] barr4 = 2
ubyte[4] barr5 = 44
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 bvar = -88
ubyte ubvar = 222
word wvar = -12345
uword uwvar = 55555
; byte b1 = 50 * 2
; byte b2 = -50 * 2
; ubyte ub1 = 50 * 2
; word w1 = 999 * 2
; word w2 = -999 * 2
; uword uw1 = 999 * 2
; float f1 = 999*2
; float f2 = -999*2
byte bv2
ubyte ubv2
word wv2
uword uwv2
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
}
; 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 java.io.File
import java.io.PrintStream
import java.lang.IllegalArgumentException
import java.nio.file.Paths
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")
in ArrayDatatypes ->
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)
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)) {
if(rv.first.value!=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))
val valueDt=rv.second.resultingDatatype(namespace, heap)
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)
}

View File

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

View File

@ -35,6 +35,16 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
val constTrue = LiteralValue.fromBoolean(true, 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
when(expr.operator) {
"or" -> {
@ -112,6 +122,87 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
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 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
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.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.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
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
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.misc.*;
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.atn.ATN;
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.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Parser extends Parser {

View File

@ -1,6 +1,8 @@
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.target.c64.Petscii
import java.io.File
@ -130,7 +132,9 @@ enum class Opcode {
// numeric type conversions
LSB,
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
MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00
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_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_STR2BYTE(92),
FUNC_STR2WORD(93),
FUNC_STR2FLOAT(94)
FUNC_WRD(92),
FUNC_UWRD(93),
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:
// 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 -> {
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)
}
Opcode.PUSH_VAR_FLOAT -> {
@ -1452,6 +1460,19 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(second, DataType.FLOAT)
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 -> {
val byte = evalstack.pop()
checkDt(byte, DataType.BYTE)
@ -1787,19 +1808,67 @@ class StackVm(private var traceOutputFile: String?) {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
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 -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
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 -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
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")
if(result.toDouble() < 0 ) {
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.WORD -> Value(DataType.WORD, result.toInt())
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
fun testB2Word() {
val ins = mutableListOf(
@ -703,11 +733,17 @@ class TestStackVmOpcodes {
@Test
fun testLess() {
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, 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.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.001), Value(DataType.UBYTE, 1))
}
@ -716,10 +752,16 @@ class TestStackVmOpcodes {
fun testLessEq() {
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.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, 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, 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, 20.999), Value(DataType.UBYTE, 0))
}
@ -728,10 +770,16 @@ class TestStackVmOpcodes {
fun testGreater() {
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.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, 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, 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, 20.999), Value(DataType.UBYTE, 1))
}
@ -740,10 +788,16 @@ class TestStackVmOpcodes {
fun testGreaterEq() {
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.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, 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, 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.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.
wrd(x)
Explicitly convert the byte x to a word.
This is required if you want calculations to have word precision when the values are bytes.
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 different types.
wrdhi(x)
Explicitly convert the byte x to a word, where x will be the high byte (msb) in the word.
This can be useful in calculations with word precision when the values are bytes.
uwrd(x)
Explicitly convert the byte x to an unsigned word.
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)
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)
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
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)
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)
converts string s into the numeric value that s represents (float).