introduced type cast "... as ..." instead of builtin functions

This commit is contained in:
Irmen de Jong 2018-12-20 02:52:33 +01:00
parent 445db44c05
commit 5870006b2f
13 changed files with 253 additions and 446 deletions

View File

@ -8,12 +8,14 @@
; @todo unify the type cast functions... "wrd(5)" -> "5 as word"
; @todo docs: "integer / int will not result in float but is integer floor division." verify this!
sub toscreenx(float x, float z) -> word {
return 42 as word
}
asmsub blerp(ubyte x @ A, uword ding @ XY) -> clobbers() -> () {
word qq = X as word
word qq = A as word
}
sub start() {

View File

@ -39,7 +39,7 @@ private fun compileMain(args: Array<String>) {
else if(!arg.startsWith("--"))
moduleFile = arg
}
if(moduleFile.isNullOrBlank())
if(moduleFile.isBlank())
usage()
val filepath = Paths.get(moduleFile).normalize()

View File

@ -995,7 +995,6 @@ class TypecastExpression(var expression: IExpression, var type: DataType, overri
companion object {
fun typecast(cv: LiteralValue, type: DataType): LiteralValue? {
println("CONSTVALUE $cv -> $type")
return when (cv.type) {
DataType.UBYTE -> {
when (type) {

View File

@ -1,6 +1,5 @@
package prog8.ast
import com.sun.org.apache.xpath.internal.operations.Bool
import prog8.compiler.CompilationOptions
import prog8.compiler.HeapValues
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE

View File

@ -580,8 +580,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
private fun convertType(givenDt: DataType, targetDt: DataType) {
// only WIDENS a type, never NARROWS
// TODO replace by type cast "... as type" ?
// only WIDENS a type, never NARROWS. To avoid loss of precision.
if(givenDt==targetDt)
return
if(givenDt !in NumericDatatypes)
@ -590,23 +589,25 @@ private class StatementTranslator(private val prog: IntermediateProgram,
throw CompilerException("converting $givenDt to non-numeric $targetDt")
when(givenDt) {
DataType.UBYTE -> when(targetDt) {
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.UB2UWORD)
DataType.FLOAT -> prog.instr(Opcode.UB2FLOAT)
DataType.UWORD -> prog.instr(Opcode.CAST_UB_TO_UW)
DataType.WORD -> prog.instr(Opcode.CAST_UB_TO_W)
DataType.FLOAT -> prog.instr(Opcode.CAST_UB_TO_F)
else -> {}
}
DataType.BYTE -> when(targetDt) {
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.B2WORD)
DataType.FLOAT -> prog.instr(Opcode.B2FLOAT)
DataType.UWORD -> prog.instr(Opcode.CAST_B_TO_UW)
DataType.WORD -> prog.instr(Opcode.CAST_B_TO_W)
DataType.FLOAT -> prog.instr(Opcode.CAST_B_TO_F)
else -> {}
}
DataType.UWORD -> when(targetDt) {
DataType.UBYTE, DataType.BYTE -> throw CompilerException("narrowing type")
DataType.FLOAT -> prog.instr(Opcode.UW2FLOAT)
DataType.FLOAT -> prog.instr(Opcode.CAST_UW_TO_F)
else -> {}
}
DataType.WORD -> when(targetDt) {
DataType.UBYTE, DataType.BYTE -> throw CompilerException("narrowing type")
DataType.FLOAT -> prog.instr(Opcode.W2FLOAT)
DataType.FLOAT -> prog.instr(Opcode.CAST_W_TO_F)
else -> {}
}
DataType.FLOAT -> if(targetDt in IntegerDatatypes) throw CompilerException("narrowing type")
@ -724,22 +725,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
else -> throw CompilerException("wrong datatype for $funcname()")
}
}
"flt" -> {
// 1 argument, type determines the exact opcode to use
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.UBYTE -> prog.instr(Opcode.UB2FLOAT)
DataType.BYTE -> prog.instr(Opcode.B2FLOAT)
DataType.UWORD -> prog.instr(Opcode.UW2FLOAT)
DataType.WORD -> prog.instr(Opcode.W2FLOAT)
DataType.FLOAT -> prog.instr(Opcode.NOP)
else -> throw CompilerException("wrong datatype for flt()")
}
}
"msb" -> prog.instr(Opcode.MSB)
"lsb" -> prog.instr(Opcode.LSB)
"b2ub" -> prog.instr(Opcode.B2UB)
"ub2b" -> prog.instr(Opcode.UB2B)
"lsb" -> TODO("lsb -> uw2ub or w2ub?")
"lsl" -> {
val arg = args.single()
val dt = arg.resultingDatatype(namespace, heap)
@ -1269,15 +1256,15 @@ private class StatementTranslator(private val prog: IntermediateProgram,
throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.WORD -> {
when (valueDt) {
DataType.UBYTE -> prog.instr(Opcode.UB2UWORD)
DataType.BYTE -> prog.instr(Opcode.B2WORD)
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_W)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_W)
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
}
}
DataType.UWORD -> {
when (valueDt) {
DataType.UBYTE -> prog.instr(Opcode.UB2UWORD)
DataType.BYTE -> prog.instr(Opcode.B2WORD)
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_UW)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_UW)
DataType.STR, DataType.STR_S -> pushStringAddress(stmt.value, true)
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_F -> {
if (stmt.value is IdentifierReference) {
@ -1293,10 +1280,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
DataType.FLOAT -> {
when (valueDt) {
DataType.UBYTE -> prog.instr(Opcode.UB2FLOAT)
DataType.BYTE -> prog.instr(Opcode.B2FLOAT)
DataType.UWORD -> prog.instr(Opcode.UW2FLOAT)
DataType.WORD -> prog.instr(Opcode.W2FLOAT)
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_F)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_F)
DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_F)
DataType.WORD -> prog.instr(Opcode.CAST_W_TO_F)
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
}
}
@ -1979,7 +1966,52 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
private fun translate(expr: TypecastExpression) {
TODO("translate typecast $expr") //To change body of created functions use File | Settings | File Templates.
translate(expr.expression)
val sourceDt = expr.expression.resultingDatatype(namespace, heap) ?: throw CompilerException("don't know what type to cast")
if(sourceDt==expr.type)
return
when(expr.type) {
DataType.UBYTE -> when(sourceDt) {
DataType.UBYTE -> {}
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_UB)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.CAST_WRD_TO_UB)
DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_UB)
else -> throw CompilerException("invalid cast type $sourceDt")
}
DataType.BYTE -> when(sourceDt) {
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_B)
DataType.BYTE -> {}
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.CAST_WRD_TO_B)
DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_B)
else -> throw CompilerException("invalid cast type $sourceDt")
}
DataType.UWORD -> when(sourceDt) {
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_UW)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_UW)
DataType.UWORD -> {}
DataType.WORD -> prog.instr(Opcode.CAST_W_TO_UW)
DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_UW)
else -> throw CompilerException("invalid cast type $sourceDt")
}
DataType.WORD -> when(sourceDt) {
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_W)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_W)
DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_W)
DataType.WORD -> {}
DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_W)
else -> throw CompilerException("invalid cast type $sourceDt")
}
DataType.FLOAT -> when(sourceDt) {
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_F)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_F)
DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_F)
DataType.WORD -> prog.instr(Opcode.CAST_W_TO_F)
DataType.FLOAT -> {}
else -> throw CompilerException("invalid cast type $sourceDt")
}
else -> throw CompilerException("can't typecast to ${expr.type}")
}
}
}

