mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
p8ir file format is now valid XML
This commit is contained in:
parent
136a9a39de
commit
9d7b9771c2
@ -53,5 +53,5 @@ class VirtualMachineDefinition: IMachineDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IVirtualMachineRunner {
|
interface IVirtualMachineRunner {
|
||||||
fun runProgram(irSource: CharSequence)
|
fun runProgram(irSource: String)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ class TestLaunchEmu: FunSpec({
|
|||||||
test("test launch virtualmachine via target") {
|
test("test launch virtualmachine via target") {
|
||||||
val target = VMTarget()
|
val target = VMTarget()
|
||||||
val tmpfile = kotlin.io.path.createTempFile(suffix=".p8ir")
|
val tmpfile = kotlin.io.path.createTempFile(suffix=".p8ir")
|
||||||
tmpfile.writeText("""<PROGRAM NAME=test>
|
tmpfile.writeText("""<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PROGRAM NAME="test">
|
||||||
<OPTIONS>
|
<OPTIONS>
|
||||||
</OPTIONS>
|
</OPTIONS>
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ class TestLaunchEmu: FunSpec({
|
|||||||
<INITGLOBALS>
|
<INITGLOBALS>
|
||||||
</INITGLOBALS>
|
</INITGLOBALS>
|
||||||
|
|
||||||
<BLOCK NAME=main ADDRESS=null ALIGN=NONE POS=[unittest: line 42 col 1-9]>
|
<BLOCK NAME="main" ADDRESS="null" ALIGN="NONE" POS="[unittest: line 42 col 1-9]">
|
||||||
</BLOCK>
|
</BLOCK>
|
||||||
</PROGRAM>
|
</PROGRAM>
|
||||||
""")
|
""")
|
||||||
|
@ -3,6 +3,8 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- fix IR/VM compiler crash: subroutine address in array: uword[] @shared ptrs = [&x1, &x2, &start] + unit test
|
||||||
|
- IRFileReader should parse the p8ir file with xml parser
|
||||||
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
|
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
|
||||||
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
|
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
|
||||||
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
||||||
|
@ -1,35 +1,18 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import psg
|
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte @shared variable
|
uword[] @shared ptrs = [&x1, &x2, &start, 4242, 4242]
|
||||||
|
ubyte x1
|
||||||
|
ubyte x2
|
||||||
|
|
||||||
sub nested() {
|
txt.print_uwhex(ptrs[0], true)
|
||||||
ubyte @shared variable2
|
txt.spc()
|
||||||
|
txt.print_uwhex(ptrs[1], true)
|
||||||
variable2 = 33
|
txt.spc()
|
||||||
nested()
|
txt.print_uwhex(ptrs[2], true)
|
||||||
|
txt.nl()
|
||||||
sub nested() {
|
|
||||||
ubyte @shared variable3
|
|
||||||
|
|
||||||
variable3 = 33
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nested()
|
|
||||||
explosion()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub explosion() {
|
|
||||||
; this subroutine is not used but it is an example of how to make a sound effect using the psg library!
|
|
||||||
psg.silent()
|
|
||||||
psg.voice(0, psg.LEFT, 63, psg.NOISE, 0)
|
|
||||||
psg.voice(1, psg.RIGHT, 63, psg.NOISE, 0)
|
|
||||||
psg.freq(0, 1000)
|
|
||||||
psg.freq(1, 2000)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,34 @@ import kotlin.io.path.bufferedReader
|
|||||||
|
|
||||||
class IRFileReader {
|
class IRFileReader {
|
||||||
|
|
||||||
fun read(irSourceCode: CharSequence): IRProgram {
|
fun read(irSourceCode: String): IRProgram {
|
||||||
|
// TODO parse the source via XML parser
|
||||||
|
// val isrc = InputSource(StringReader(irSourceCode))
|
||||||
|
// val xmlDoc: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(isrc)
|
||||||
|
// xmlDoc.normalizeDocument()
|
||||||
|
// println("ROOT NODE: ${xmlDoc.documentElement.nodeName}") // TODO
|
||||||
|
|
||||||
return parseProgram(irSourceCode.lineSequence().iterator())
|
return parseProgram(irSourceCode.lineSequence().iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun read(irSourceFile: Path): IRProgram {
|
fun read(irSourceFile: Path): IRProgram {
|
||||||
println("Reading intermediate representation from $irSourceFile")
|
println("Reading intermediate representation from $irSourceFile")
|
||||||
irSourceFile.bufferedReader().use { reader ->
|
|
||||||
|
// TODO parse the source via XML parser
|
||||||
|
// val xmlDoc: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(irSourceFile.toFile())
|
||||||
|
// xmlDoc.normalizeDocument()
|
||||||
|
// println("ROOT NODE: ${xmlDoc.documentElement.nodeName}") // TODO
|
||||||
|
|
||||||
|
irSourceFile.bufferedReader(charset=Charsets.UTF_8).use { reader ->
|
||||||
return parseProgram(reader.lineSequence().iterator())
|
return parseProgram(reader.lineSequence().iterator())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseProgram(lines: Iterator<String>): IRProgram {
|
private fun parseProgram(lines: Iterator<String>): IRProgram {
|
||||||
val programPattern = Regex("<PROGRAM NAME=(.+)>")
|
val xmlheader = lines.next()
|
||||||
|
if(!xmlheader.startsWith("<?xml version=\"1.0\""))
|
||||||
|
throw IRParseException("missing xml header")
|
||||||
|
val programPattern = Regex("<PROGRAM NAME=\"(.+)\">")
|
||||||
val line = lines.next()
|
val line = lines.next()
|
||||||
val match = programPattern.matchEntire(line) ?: throw IRParseException("invalid PROGRAM")
|
val match = programPattern.matchEntire(line) ?: throw IRParseException("invalid PROGRAM")
|
||||||
val programName = match.groups[1]!!.value
|
val programName = match.groups[1]!!.value
|
||||||
@ -171,7 +186,7 @@ class IRFileReader {
|
|||||||
} else {
|
} else {
|
||||||
bss = false
|
bss = false
|
||||||
initArray = value.split(',').map {
|
initArray = value.split(',').map {
|
||||||
if (it.startsWith('&'))
|
if (it.startsWith('@'))
|
||||||
StArrayElement(null, it.drop(1).split('.'))
|
StArrayElement(null, it.drop(1).split('.'))
|
||||||
else
|
else
|
||||||
StArrayElement(parseIRValue(it).toDouble(), null)
|
StArrayElement(parseIRValue(it).toDouble(), null)
|
||||||
@ -194,7 +209,7 @@ class IRFileReader {
|
|||||||
if(line!="<MEMORYMAPPEDVARIABLES>")
|
if(line!="<MEMORYMAPPEDVARIABLES>")
|
||||||
throw IRParseException("invalid MEMORYMAPPEDVARIABLES")
|
throw IRParseException("invalid MEMORYMAPPEDVARIABLES")
|
||||||
val memvars = mutableListOf<StMemVar>()
|
val memvars = mutableListOf<StMemVar>()
|
||||||
val mappedPattern = Regex("&(.+?)(\\[.+?\\])? (.+)=(.+)")
|
val mappedPattern = Regex("@(.+?)(\\[.+?\\])? (.+)=(.+)")
|
||||||
while(true) {
|
while(true) {
|
||||||
line = lines.next()
|
line = lines.next()
|
||||||
if(line=="</MEMORYMAPPEDVARIABLES>")
|
if(line=="</MEMORYMAPPEDVARIABLES>")
|
||||||
@ -286,11 +301,11 @@ class IRFileReader {
|
|||||||
return blocks
|
return blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
private val blockPattern = Regex("<BLOCK NAME=(.+) ADDRESS=(.*) ALIGN=(.+) POS=(.+)>")
|
private val blockPattern = Regex("<BLOCK NAME=\"(.+)\" ADDRESS=\"(.*)\" ALIGN=\"(.+)\" POS=\"(.+)\">")
|
||||||
private val inlineAsmPattern = Regex("<INLINEASM LABEL=(.*) IR=(.+)>")
|
private val inlineAsmPattern = Regex("<INLINEASM LABEL=\"(.*)\" IR=\"(.+)\">")
|
||||||
private val bytesPattern = Regex("<BYTES LABEL=(.*)>")
|
private val bytesPattern = Regex("<BYTES LABEL=\"(.*)\">")
|
||||||
private val asmsubPattern = Regex("<ASMSUB NAME=(.+) ADDRESS=(.+) CLOBBERS=(.*) RETURNS=(.*) POS=(.+)>")
|
private val asmsubPattern = Regex("<ASMSUB NAME=\"(.+)\" ADDRESS=\"(.+)\" CLOBBERS=\"(.*)\" RETURNS=\"(.*)\" POS=\"(.+)\">")
|
||||||
private val subPattern = Regex("<SUB NAME=(.+) RETURNTYPE=(.+) POS=(.+)>")
|
private val subPattern = Regex("<SUB NAME=\"(.+)\" RETURNTYPE=\"(.+)\" POS=\"(.+)\">")
|
||||||
private val posPattern = Regex("\\[(.+): line (.+) col (.+)-(.+)\\]")
|
private val posPattern = Regex("\\[(.+): line (.+) col (.+)-(.+)\\]")
|
||||||
|
|
||||||
private fun parseBlock(startline: String, lines: Iterator<String>): IRBlock {
|
private fun parseBlock(startline: String, lines: Iterator<String>): IRBlock {
|
||||||
@ -445,8 +460,8 @@ class IRFileReader {
|
|||||||
else
|
else
|
||||||
throw IRParseException("invalid or empty <C>ODE chunk")
|
throw IRParseException("invalid or empty <C>ODE chunk")
|
||||||
}
|
}
|
||||||
val label = if(firstline.startsWith("<C LABEL="))
|
val label = if(firstline.startsWith("<C LABEL=\""))
|
||||||
firstline.split('=', limit = 2)[1].dropLast(1)
|
firstline.split('=', limit = 2)[1].dropLast(1).trim('"')
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
val chunk = IRCodeChunk(label, null)
|
val chunk = IRCodeChunk(label, null)
|
||||||
|
@ -8,14 +8,15 @@ import kotlin.io.path.div
|
|||||||
|
|
||||||
class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||||
private val outfile = outfileOverride ?: (irProgram.options.outputDir / ("${irProgram.name}.p8ir"))
|
private val outfile = outfileOverride ?: (irProgram.options.outputDir / ("${irProgram.name}.p8ir"))
|
||||||
private val out = outfile.bufferedWriter()
|
private val out = outfile.bufferedWriter(charset=Charsets.UTF_8)
|
||||||
private var numChunks = 0
|
private var numChunks = 0
|
||||||
private var numInstr = 0
|
private var numInstr = 0
|
||||||
|
|
||||||
|
|
||||||
fun write(): Path {
|
fun write(): Path {
|
||||||
println("Writing intermediate representation to $outfile")
|
println("Writing intermediate representation to $outfile")
|
||||||
out.write("<PROGRAM NAME=${irProgram.name}>\n")
|
out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
||||||
|
out.write("<PROGRAM NAME=\"${irProgram.name}\">\n")
|
||||||
writeOptions()
|
writeOptions()
|
||||||
writeAsmSymbols()
|
writeAsmSymbols()
|
||||||
writeVariableAllocations()
|
writeVariableAllocations()
|
||||||
@ -44,12 +45,12 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
|
|
||||||
private fun writeBlocks() {
|
private fun writeBlocks() {
|
||||||
irProgram.blocks.forEach { block ->
|
irProgram.blocks.forEach { block ->
|
||||||
out.write("\n<BLOCK NAME=${block.name} ADDRESS=${block.address?.toHex()} ALIGN=${block.alignment} POS=${block.position}>\n")
|
out.write("\n<BLOCK NAME=\"${block.name}\" ADDRESS=\"${block.address?.toHex()}\" ALIGN=\"${block.alignment}\" POS=\"${block.position}\">\n")
|
||||||
block.inlineAssembly.forEach {
|
block.inlineAssembly.forEach {
|
||||||
writeInlineAsm(it)
|
writeInlineAsm(it)
|
||||||
}
|
}
|
||||||
block.subroutines.forEach {
|
block.subroutines.forEach {
|
||||||
out.write("<SUB NAME=${it.name} RETURNTYPE=${it.returnType.toString().lowercase()} POS=${it.position}>\n")
|
out.write("<SUB NAME=\"${it.name}\" RETURNTYPE=\"${it.returnType.toString().lowercase()}\" POS=\"${it.position}\">\n")
|
||||||
out.write("<PARAMS>\n")
|
out.write("<PARAMS>\n")
|
||||||
it.parameters.forEach { param -> out.write("${getTypeString(param.dt)} ${param.name}\n") }
|
it.parameters.forEach { param -> out.write("${getTypeString(param.dt)} ${param.name}\n") }
|
||||||
out.write("</PARAMS>\n")
|
out.write("</PARAMS>\n")
|
||||||
@ -70,7 +71,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
if(reg.registerOrPair!=null) "${reg.registerOrPair}:${dt.toString().lowercase()}"
|
if(reg.registerOrPair!=null) "${reg.registerOrPair}:${dt.toString().lowercase()}"
|
||||||
else "${reg.statusflag}:${dt.toString().lowercase()}"
|
else "${reg.statusflag}:${dt.toString().lowercase()}"
|
||||||
}.joinToString(",")
|
}.joinToString(",")
|
||||||
out.write("<ASMSUB NAME=${it.name} ADDRESS=${it.address?.toHex()} CLOBBERS=$clobbers RETURNS=$returns POS=${it.position}>\n")
|
out.write("<ASMSUB NAME=\"${it.name}\" ADDRESS=\"${it.address?.toHex()}\" CLOBBERS=\"$clobbers\" RETURNS=\"$returns\" POS=\"${it.position}\">\n")
|
||||||
out.write("<PARAMS>\n")
|
out.write("<PARAMS>\n")
|
||||||
it.parameters.forEach { (dt, regOrSf) ->
|
it.parameters.forEach { (dt, regOrSf) ->
|
||||||
val reg = if(regOrSf.registerOrPair!=null) regOrSf.registerOrPair.toString()
|
val reg = if(regOrSf.registerOrPair!=null) regOrSf.registerOrPair.toString()
|
||||||
@ -87,7 +88,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
|
|
||||||
private fun writeCodeChunk(chunk: IRCodeChunk) {
|
private fun writeCodeChunk(chunk: IRCodeChunk) {
|
||||||
if(chunk.label!=null)
|
if(chunk.label!=null)
|
||||||
out.write("<C LABEL=${chunk.label}>\n")
|
out.write("<C LABEL=\"${chunk.label}\">\n")
|
||||||
else
|
else
|
||||||
out.write("<C>\n")
|
out.write("<C>\n")
|
||||||
chunk.instructions.forEach { instr ->
|
chunk.instructions.forEach { instr ->
|
||||||
@ -99,7 +100,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun writeInlineBytes(chunk: IRInlineBinaryChunk) {
|
private fun writeInlineBytes(chunk: IRInlineBinaryChunk) {
|
||||||
out.write("<BYTES LABEL=${chunk.label ?: ""}>\n")
|
out.write("<BYTES LABEL=\"${chunk.label ?: ""}\">\n")
|
||||||
chunk.data.withIndex().forEach {(index, byte) ->
|
chunk.data.withIndex().forEach {(index, byte) ->
|
||||||
out.write(byte.toString(16).padStart(2,'0'))
|
out.write(byte.toString(16).padStart(2,'0'))
|
||||||
if(index and 63 == 63 && index < chunk.data.size-1)
|
if(index and 63 == 63 && index < chunk.data.size-1)
|
||||||
@ -109,7 +110,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun writeInlineAsm(chunk: IRInlineAsmChunk) {
|
private fun writeInlineAsm(chunk: IRInlineAsmChunk) {
|
||||||
out.write("<INLINEASM LABEL=${chunk.label ?: ""} IR=${chunk.isIR}>\n")
|
out.write("<INLINEASM LABEL=\"${chunk.label ?: ""}\" IR=\"${chunk.isIR}\">\n")
|
||||||
out.write(chunk.assembly)
|
out.write(chunk.assembly)
|
||||||
out.write("\n</INLINEASM>\n")
|
out.write("\n</INLINEASM>\n")
|
||||||
}
|
}
|
||||||
@ -157,7 +158,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
if(it.number!=null)
|
if(it.number!=null)
|
||||||
it.number!!.toInt().toHex()
|
it.number!!.toInt().toHex()
|
||||||
else
|
else
|
||||||
"&${it.addressOf!!.joinToString(".")}"
|
"@${it.addressOf!!.joinToString(".")}"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"" // array will be zero'd out at program start
|
"" // array will be zero'd out at program start
|
||||||
@ -172,7 +173,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
out.write("\n<MEMORYMAPPEDVARIABLES>\n")
|
out.write("\n<MEMORYMAPPEDVARIABLES>\n")
|
||||||
for (variable in irProgram.st.allMemMappedVariables()) {
|
for (variable in irProgram.st.allMemMappedVariables()) {
|
||||||
val typeStr = getTypeString(variable)
|
val typeStr = getTypeString(variable)
|
||||||
out.write("&$typeStr ${variable.name}=${variable.address.toHex()}\n")
|
out.write("@$typeStr ${variable.name}=${variable.address.toHex()}\n")
|
||||||
}
|
}
|
||||||
out.write("</MEMORYMAPPEDVARIABLES>\n")
|
out.write("</MEMORYMAPPEDVARIABLES>\n")
|
||||||
|
|
||||||
|
@ -521,8 +521,8 @@ data class InstructionFormat(val datatype: IRDataType?,
|
|||||||
/*
|
/*
|
||||||
<X = X is not modified (input/readonly value)
|
<X = X is not modified (input/readonly value)
|
||||||
>X = X is overwritten with output value (output value)
|
>X = X is overwritten with output value (output value)
|
||||||
<>X = X is modified (input + output)
|
<>X = X is modified (read as input + written as output)
|
||||||
TODO: also encode if memory is read/written/modified?
|
TODO: also encode if *memory* is read/written/modified?
|
||||||
*/
|
*/
|
||||||
@Suppress("BooleanLiteralArgument")
|
@Suppress("BooleanLiteralArgument")
|
||||||
val instructionFormats = mutableMapOf(
|
val instructionFormats = mutableMapOf(
|
||||||
|
@ -33,14 +33,16 @@ class TestIRFileInOut: FunSpec({
|
|||||||
val writer = IRFileWriter(program, null)
|
val writer = IRFileWriter(program, null)
|
||||||
val generatedFile = writer.write()
|
val generatedFile = writer.write()
|
||||||
val lines = generatedFile.readLines()
|
val lines = generatedFile.readLines()
|
||||||
lines.first() shouldBe "<PROGRAM NAME=unittest-irwriter>"
|
lines[0] shouldBe "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||||
|
lines[1] shouldBe "<PROGRAM NAME=\"unittest-irwriter\">"
|
||||||
lines.last() shouldBe "</PROGRAM>"
|
lines.last() shouldBe "</PROGRAM>"
|
||||||
generatedFile.deleteExisting()
|
generatedFile.deleteExisting()
|
||||||
lines.size shouldBeGreaterThan 20
|
lines.size shouldBeGreaterThan 20
|
||||||
}
|
}
|
||||||
|
|
||||||
test("test IR reader") {
|
test("test IR reader") {
|
||||||
val source="""<PROGRAM NAME=test-ir-reader>
|
val source="""<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PROGRAM NAME="test-ir-reader">
|
||||||
<OPTIONS>
|
<OPTIONS>
|
||||||
compTarget=virtual
|
compTarget=virtual
|
||||||
output=PRG
|
output=PRG
|
||||||
@ -59,7 +61,7 @@ uword sys.wait.jiffies= zp=DONTCARE
|
|||||||
</VARIABLES>
|
</VARIABLES>
|
||||||
|
|
||||||
<MEMORYMAPPEDVARIABLES>
|
<MEMORYMAPPEDVARIABLES>
|
||||||
&uword cx16.r0=65282
|
@uword cx16.r0=65282
|
||||||
</MEMORYMAPPEDVARIABLES>
|
</MEMORYMAPPEDVARIABLES>
|
||||||
|
|
||||||
<MEMORYSLABS>
|
<MEMORYSLABS>
|
||||||
@ -71,22 +73,22 @@ load.b r1,42
|
|||||||
</C>
|
</C>
|
||||||
</INITGLOBALS>
|
</INITGLOBALS>
|
||||||
|
|
||||||
<BLOCK NAME=main ADDRESS=null ALIGN=NONE POS=[examples/test.p8: line 2 col 2-5]>
|
<BLOCK NAME="main" ADDRESS="null" ALIGN="NONE" POS="[examples/test.p8: line 2 col 2-5]">
|
||||||
<SUB NAME=main.start RETURNTYPE=null POS=[examples/test.p8: line 4 col 6-8]>
|
<SUB NAME="main.start" RETURNTYPE="null" POS="[examples/test.p8: line 4 col 6-8]">
|
||||||
<PARAMS>
|
<PARAMS>
|
||||||
</PARAMS>
|
</PARAMS>
|
||||||
<C LABEL=main.start>
|
<C LABEL="main.start">
|
||||||
return
|
return
|
||||||
</C>
|
</C>
|
||||||
</SUB>
|
</SUB>
|
||||||
</BLOCK>
|
</BLOCK>
|
||||||
|
|
||||||
<BLOCK NAME=sys ADDRESS=null ALIGN=NONE POS=[library:/prog8lib/virtual/syslib.p8: line 3 col 2-4]>
|
<BLOCK NAME="sys" ADDRESS="null" ALIGN="NONE" POS="[library:/prog8lib/virtual/syslib.p8: line 3 col 2-4]">
|
||||||
<SUB NAME=sys.wait RETURNTYPE=null POS=[library:/prog8lib/virtual/syslib.p8: line 15 col 6-8]>
|
<SUB NAME="sys.wait" RETURNTYPE="null" POS="[library:/prog8lib/virtual/syslib.p8: line 15 col 6-8]">
|
||||||
<PARAMS>
|
<PARAMS>
|
||||||
uword sys.wait.jiffies
|
uword sys.wait.jiffies
|
||||||
</PARAMS>
|
</PARAMS>
|
||||||
<INLINEASM LABEL=sys.wait IR=true POS=[library:/prog8lib/virtual/syslib.p8: line 17 col 10-13]>
|
<INLINEASM LABEL="sys.wait" IR="true" POS="[library:/prog8lib/virtual/syslib.p8: line 17 col 10-13]">
|
||||||
loadm.w r0,sys.wait.jiffies
|
loadm.w r0,sys.wait.jiffies
|
||||||
syscall 13
|
syscall 13
|
||||||
</INLINEASM>
|
</INLINEASM>
|
||||||
|
@ -2155,11 +2155,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
|
|
||||||
// probably called via reflection
|
// probably called via reflection
|
||||||
class VmRunner: IVirtualMachineRunner {
|
class VmRunner: IVirtualMachineRunner {
|
||||||
override fun runProgram(irSource: CharSequence) {
|
override fun runProgram(irSource: String) {
|
||||||
runAndTestProgram(irSource) { /* no tests */ }
|
runAndTestProgram(irSource) { /* no tests */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runAndTestProgram(irSource: CharSequence, test: (VirtualMachine) -> Unit) {
|
fun runAndTestProgram(irSource: String, test: (VirtualMachine) -> Unit) {
|
||||||
val irProgram = IRFileReader().read(irSource)
|
val irProgram = IRFileReader().read(irSource)
|
||||||
val vm = VirtualMachine(irProgram)
|
val vm = VirtualMachine(irProgram)
|
||||||
vm.run()
|
vm.run()
|
||||||
|
@ -120,7 +120,8 @@ class TestVm: FunSpec( {
|
|||||||
|
|
||||||
test("vmrunner") {
|
test("vmrunner") {
|
||||||
val runner = VmRunner()
|
val runner = VmRunner()
|
||||||
val irSource="""<PROGRAM NAME=test>
|
val irSource="""<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PROGRAM NAME="test">
|
||||||
<OPTIONS>
|
<OPTIONS>
|
||||||
</OPTIONS>
|
</OPTIONS>
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ class TestVm: FunSpec( {
|
|||||||
<INITGLOBALS>
|
<INITGLOBALS>
|
||||||
</INITGLOBALS>
|
</INITGLOBALS>
|
||||||
|
|
||||||
<BLOCK NAME=main ADDRESS=null ALIGN=NONE POS=[unittest: line 42 col 1-9]>
|
<BLOCK NAME="main" ADDRESS="null" ALIGN="NONE" POS="[unittest: line 42 col 1-9]">
|
||||||
</BLOCK>
|
</BLOCK>
|
||||||
</PROGRAM>
|
</PROGRAM>
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user