mirror of
https://github.com/irmen/prog8.git
synced 2024-09-29 08:57:51 +00:00
fix datatype conversion issues
This commit is contained in:
parent
cc54e3ec99
commit
7aec14524e
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
; }
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user