when working correctly in stackvm and astvm

This commit is contained in:
Irmen de Jong 2019-07-09 20:39:08 +02:00
parent 9e6408244f
commit 9d0c65c682
4 changed files with 51 additions and 34 deletions

View File

@ -926,14 +926,17 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(whenChoice: WhenChoice) { override fun visit(whenChoice: WhenChoice) {
val whenStmt = whenChoice.parent as WhenStatement
if(whenChoice.value!=null) { if(whenChoice.value!=null) {
val conditionType = whenStmt.condition.inferType(program)
val constvalue = whenChoice.value.constValue(program) val constvalue = whenChoice.value.constValue(program)
if (constvalue == null) when {
checkResult.add(SyntaxError("value of a when choice must be a constant", whenChoice.position)) constvalue == null -> checkResult.add(SyntaxError("choice value must be a constant", whenChoice.position))
else if (constvalue.type !in IntegerDatatypes) constvalue.type !in IntegerDatatypes -> checkResult.add(SyntaxError("choice value must be a byte or word", whenChoice.position))
checkResult.add(SyntaxError("value of a when choice must be a byte or word", whenChoice.position)) constvalue.type != conditionType -> checkResult.add(SyntaxError("choice value datatype differs from condition value", whenChoice.position))
}
} else { } else {
if(whenChoice !== (whenChoice.parent as WhenStatement).choices.last()) if(whenChoice !== whenStmt.choices.last())
checkResult.add(SyntaxError("else choice must be the last one", whenChoice.position)) checkResult.add(SyntaxError("else choice must be the last one", whenChoice.position))
} }
super.visit(whenChoice) super.visit(whenChoice)

View File

@ -2095,22 +2095,20 @@ internal class Compiler(private val program: Program) {
val endOfWhenLabel = makeLabel(whenstmt, "when_end") val endOfWhenLabel = makeLabel(whenstmt, "when_end")
val choiceLabels = mutableListOf<String>() val choiceLabels = mutableListOf<String>()
var previousValue = 0
for(choice in whenstmt.choiceValues(program)) { for(choice in whenstmt.choiceValues(program)) {
val choiceVal = choice.first val choiceVal = choice.first
if(choiceVal==null) { if(choiceVal==null) {
// the else clause // the else clause
translate(choice.second.statements) translate(choice.second.statements)
} else { } else {
val subtract = choiceVal-previousValue val rval = RuntimeValue(conditionDt!!, choiceVal)
previousValue = choiceVal
if (conditionDt in ByteDatatypes) { if (conditionDt in ByteDatatypes) {
prog.instr(Opcode.DUP_B) prog.instr(Opcode.DUP_B)
prog.instr(opcodeCompare(conditionDt!!), RuntimeValue(conditionDt, subtract)) prog.instr(opcodeCompare(conditionDt), rval)
} }
else { else {
prog.instr(Opcode.DUP_W) prog.instr(Opcode.DUP_W)
prog.instr(opcodeCompare(conditionDt!!), RuntimeValue(conditionDt, subtract)) prog.instr(opcodeCompare(conditionDt), rval)
} }
val choiceLabel = makeLabel(whenstmt, "choice_$choiceVal") val choiceLabel = makeLabel(whenstmt, "choice_$choiceVal")
choiceLabels.add(choiceLabel) choiceLabels.add(choiceLabel)
@ -2120,12 +2118,12 @@ internal class Compiler(private val program: Program) {
prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel) prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel)
for(choice in whenstmt.choices.zip(choiceLabels)) { for(choice in whenstmt.choices.zip(choiceLabels)) {
// TODO the various code blocks here, don't forget to jump to the end label at their eind
prog.label(choice.second) prog.label(choice.second)
prog.instr(Opcode.NOP) translate(choice.first.statements)
prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel) prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel)
} }
prog.removeLastInstruction() // remove the last jump, that can fall through to here
prog.label(endOfWhenLabel) prog.label(endOfWhenLabel)
if (conditionDt in ByteDatatypes) prog.instr(Opcode.DISCARD_BYTE) if (conditionDt in ByteDatatypes) prog.instr(Opcode.DISCARD_BYTE)

View File

@ -53,27 +53,37 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
init { init {
when(type) { when(type) {
DataType.UBYTE -> { DataType.UBYTE -> {
byteval = (num!!.toInt() and 255).toShort() val inum = num!!.toInt()
if(inum !in 0 .. 255)
throw IllegalArgumentException("invalid value for ubyte: $inum")
byteval = inum.toShort()
wordval = null wordval = null
floatval = null floatval = null
asBoolean = byteval != 0.toShort() asBoolean = byteval != 0.toShort()
} }
DataType.BYTE -> { DataType.BYTE -> {
val v = num!!.toInt() and 255 val inum = num!!.toInt()
byteval = (if(v<128) v else v-256).toShort() if(inum !in -128 .. 127)
throw IllegalArgumentException("invalid value for byte: $inum")
byteval = inum.toShort()
wordval = null wordval = null
floatval = null floatval = null
asBoolean = byteval != 0.toShort() asBoolean = byteval != 0.toShort()
} }
DataType.UWORD -> { DataType.UWORD -> {
wordval = num!!.toInt() and 65535 val inum = num!!.toInt()
if(inum !in 0 .. 65536)
throw IllegalArgumentException("invalid value for uword: $inum")
wordval = inum
byteval = null byteval = null
floatval = null floatval = null
asBoolean = wordval != 0 asBoolean = wordval != 0
} }
DataType.WORD -> { DataType.WORD -> {
val v = num!!.toInt() and 65535 val inum = num!!.toInt()
wordval = if(v<32768) v else v - 65536 if(inum !in -32768 .. 32767)
throw IllegalArgumentException("invalid value for word: $inum")
wordval = inum
byteval = null byteval = null
floatval = null floatval = null
asBoolean = wordval != 0 asBoolean = wordval != 0

View File

@ -4,31 +4,43 @@
~ main { ~ main {
sub start() { sub start() {
A=100 ubyte aa = 100
Y=22 ubyte yy = 22
uword uw = (A as uword)*Y uword uw = (aa as uword)*yy
c64scr.print("stack (255?): ") c64scr.print("stack (255?): ")
c64scr.print_ub(X) c64scr.print_ub(X)
c64.CHROUT('\n') c64.CHROUT('\n')
aa=30
yy=2
c64scr.print_ub(aa+yy)
c64scr.print("?: ")
check(aa, yy)
aa+=9
c64scr.print_ub(aa+yy)
c64scr.print("?: ")
check(aa, yy)
c64scr.print_uw(uw) c64scr.print_uw(uw)
c64scr.print("?: ") c64scr.print("?: ")
when uw { when uw {
12345 -> c64scr.print("12345") 12345 -> c64scr.print("12345")
12346 -> c64scr.print("12346") 12346 -> c64scr.print("12346")
2200 -> c64scr.print("2200") 2200 -> c64scr.print("2200")
2202 -> c64scr.print("2202")
12347 -> c64scr.print("12347") 12347 -> c64scr.print("12347")
else -> c64scr.print("else") else -> c64scr.print("not in table")
} }
c64.CHROUT('\n') c64.CHROUT('\n')
A=30 c64scr.print("stack (255?): ")
Y=2 c64scr.print_ub(X)
}
c64scr.print_ub(A+Y) sub check(ubyte a, ubyte y) {
c64scr.print("?: ") when a+y {
when A+Y {
10 -> { 10 -> {
c64scr.print("ten") c64scr.print("ten")
} }
@ -44,16 +56,10 @@
56 -> { 56 -> {
; should be optimized away ; should be optimized away
} }
57243 -> {
; should be optimized away
}
else -> { else -> {
c64scr.print("!??!\n") c64scr.print("not in table")
} }
} }
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print("stack (255?): ")
c64scr.print_ub(X)
} }
} }