mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
vm: fix scoped name in address-of inside array
This commit is contained in:
parent
0e1886e6bd
commit
ca41669f4f
@ -1,6 +1,7 @@
|
||||
package prog8tests.vm
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.code.target.VMTarget
|
||||
@ -32,11 +33,15 @@ main {
|
||||
test("compile virtual: array with pointers") {
|
||||
val src = """
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
ubyte variable
|
||||
uword[] words = [1111,2222,"three",&variable]
|
||||
variable = 2222 in words
|
||||
str localstr = "hello"
|
||||
ubyte[] otherarray = [1,2,3]
|
||||
uword[] words = [1111,2222,"three",&localstr,&otherarray]
|
||||
uword @shared zz = &words
|
||||
ubyte result = 2222 in words
|
||||
zz = words[2]
|
||||
zz++
|
||||
zz = words[3]
|
||||
}
|
||||
}"""
|
||||
val othertarget = Cx16Target()
|
||||
@ -105,4 +110,31 @@ mylabel_inside:
|
||||
VmRunner().runProgram(virtfile.readText())
|
||||
}
|
||||
|
||||
test("case sensitive symbols") {
|
||||
val src = """
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte bytevar = 11 ; var at 0
|
||||
ubyte byteVAR = 22 ; var at 1
|
||||
ubyte ByteVar = 33 ; var at 2
|
||||
ubyte @shared total = bytevar+byteVAR+ByteVar ; var at 3
|
||||
goto skipLABEL
|
||||
SkipLabel:
|
||||
return
|
||||
skipLABEL:
|
||||
bytevar = 42
|
||||
}
|
||||
}"""
|
||||
val othertarget = Cx16Target()
|
||||
compileText(othertarget, true, src, writeAssembly = true, keepIR=true) shouldNotBe null
|
||||
val target = VMTarget()
|
||||
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
|
||||
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
|
||||
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
|
||||
vm.memory.getUB(0) shouldBe 42u
|
||||
vm.memory.getUB(3) shouldBe 66u
|
||||
}
|
||||
}
|
||||
})
|
@ -3,8 +3,9 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- fix vm symbol case insensitivity (TestCompilerVirtual)
|
||||
- fix vm crash in TestCompilerVirtual: array with pointers
|
||||
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler)
|
||||
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler, caused by above?)
|
||||
|
||||
...
|
||||
|
||||
|
@ -121,8 +121,11 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
it.number!!.toInt().toString()
|
||||
else
|
||||
"&${it.addressOf!!.joinToString(".")}"
|
||||
else {
|
||||
val target = variable.lookup(it.addressOf!!)
|
||||
?: throw InternalCompilerException("symbol not found: ${it.addressOf} in ${variable.scopedName}")
|
||||
"&${target.scopedName.joinToString(".")}"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(1..variable.length!!).joinToString(",") { "0" }
|
||||
|
@ -17,6 +17,8 @@ class Assembler {
|
||||
|
||||
fun initializeMemory(memsrc: String, memory: Memory) {
|
||||
symbolAddresses.clear()
|
||||
val arrayValuePlaceholders = mutableListOf<Pair<Int, String>>()
|
||||
|
||||
val instrPattern = Regex("""var (.+) @([0-9]+) ([a-z]+)(\[[0-9]+\])? (.+)""", RegexOption.IGNORE_CASE)
|
||||
for(line in memsrc.lines()) {
|
||||
if(line.isBlank() || line.startsWith(';'))
|
||||
@ -58,18 +60,33 @@ class Assembler {
|
||||
}
|
||||
}
|
||||
"uword", "word" -> {
|
||||
val array = values.split(',').map { parseValue(Opcode.LOADCPU, it.trim(), 0).toInt() }
|
||||
require(array.size==numArrayElts || array.size==1)
|
||||
if(numArrayElts>array.size) {
|
||||
val value = array.single().toUShort()
|
||||
repeat(numArrayElts) {
|
||||
memory.setUW(address, value)
|
||||
address += 2
|
||||
}
|
||||
if(arrayspec.isBlank()) {
|
||||
// single value
|
||||
val value = parseValue(Opcode.LOADCPU, values.trim(), 0).toInt()
|
||||
memory.setUW(address, value.toUShort())
|
||||
address += 2
|
||||
} else {
|
||||
for (value in array) {
|
||||
memory.setUW(address, value.toUShort())
|
||||
address += 2
|
||||
// array initializer
|
||||
val array = values.split(',').withIndex().map {(index, value) ->
|
||||
val tv = value.trim()
|
||||
if(tv.startsWith('&')) {
|
||||
arrayValuePlaceholders += Pair(address+index*2, tv.drop(1))
|
||||
9999 // will be replaced with correct value at the end.
|
||||
} else
|
||||
parseValue(Opcode.LOADCPU, tv, 0).toInt()
|
||||
}
|
||||
require(array.size==numArrayElts || array.size==1)
|
||||
if(numArrayElts>array.size) {
|
||||
val value = array.single().toUShort()
|
||||
repeat(numArrayElts) {
|
||||
memory.setUW(address, value)
|
||||
address += 2
|
||||
}
|
||||
} else {
|
||||
for (value in array) {
|
||||
memory.setUW(address, value.toUShort())
|
||||
address += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,6 +110,12 @@ class Assembler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// correct the addres-of values in array initializers
|
||||
arrayValuePlaceholders.forEach { (address, symbol) ->
|
||||
val addr = this.symbolAddresses.getValue(symbol)
|
||||
memory.setUW(address, addr.toUShort())
|
||||
}
|
||||
}
|
||||
|
||||
fun assembleProgram(source: CharSequence): List<Instruction> {
|
||||
|
@ -2106,6 +2106,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
|
||||
// probably called via reflection
|
||||
class VmRunner: IVirtualMachineRunner {
|
||||
override fun runProgram(source: String) {
|
||||
runAndTestProgram(source) { /* no tests */ }
|
||||
}
|
||||
|
||||
fun runAndTestProgram(source: String, test: (VirtualMachine) -> Unit) {
|
||||
val (memsrc, programsrc) = source.split("------PROGRAM------".toRegex(), 2)
|
||||
val memory = Memory()
|
||||
val assembler = Assembler()
|
||||
@ -2113,5 +2117,6 @@ class VmRunner: IVirtualMachineRunner {
|
||||
val program = assembler.assembleProgram(programsrc)
|
||||
val vm = VirtualMachine(memory, program, assembler.cx16virtualregBaseAdress)
|
||||
vm.run()
|
||||
test(vm)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user