mirror of
https://github.com/irmen/prog8.git
synced 2024-12-01 15:52:54 +00:00
when working correctly in stackvm and astvm
This commit is contained in:
parent
9e6408244f
commit
9d0c65c682
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user