View File

@ -179,26 +179,21 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
fun optimizeFloatConversion(index0: Int, index1: Int, ins1: Instruction) {
when (ins1.opcode) {
Opcode.LSB,
Opcode.MSB,
Opcode.B2WORD,
Opcode.UB2UWORD,
Opcode.B2FLOAT,
Opcode.UB2FLOAT,
Opcode.UW2FLOAT,
Opcode.W2FLOAT -> throw CompilerException("invalid conversion following a float")
Opcode.DISCARD_FLOAT -> {
instructionsToReplace[index0] = Instruction(Opcode.NOP)
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.DISCARD_BYTE, Opcode.DISCARD_WORD -> throw CompilerException("invalid discard type following a float")
else -> throw CompilerException("invalid conversion opcode ${ins1.opcode}")
else -> throw CompilerException("invalid conversion opcode ${ins1.opcode} following a float")
}
}
fun optimizeWordConversion(index0: Int, ins0: Instruction, index1: Int, ins1: Instruction) {
when (ins1.opcode) {
Opcode.LSB -> {
Opcode.CAST_B_TO_W, Opcode.CAST_B_TO_UW -> TODO("cast byte to (u)word")
Opcode.CAST_UB_TO_W, Opcode.CAST_UB_TO_UW -> TODO("cast ubyte to (u)word")
Opcode.CAST_WRD_TO_B -> TODO("cast (u)word to byte")
Opcode.CAST_WRD_TO_UB -> {
val ins = Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, ins0.arg!!.integerValue() and 255))
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
@ -208,11 +203,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.B2WORD,
Opcode.UB2UWORD,
Opcode.B2FLOAT,
Opcode.UB2FLOAT -> throw CompilerException("invalid conversion following a word")
Opcode.W2FLOAT, Opcode.UW2FLOAT -> {
Opcode.CAST_W_TO_F, Opcode.CAST_UW_TO_F -> {
val ins = Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, ins0.arg!!.integerValue().toDouble()))
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
@ -222,30 +213,32 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.DISCARD_BYTE, Opcode.DISCARD_FLOAT -> throw CompilerException("invalid discard type following a byte")
else -> throw CompilerException("invalid conversion opcode ${ins1.opcode}")
else -> throw CompilerException("invalid conversion opcode ${ins1.opcode} following a word")
}
}
fun optimizeByteConversion(index0: Int, ins0: Instruction, index1: Int, ins1: Instruction) {
when (ins1.opcode) {
Opcode.LSB -> instructionsToReplace[index1] = Instruction(Opcode.NOP)
Opcode.CAST_B_TO_UB, Opcode.CAST_UB_TO_B,
Opcode.CAST_WRD_TO_B, Opcode.CAST_WRD_TO_UB -> instructionsToReplace[index1] = Instruction(Opcode.NOP)
Opcode.MSB -> throw CompilerException("msb of a byte")
Opcode.UB2UWORD -> {
Opcode.CAST_UB_TO_UW -> {
val ins = Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, ins0.arg!!.integerValue()))
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.B2WORD -> {
Opcode.CAST_B_TO_W -> {
val ins = Instruction(Opcode.PUSH_WORD, Value(DataType.WORD, ins0.arg!!.integerValue()))
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.B2FLOAT, Opcode.UB2FLOAT -> {
Opcode.CAST_B_TO_UW, Opcode.CAST_UB_TO_W -> TODO("cast byte to (u)word")
Opcode.CAST_B_TO_F, Opcode.CAST_UB_TO_F-> {
val ins = Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, ins0.arg!!.integerValue().toDouble()))
instructionsToReplace[index0] = ins
instructionsToReplace[index1] = Instruction(Opcode.NOP)
}
Opcode.W2FLOAT, Opcode.UW2FLOAT -> throw CompilerException("invalid conversion following a byte")
Opcode.CAST_W_TO_F, Opcode.CAST_UW_TO_F-> throw CompilerException("invalid conversion following a byte")
Opcode.DISCARD_BYTE -> {
instructionsToReplace[index0] = Instruction(Opcode.NOP)
instructionsToReplace[index1] = Instruction(Opcode.NOP)
@ -259,14 +252,25 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
instructionsToReplace.clear()
val typeConversionOpcodes = setOf(
Opcode.LSB,
Opcode.MSB,
Opcode.B2WORD,
Opcode.UB2UWORD,
Opcode.B2FLOAT,
Opcode.UB2FLOAT,
Opcode.W2FLOAT,
Opcode.UW2FLOAT,
Opcode.CAST_UB_TO_B,
Opcode.CAST_UB_TO_UW,
Opcode.CAST_UB_TO_W,
Opcode.CAST_UB_TO_F,
Opcode.CAST_B_TO_UB,
Opcode.CAST_B_TO_UW,
Opcode.CAST_B_TO_W,
Opcode.CAST_B_TO_F,
Opcode.CAST_UW_TO_W,
Opcode.CAST_UW_TO_F,
Opcode.CAST_WRD_TO_UB,
Opcode.CAST_WRD_TO_B,
Opcode.CAST_W_TO_UW,
Opcode.CAST_W_TO_F,
Opcode.CAST_F_TO_UB,
Opcode.CAST_F_TO_B,
Opcode.CAST_F_TO_UW,
Opcode.CAST_F_TO_W,
Opcode.DISCARD_BYTE,
Opcode.DISCARD_WORD,
Opcode.DISCARD_FLOAT

View File

@ -119,16 +119,25 @@ enum class Opcode {
INV_WORD,
// numeric type conversions
LSB,
MSB,
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
B2FLOAT, // convert byte into floating point
UB2FLOAT, // convert unsigned byte into floating point
W2FLOAT, // convert word into floating point
UW2FLOAT, // convert unsigned word into floating point
MSB, // note: lsb is equivalent to CAST_UW_TO_UB or CAST_WRD_TO_UB
CAST_UB_TO_B,
CAST_UB_TO_UW,
CAST_UB_TO_W,
CAST_UB_TO_F,
CAST_B_TO_UB,
CAST_B_TO_UW,
CAST_B_TO_W,
CAST_B_TO_F,
CAST_WRD_TO_UB, // word and uword: just take the LSB
CAST_WRD_TO_B, // word and uword: just take the LSB
CAST_W_TO_UW,
CAST_W_TO_F,
CAST_UW_TO_W,
CAST_UW_TO_F,
CAST_F_TO_UB,
CAST_F_TO_B,
CAST_F_TO_UW,
CAST_F_TO_W,
// logical operations
AND_BYTE,

View File

@ -386,15 +386,6 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
}
}
fun lsb(): Value {
return when(type) {
DataType.UBYTE -> Value(DataType.UBYTE, byteval!!)
DataType.BYTE -> Value(DataType.UBYTE, byteval!!.toInt() and 255)
DataType.UWORD, DataType.WORD -> Value(DataType.UBYTE, wordval!! and 255)
else -> throw VmExecutionException("lsb can only work on (u)byte/(u)word")
}
}
fun msb(): Value {
return when(type) {
DataType.UBYTE, DataType.BYTE -> Value(DataType.UBYTE, 0)

View File

@ -426,7 +426,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
when(call) {
Syscall.FUNC_WRD, Syscall.FUNC_UWRD -> ""
Syscall.FUNC_STR2UBYTE, Syscall.FUNC_STR2UWORD -> " jsr prog8_lib.func_str2uword"
else -> " jsr prog8_lib.${call.toString().toLowerCase()}"
}
@ -671,14 +670,25 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
bne ${ins.callLabel}
"""
}
Opcode.UB2FLOAT -> " jsr prog8_lib.stack_ub2float"
Opcode.B2FLOAT -> " jsr prog8_lib.stack_b2float"
Opcode.UW2FLOAT -> " jsr prog8_lib.stack_uw2float"
Opcode.W2FLOAT -> " jsr prog8_lib.stack_w2float"
Opcode.B2UB -> "" // is a no-op, just carry on with the byte as-is
Opcode.UB2B -> "" // is a no-op, just carry on with the byte as-is
Opcode.UB2UWORD -> " lda #0 | sta ${ESTACK_HI+1},x"
Opcode.B2WORD -> " ${signExtendA("${ESTACK_HI+1},x")}"
Opcode.CAST_B_TO_UB -> "" // is a no-op, just carry on with the byte as-is
Opcode.CAST_UB_TO_B -> "" // is a no-op, just carry on with the byte as-is
Opcode.CAST_W_TO_UW -> "" // is a no-op, just carry on with the word as-is
Opcode.CAST_UW_TO_W -> "" // is a no-op, just carry on with the word as-is
Opcode.CAST_WRD_TO_UB -> "" // is a no-op, just carry on with the lsb of the (u)word as-is
Opcode.CAST_WRD_TO_B -> "" // is a no-op, just carry on with the lsb of the (u)word as-is
Opcode.CAST_UB_TO_F -> " jsr prog8_lib.stack_ub2float"
Opcode.CAST_B_TO_F -> " jsr prog8_lib.stack_b2float"
Opcode.CAST_UW_TO_F -> " jsr prog8_lib.stack_uw2float"
Opcode.CAST_W_TO_F -> " jsr prog8_lib.stack_w2float"
Opcode.CAST_UB_TO_UW -> " lda #0 | sta ${ESTACK_HI+1},x" // clear the msb
Opcode.CAST_UB_TO_W -> TODO("ub2w")
Opcode.CAST_B_TO_UW -> TODO("b2uw")
Opcode.CAST_B_TO_W -> " ${signExtendA("${ESTACK_HI+1},x")}" // sign extend the lsb @todo missing an lda???
Opcode.CAST_F_TO_UB -> TODO("f2ub")
Opcode.CAST_F_TO_B -> TODO("f2b")
Opcode.CAST_F_TO_UW -> TODO("f2uw")
Opcode.CAST_F_TO_W -> TODO("f2w")
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
Opcode.DIV_UB -> " jsr prog8_lib.div_ub"
Opcode.DIV_B -> " jsr prog8_lib.div_b"
@ -765,9 +775,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w"
Opcode.LESSEQ_F -> " jsr prog8_lib.lesseq_f"
Opcode.LSB -> ""
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
else -> null
}
}
@ -1358,7 +1365,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = ubytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment ->
when(segment[0].callLabel) {
"A" -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
"X" -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
@ -1385,7 +1392,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment ->
" lda ${hexVal(segment[0])} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
},
// var = mem (u)word
@ -1400,19 +1407,19 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = ubytearray[index_byte]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment ->
val index = hexVal(segment[0])
" lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1"
},
// var = ubytearray[index var]
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment ->
val loadA = loadAFromIndexedByVar(segment[0], segment[1])
" $loadA | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1"
},
// var = ubytearray[index mem]
AsmPattern(
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${segment[3].callLabel}
@ -1458,7 +1465,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem uword = ubyte var
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment ->
when(segment[0].callLabel) {
"A" -> " sta ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}"
"X" -> " stx ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}"
@ -1467,7 +1474,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
},
// mem uword = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${hexVal(segment[2])}
@ -1495,7 +1502,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem uword = ubytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment ->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -1505,7 +1512,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem uword = bytearray[index] (sign extended)
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment ->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -1514,7 +1521,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem uword = bytearray[index var] (sign extended)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment ->
val loadA = loadAFromIndexedByVar(segment[0], segment[1])
"""
$loadA
@ -1524,8 +1531,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// mem uword = bytearray[mem (u)byte] (sign extended)
AsmPattern(
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${hexVal(segment[3])}
@ -1533,14 +1540,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem uword = ubytearray[index var]
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment ->
val loadA = loadAFromIndexedByVar(segment[0], segment[1])
" $loadA | sta ${hexVal(segment[3])} | lda #0 | sta ${hexValPlusOne(segment[3])}"
},
// mem uword = ubytearray[mem (u)bute]
AsmPattern(
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${hexVal(segment[3])}
@ -1582,7 +1589,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// word var = bytevar (sign extended)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${segment[0].callLabel}
sta ${segment[2].callLabel}
@ -1590,7 +1597,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem word = bytevar (sign extended)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment ->
"""
lda ${segment[0].callLabel}
sta ${hexVal(segment[2])}
@ -1598,7 +1605,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// mem word = mem byte (sign extended)
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.POP_MEM_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${hexVal(segment[2])}
@ -1606,7 +1613,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = membyte (sign extended)
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${segment[2].callLabel}
@ -1614,7 +1621,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = bytearray[index_byte] (sign extended)
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment ->
val index = hexVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -1623,7 +1630,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// var = bytearray[index var] (sign extended)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment ->
val loadByteA = loadAFromIndexedByVar(segment[0], segment[1])
"""
$loadByteA
@ -1633,8 +1640,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// var = bytearray[mem (u)byte] (sign extended)
AsmPattern(
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${segment[3].callLabel}
@ -1712,7 +1719,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// uwordarray[index] = ubytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val index = intVal(segment[2])*2
when(segment[0].callLabel) {
"A" -> " sta ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index+1}"
@ -1722,7 +1729,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
},
// wordarray[index] = bytevar (extend sign)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val index = intVal(segment[2])*2
when(segment[0].callLabel) {
"A" ->
@ -1752,8 +1759,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// wordarray[index mem] = bytevar (extend sign)
AsmPattern(
listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
when(segment[0].callLabel) {
"A" ->
"""
@ -1799,8 +1806,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// wordarray[memory (u)byte] = ubyte mem
AsmPattern(
listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
"""
lda ${hexVal(segment[2])}
asl a
@ -1811,7 +1818,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// wordarray[index] = mem byte (extend sign)
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val index = intVal(segment[2])*2
"""
lda ${hexVal(segment[0])}
@ -1820,7 +1827,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// wordarray2[index2] = bytearray1[index1] (extend sign)
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index1 = intVal(segment[0])
val index2 = segment[3].arg!!.integerValue()*2
"""
@ -1831,8 +1838,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// wordarray2[mem (u)byte] = bytearray1[index1] (extend sign)
AsmPattern(
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index1 = intVal(segment[0])
"""
lda ${hexVal(segment[3])}
@ -1845,7 +1852,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// wordarray[indexvar] = byte var (sign extended)
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val loadValueOnStack = when(segment[0].callLabel) {
"A" -> " pha"
"X" -> " txa | pha"
@ -1867,7 +1874,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// wordarray[indexvar] = byte mem (sign extended)
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val loadIndexY = when(segment[2].callLabel) {
"A" -> " asl a | tay"
"X" -> " txa | asl a | tay"
@ -1892,7 +1899,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// wordarray2[indexvar] = bytearay[index] (sign extended)
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index = intVal(segment[0])
val loadIndex2Y = when(segment[3].callLabel) {
"A" -> " asl a | tay"
@ -1925,8 +1932,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// uwordarray[index mem] = ubytevar
AsmPattern(
listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
when(segment[0].callLabel) {
"A" ->
"""
@ -1975,8 +1982,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// uwordarray[index mem] = ubyte mem
AsmPattern(
listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
"""
lda ${hexVal(segment[2])}
asl a
@ -1988,7 +1995,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// uwordarray[index] = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val index = intVal(segment[2])*2
"""
lda ${hexVal(segment[0])}
@ -2018,7 +2025,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// uwordarray2[index2] = ubytearray1[index1]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index1 = intVal(segment[0])
val index2 = segment[3].arg!!.integerValue()*2
"""
@ -2051,7 +2058,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
" $loadIndexY | lda #<$value | sta ${segment[2].callLabel},y | lda #>$value | sta ${segment[2].callLabel}+1,y"
},
// uwordarray[indexvar] = ubyte var
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val loadValueOnStack = when(segment[0].callLabel) {
"A" -> " pha"
"X" -> " txa | pha"
@ -2087,7 +2094,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
" $loadIndexY | lda #<${segment[0].callLabel} | sta ${segment[2].callLabel},y | lda #>${segment[0].callLabel} | sta ${segment[2].callLabel}+1,y"
},
// uwordarray[indexvar] = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val loadIndexY = when(segment[2].callLabel) {
"A" -> " asl a | tay"
"X" -> " txa | asl a | tay"
@ -2109,7 +2116,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
" $loadIndexY | lda ${hexVal(segment[0])} | sta ${segment[2].callLabel},y | lda ${hexValPlusOne(segment[0])} | sta ${segment[2].callLabel}+1,y"
},
// uwordarray2[indexvar] = ubytearay[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index = intVal(segment[0])
val loadIndex2Y = when(segment[3].callLabel) {
"A" -> " asl a | tay"
@ -2132,8 +2139,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// uwordarray2[index mem] = ubytearray1[index1]
AsmPattern(
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD),
listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
val index1 = intVal(segment[0])
"""
lda ${hexVal(segment[3])}
@ -2164,7 +2171,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// ----------- assignment to FLOAT VARIABLE ----------------
// floatvar = ubytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val loadByteA = when(segment[0].callLabel) {
"A" -> ""
"X" -> "txa"
@ -2180,7 +2187,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = uwordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
@ -2192,7 +2199,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = bytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val loadByteA = when(segment[0].callLabel) {
"A" -> ""
"X" -> "txa"
@ -2208,7 +2215,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = wordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
@ -2257,7 +2264,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = mem byte
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_B1}
@ -2267,7 +2274,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_B1}
@ -2277,7 +2284,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = mem word
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.W2FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_W1}
@ -2289,7 +2296,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = mem uword
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.UW2FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_W1}
@ -2302,7 +2309,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// floatvar = bytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -2313,7 +2320,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = ubytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -2324,7 +2331,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = wordarray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val index = intVal(segment[0])*2
"""
lda ${segment[1].callLabel}+$index
@ -2337,7 +2344,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// floatvar = uwordarray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_VAR_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment->
val index = intVal(segment[0])*2
"""
lda ${segment[1].callLabel}+$index
@ -2389,7 +2396,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = ubytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val loadByteA = when(segment[0].callLabel) {
"A" -> ""
"X" -> "txa"
@ -2405,7 +2412,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = uwordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
@ -2417,7 +2424,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = bytevar
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val loadByteA = when(segment[0].callLabel) {
"A" -> ""
"X" -> "txa"
@ -2433,7 +2440,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = wordvar
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment ->
"""
lda ${segment[0].callLabel}
sta ${C64Zeropage.SCRATCH_W1}
@ -2445,7 +2452,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = mem byte
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_B1}
@ -2455,7 +2462,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = mem ubyte
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_B1}
@ -2465,7 +2472,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = mem word
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.W2FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_W1}
@ -2477,7 +2484,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = mem uword
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.UW2FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment ->
"""
lda ${hexVal(segment[0])}
sta ${C64Zeropage.SCRATCH_W1}
@ -2501,7 +2508,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = bytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -2512,7 +2519,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = ubytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val index = intVal(segment[0])
"""
lda ${segment[1].callLabel}+$index
@ -2523,7 +2530,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = wordarray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.W2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val index = intVal(segment[0])*2
"""
lda ${segment[1].callLabel}+$index
@ -2536,7 +2543,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// memfloat = uwordarray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.UW2FLOAT, Opcode.POP_MEM_FLOAT)) { segment->
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment->
val index = intVal(segment[0])*2
"""
lda ${segment[1].callLabel}+$index
@ -2707,8 +2714,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
},
// byte var = lsb(word var)
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.LSB, Opcode.POP_VAR_BYTE)) { segment ->
// byte var = wordvar as (u)byte
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_WRD_TO_UB, Opcode.POP_VAR_BYTE),
listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_WRD_TO_B, Opcode.POP_VAR_BYTE)) { segment ->
when(segment[2].callLabel) {
"A" -> " lda ${segment[0].callLabel}"
"X" -> " ldx ${segment[0].callLabel}"
@ -2725,8 +2733,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
else -> " lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}"
}
},
// push lsb(word var)
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.LSB)) { segment ->
// push word var as (u)byte
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_WRD_TO_UB),
listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_WRD_TO_B)) { segment ->
" lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex "
},
// push msb(word var)

View File

@ -1,7 +1,6 @@
package prog8.functions
import prog8.ast.*
import prog8.compiler.CompilerException
import prog8.compiler.HeapValues
import kotlin.math.log2
@ -46,13 +45,6 @@ val BuiltinFunctions = mapOf(
"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),
"fintb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.BYTE, ::builtinFintb),
"fintw" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD, ::builtinFintw),
"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),
@ -62,6 +54,7 @@ val BuiltinFunctions = mapOf(
"clear_carry" to FunctionSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null),
// @todo change the string conversion functions into "string as byte" type casts?
"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),
@ -237,96 +230,6 @@ private fun collectionArgOutputBoolean(args: List<IExpression>, position: Positi
return LiteralValue.fromBoolean(result, position)
}
private fun builtinFlt(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 numeric arg, convert to float
if(args.size!=1)
throw SyntaxError("flt requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val number = constval.asNumericValue ?: throw SyntaxError("flt requires one numeric argument", position)
return LiteralValue(DataType.FLOAT, floatvalue = number.toDouble(), position = position)
}
private fun builtinFintb(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 float arg, convert to byte
if(args.size!=1)
throw SyntaxError("fintb requires one floating point argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.FLOAT)
throw SyntaxError("fintb requires one floating point argument", position)
val integer: Short
val flt = constval.floatvalue!!
integer = when {
flt <= -128 -> -128
flt >= 127 -> 127
else -> flt.toShort()
}
return LiteralValue(DataType.BYTE, bytevalue = integer, position = position)
}
private fun builtinFintw(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 float arg, convert to word
if(args.size!=1)
throw SyntaxError("fintw requires one floating point argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.FLOAT)
throw SyntaxError("fintw requires one floating point argument", position)
val integer: Int
val flt = constval.floatvalue!!
integer = when {
flt <= -32768 -> -32768
flt >= 32767 -> 32767
else -> flt.toInt()
}
return LiteralValue(DataType.WORD, wordvalue = integer, position = position)
}
private fun builtinWrd(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 byte arg, convert to word
if(args.size!=1)
throw SyntaxError("wrd requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE && constval.type!=DataType.BYTE && constval.type!=DataType.UWORD)
throw SyntaxError("wrd requires one argument of type ubyte, byte or uword", position)
return LiteralValue(DataType.WORD, wordvalue = constval.asIntegerValue, position = position)
}
private fun builtinUwrd(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 arg, convert to uword
if(args.size!=1)
throw SyntaxError("uwrd requires one numeric argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE && constval.type!=DataType.WORD && constval.type!=DataType.UWORD)
throw SyntaxError("uwrd requires one argument of type byte, word or uword", position)
return LiteralValue(DataType.UWORD, wordvalue = constval.asIntegerValue!! and 65535, position = position)
}
private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 byte arg, convert to ubyte
if(args.size!=1)
throw SyntaxError("b2ub requires one byte argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE && constval.type!=DataType.UBYTE)
throw SyntaxError("b2ub requires one argument of type byte or ubyte", 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 {
// 1 ubyte arg, convert to byte
if(args.size!=1)
throw SyntaxError("ub2b requires one ubyte argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE)
throw SyntaxError("ub2b requires one argument of type ubyte", position)
return LiteralValue(DataType.BYTE, bytevalue=(constval.bytevalue!!.toInt() and 255).toShort(), position = position)
}
private fun builtinAbs(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
// 1 arg, type = float or int, result type= same as argument type
if(args.size!=1)

View File

@ -1,8 +1,6 @@
package prog8.stackvm
import prog8.ast.DataType
import prog8.ast.IterableDatatypes
import prog8.ast.NumericDatatypes
import prog8.ast.*
import prog8.compiler.HeapValues
import prog8.compiler.intermediate.Instruction
import prog8.compiler.intermediate.Opcode
@ -39,13 +37,9 @@ enum class Syscall(val callNr: Short) {
FUNC_ROUND(79),
FUNC_FLOOR(80),
FUNC_CEIL(81),
FUNC_FINTB(82),
FUNC_FINTW(83),
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_WRD(92),
FUNC_UWRD(93),
FUNC_STR2BYTE(100),
FUNC_STR2UBYTE(101),
FUNC_STR2WORD(102),
@ -955,11 +949,6 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(variable, DataType.FLOAT)
variables[ins.callLabel] =variable.dec()
}
Opcode.LSB -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD)
evalstack.push(v.lsb())
}
Opcode.MSB -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD)
@ -1167,49 +1156,6 @@ 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)
evalstack.push(Value(DataType.WORD, byte.integerValue()))
}
Opcode.UB2UWORD -> {
val ubyte = evalstack.pop()
checkDt(ubyte, DataType.UBYTE)
evalstack.push(Value(DataType.UWORD, ubyte.integerValue()))
}
Opcode.B2FLOAT -> {
val byte = evalstack.pop()
checkDt(byte, DataType.BYTE)
evalstack.push(Value(DataType.FLOAT, byte.integerValue()))
}
Opcode.UB2FLOAT -> {
val byte = evalstack.pop()
checkDt(byte, DataType.UBYTE)
evalstack.push(Value(DataType.FLOAT, byte.integerValue()))
}
Opcode.W2FLOAT -> {
val wrd = evalstack.pop()
checkDt(wrd, DataType.UWORD)
evalstack.push(Value(DataType.FLOAT, wrd.integerValue()))
}
Opcode.UW2FLOAT -> {
val uwrd = evalstack.pop()
checkDt(uwrd, DataType.UWORD)
evalstack.push(Value(DataType.FLOAT, uwrd.integerValue()))
}
Opcode.READ_INDEXED_VAR_BYTE -> {
// put the byte value of variable[index] onto the stack
val index = evalstack.pop().integerValue()
@ -1399,6 +1345,11 @@ class StackVm(private var traceOutputFile: String?) {
throw VmExecutionException("expected string to be on heap")
evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string
}
Opcode.CAST_UB_TO_B, Opcode.CAST_WRD_TO_B, Opcode.CAST_F_TO_B -> typecast(DataType.BYTE)
Opcode.CAST_B_TO_UB, Opcode.CAST_WRD_TO_UB, Opcode.CAST_F_TO_UB -> typecast(DataType.UBYTE)
Opcode.CAST_UB_TO_UW, Opcode.CAST_B_TO_UW, Opcode.CAST_W_TO_UW, Opcode.CAST_F_TO_UW -> typecast(DataType.UWORD)
Opcode.CAST_UB_TO_W, Opcode.CAST_B_TO_W, Opcode.CAST_UW_TO_W, Opcode.CAST_F_TO_W -> typecast(DataType.WORD)
Opcode.CAST_UB_TO_F, Opcode.CAST_B_TO_F, Opcode.CAST_UW_TO_F, Opcode.CAST_W_TO_F -> typecast(DataType.FLOAT)
//else -> throw VmExecutionException("unimplemented opcode: ${ins.opcode}")
}
@ -1411,6 +1362,13 @@ class StackVm(private var traceOutputFile: String?) {
return ins.next
}
private fun typecast(type: DataType) {
val value = evalstack.pop()
val lv = LiteralValue.optimalNumeric(value.numericValue(), Position("?", 0, 0, 0))
val lv2 = TypecastExpression.typecast(lv, type) ?: throw VmExecutionException("type cast error")
evalstack.push(Value(lv2.type, lv2.asNumericValue!!))
}
private fun dispatchSyscall(ins: Instruction) {
val callId = ins.arg!!.integerValue().toShort()
val syscall = Syscall.values().first { it.callNr == callId }
@ -1627,69 +1585,7 @@ class StackVm(private var traceOutputFile: String?) {
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.FLOAT, y.toDouble()))
}
Syscall.FUNC_FINTB -> {
val value = evalstack.pop()
if(value.type in NumericDatatypes) {
val integer: Short
val flt = value.numericValue().toDouble()
integer = when {
flt <= -128 -> -128
flt >= 127 -> 127
else -> flt.toShort()
}
evalstack.push(Value(DataType.BYTE, integer))
}
else throw VmExecutionException("cannot fintb $value")
}
Syscall.FUNC_FINTW -> {
val value = evalstack.pop()
if(value.type in NumericDatatypes) {
val integer: Int
val flt = value.numericValue().toDouble()
integer = when {
flt <= -32768 -> -32768
flt >= 32767 -> 32767
else -> flt.toInt()
}
evalstack.push(Value(DataType.WORD, integer))
}
else throw VmExecutionException("cannot fintw $value")
}
Syscall.FUNC_WRD -> {
val value = evalstack.pop()
checkDt(value, 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, 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 -> {}
}
}
}
}
}
fun irq(timestamp: Long) {

View File

@ -421,22 +421,6 @@ class TestStackVmOpcodes {
}
}
@Test
fun testLsb() {
val ins = mutableListOf(
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 0x45)),
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0xea31)),
Instruction(Opcode.LSB),
Instruction(Opcode.LSB)
)
vm.load(makeProg(ins), null)
vm.step(3)
assertEquals(Value(DataType.UBYTE, 0x31), vm.evalstack.pop())
assertFailsWith<VmExecutionException> {
vm.step(1)
}
}
@Test
fun testMsb() {
val ins = mutableListOf(
@ -453,13 +437,15 @@ class TestStackVmOpcodes {
}
}
// @todo more conversion tests.
@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)
Instruction(Opcode.CAST_B_TO_UB),
Instruction(Opcode.CAST_B_TO_UB)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -473,8 +459,8 @@ class TestStackVmOpcodes {
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)
Instruction(Opcode.CAST_UB_TO_B),
Instruction(Opcode.CAST_UB_TO_B)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -488,8 +474,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_WORD, Value(DataType.WORD, 0x7a31)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.BYTE, 127)),
Instruction(Opcode.B2WORD),
Instruction(Opcode.B2WORD)
Instruction(Opcode.CAST_B_TO_W),
Instruction(Opcode.CAST_B_TO_W)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -504,8 +490,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0xea31)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 0x45)),
Instruction(Opcode.UB2UWORD),
Instruction(Opcode.UB2UWORD)
Instruction(Opcode.CAST_UB_TO_UW),
Instruction(Opcode.CAST_UB_TO_UW)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -520,8 +506,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_WORD, Value(DataType.WORD, 0x7a31)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.BYTE, 127)),
Instruction(Opcode.B2FLOAT),
Instruction(Opcode.B2FLOAT)
Instruction(Opcode.CAST_B_TO_F),
Instruction(Opcode.CAST_B_TO_F)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -536,8 +522,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0xea31)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 177)),
Instruction(Opcode.UB2FLOAT),
Instruction(Opcode.UB2FLOAT)
Instruction(Opcode.CAST_UB_TO_F),
Instruction(Opcode.CAST_UB_TO_F)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -552,8 +538,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 177)),
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 52345)),
Instruction(Opcode.W2FLOAT),
Instruction(Opcode.W2FLOAT)
Instruction(Opcode.CAST_W_TO_F),
Instruction(Opcode.CAST_W_TO_F)
)
vm.load(makeProg(ins), null)
vm.step(3)
@ -568,8 +554,8 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 177)),
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 52345)),
Instruction(Opcode.UW2FLOAT),
Instruction(Opcode.UW2FLOAT)
Instruction(Opcode.CAST_UW_TO_F),
Instruction(Opcode.CAST_UW_TO_F)
)
vm.load(makeProg(ins), null)
vm.step(3)

View File

@ -435,8 +435,9 @@ You can also reference idendifiers defined elsewhere in your code.
Calculations with integers will not result in floating point values;
if you divide two integer values (say: ``32500 / 99``) the result will be the integer floor
division (328) rather than the floating point result (328.2828282828283). If you need the full precision,
you'll have to write ``flt(32500) / 99`` (or if they're constants, simply ``32500.0 / 99``), to make sure the
first operand is a floating point value.
you'll have to make sure at least the first operand is a floating point. So write ``32500.0 / 99.0``,
or use the type cast ``value as float``.
Arithmetic and Logical expressions
@ -542,35 +543,11 @@ len(x)
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte.
lsb(x)
Get the least significant byte of the word x.
Get the least significant byte of the word x. Equivalent to the cast "x as ubyte".
msb(x)
Get the most significant byte of the word x.
flt(x)
Explicitly convert the number x to a floating point number.
This is required if you want calculations to have floating point precision when the values aren't float already.
fintb(x)
Take floor of the floating point into a byte value. (no overflow check). Use together with b2ub() to convert into a unsigned byte instead.
fintw(x)
Take floor of the floating point into a word value. (no overflow check).
wrd(x)
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.
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 array value x is 'true' (not zero), else 0 ('false')