mirror of
https://github.com/irmen/prog8.git
synced 2025-02-09 07:31:34 +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
|
package prog8tests.vm
|
||||||
|
|
||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
import io.kotest.matchers.shouldNotBe
|
import io.kotest.matchers.shouldNotBe
|
||||||
import prog8.code.target.Cx16Target
|
import prog8.code.target.Cx16Target
|
||||||
import prog8.code.target.VMTarget
|
import prog8.code.target.VMTarget
|
||||||
@ -32,11 +33,15 @@ main {
|
|||||||
test("compile virtual: array with pointers") {
|
test("compile virtual: array with pointers") {
|
||||||
val src = """
|
val src = """
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte variable
|
str localstr = "hello"
|
||||||
uword[] words = [1111,2222,"three",&variable]
|
ubyte[] otherarray = [1,2,3]
|
||||||
variable = 2222 in words
|
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()
|
val othertarget = Cx16Target()
|
||||||
@ -105,4 +110,31 @@ mylabel_inside:
|
|||||||
VmRunner().runProgram(virtfile.readText())
|
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
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- fix vm symbol case insensitivity (TestCompilerVirtual)
|
||||||
- fix vm crash in TestCompilerVirtual: array with pointers
|
- 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(",") {
|
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||||
if(it.number!=null)
|
if(it.number!=null)
|
||||||
it.number!!.toInt().toString()
|
it.number!!.toInt().toString()
|
||||||
else
|
else {
|
||||||
"&${it.addressOf!!.joinToString(".")}"
|
val target = variable.lookup(it.addressOf!!)
|
||||||
|
?: throw InternalCompilerException("symbol not found: ${it.addressOf} in ${variable.scopedName}")
|
||||||
|
"&${target.scopedName.joinToString(".")}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(1..variable.length!!).joinToString(",") { "0" }
|
(1..variable.length!!).joinToString(",") { "0" }
|
||||||
|
@ -17,6 +17,8 @@ class Assembler {
|
|||||||
|
|
||||||
fun initializeMemory(memsrc: String, memory: Memory) {
|
fun initializeMemory(memsrc: String, memory: Memory) {
|
||||||
symbolAddresses.clear()
|
symbolAddresses.clear()
|
||||||
|
val arrayValuePlaceholders = mutableListOf<Pair<Int, String>>()
|
||||||
|
|
||||||
val instrPattern = Regex("""var (.+) @([0-9]+) ([a-z]+)(\[[0-9]+\])? (.+)""", RegexOption.IGNORE_CASE)
|
val instrPattern = Regex("""var (.+) @([0-9]+) ([a-z]+)(\[[0-9]+\])? (.+)""", RegexOption.IGNORE_CASE)
|
||||||
for(line in memsrc.lines()) {
|
for(line in memsrc.lines()) {
|
||||||
if(line.isBlank() || line.startsWith(';'))
|
if(line.isBlank() || line.startsWith(';'))
|
||||||
@ -58,18 +60,33 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"uword", "word" -> {
|
"uword", "word" -> {
|
||||||
val array = values.split(',').map { parseValue(Opcode.LOADCPU, it.trim(), 0).toInt() }
|
if(arrayspec.isBlank()) {
|
||||||
require(array.size==numArrayElts || array.size==1)
|
// single value
|
||||||
if(numArrayElts>array.size) {
|
val value = parseValue(Opcode.LOADCPU, values.trim(), 0).toInt()
|
||||||
val value = array.single().toUShort()
|
memory.setUW(address, value.toUShort())
|
||||||
repeat(numArrayElts) {
|
address += 2
|
||||||
memory.setUW(address, value)
|
|
||||||
address += 2
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (value in array) {
|
// array initializer
|
||||||
memory.setUW(address, value.toUShort())
|
val array = values.split(',').withIndex().map {(index, value) ->
|
||||||
address += 2
|
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> {
|
fun assembleProgram(source: CharSequence): List<Instruction> {
|
||||||
|
@ -2106,6 +2106,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>, val cx16vir
|
|||||||
// probably called via reflection
|
// probably called via reflection
|
||||||
class VmRunner: IVirtualMachineRunner {
|
class VmRunner: IVirtualMachineRunner {
|
||||||
override fun runProgram(source: String) {
|
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 (memsrc, programsrc) = source.split("------PROGRAM------".toRegex(), 2)
|
||||||
val memory = Memory()
|
val memory = Memory()
|
||||||
val assembler = Assembler()
|
val assembler = Assembler()
|
||||||
@ -2113,5 +2117,6 @@ class VmRunner: IVirtualMachineRunner {
|
|||||||
val program = assembler.assembleProgram(programsrc)
|
val program = assembler.assembleProgram(programsrc)
|
||||||
val vm = VirtualMachine(memory, program, assembler.cx16virtualregBaseAdress)
|
val vm = VirtualMachine(memory, program, assembler.cx16virtualregBaseAdress)
|
||||||
vm.run()
|
vm.run()
|
||||||
|
test(vm)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user