mirror of
https://github.com/irmen/prog8.git
synced 2024-07-10 08:28:57 +00:00
vm: fix crashes when array contains pointers/strings
This commit is contained in:
parent
5c9c7f2c5e
commit
c26e116f0e
@ -29,6 +29,14 @@ class PtSub(
|
|||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print(name)
|
print(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
// params and return value should not be str
|
||||||
|
if(parameters.any{ it.type !in NumericDatatypes })
|
||||||
|
throw AssemblyError("non-numeric parameter")
|
||||||
|
if(returntype!=null && returntype !in NumericDatatypes)
|
||||||
|
throw AssemblyError("non-numeric returntype $returntype")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ sealed class SourceCode {
|
|||||||
* [origin]: `library:/x/y/z.p8` for a given `pathString` of "x/y/z.p8"
|
* [origin]: `library:/x/y/z.p8` for a given `pathString` of "x/y/z.p8"
|
||||||
*/
|
*/
|
||||||
class Resource(pathString: String): SourceCode() {
|
class Resource(pathString: String): SourceCode() {
|
||||||
private val normalized = "/" + Path.of(pathString).normalize().toMutableList().joinToString("/")
|
private val normalized = "/" + Path(pathString).normalize().toMutableList().joinToString("/")
|
||||||
|
|
||||||
override val isFromResources = true
|
override val isFromResources = true
|
||||||
override val isFromFilesystem = false
|
override val isFromFilesystem = false
|
||||||
@ -125,7 +125,7 @@ sealed class SourceCode {
|
|||||||
}
|
}
|
||||||
val stream = object {}.javaClass.getResourceAsStream(normalized)
|
val stream = object {}.javaClass.getResourceAsStream(normalized)
|
||||||
text = stream!!.reader().use { it.readText() }
|
text = stream!!.reader().use { it.readText() }
|
||||||
name = Path.of(pathString).toFile().nameWithoutExtension
|
name = Path(pathString).toFile().nameWithoutExtension
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import prog8.code.core.IErrorReporter
|
|||||||
import prog8.codegen.intermediate.IRCodeGen
|
import prog8.codegen.intermediate.IRCodeGen
|
||||||
import prog8.intermediate.IRFileReader
|
import prog8.intermediate.IRFileReader
|
||||||
import prog8.intermediate.IRFileWriter
|
import prog8.intermediate.IRFileWriter
|
||||||
import java.nio.file.Path
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
class VmCodeGen(private val program: PtProgram,
|
class VmCodeGen(private val program: PtProgram,
|
||||||
private val symbolTable: SymbolTable,
|
private val symbolTable: SymbolTable,
|
||||||
@ -33,7 +33,7 @@ class VmCodeGen(private val program: PtProgram,
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun compileIR(listingFilename: String): IAssemblyProgram {
|
fun compileIR(listingFilename: String): IAssemblyProgram {
|
||||||
val irProgram = IRFileReader(Path.of(""), listingFilename).readFile()
|
val irProgram = IRFileReader(Path(""), listingFilename).readFile()
|
||||||
return VmAssemblyProgram(irProgram.name, irProgram)
|
return VmAssemblyProgram(irProgram.name, irProgram)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,12 @@ internal class VmVariableAllocator(val st: SymbolTable, val encoding: IStringEnc
|
|||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
if(variable.onetimeInitializationArrayValue!==null) {
|
if(variable.onetimeInitializationArrayValue!==null) {
|
||||||
variable.onetimeInitializationArrayValue!!.joinToString(",") { it.number!!.toHex() }
|
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||||
|
if(it.number!=null)
|
||||||
|
it.number!!.toHex()
|
||||||
|
else
|
||||||
|
"&${it.addressOf!!.joinToString(".")}"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(1..variable.length!!).joinToString(",") { "0" }
|
(1..variable.length!!).joinToString(",") { "0" }
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
8.5
|
8.6-dev
|
||||||
|
@ -13,6 +13,7 @@ import java.io.File
|
|||||||
import java.nio.file.*
|
import java.nio.file.*
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
@ -142,7 +143,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
for (importedFile in allImportedFiles) {
|
for (importedFile in allImportedFiles) {
|
||||||
print(" ")
|
print(" ")
|
||||||
println(importedFile)
|
println(importedFile)
|
||||||
val watchDir = importedFile.parent ?: Path.of("")
|
val watchDir = importedFile.parent ?: Path("")
|
||||||
watchDir.register(watchservice, StandardWatchEventKinds.ENTRY_MODIFY)
|
watchDir.register(watchservice, StandardWatchEventKinds.ENTRY_MODIFY)
|
||||||
}
|
}
|
||||||
println("[${LocalDateTime.now().withNano(0)}] Waiting for file changes.")
|
println("[${LocalDateTime.now().withNano(0)}] Waiting for file changes.")
|
||||||
|
@ -320,9 +320,12 @@ class IntermediateAstMaker(val program: Program) {
|
|||||||
|
|
||||||
private fun transformSub(srcSub: Subroutine): PtSub {
|
private fun transformSub(srcSub: Subroutine): PtSub {
|
||||||
val (vardecls, statements) = srcSub.statements.partition { it is VarDecl }
|
val (vardecls, statements) = srcSub.statements.partition { it is VarDecl }
|
||||||
|
var returntype = srcSub.returntypes.singleOrNull()
|
||||||
|
if(returntype==DataType.STR)
|
||||||
|
returntype=DataType.UWORD // if a sub returns 'str', replace with uword. Intermediate AST and I.R. don't contain 'str' datatype anymore.
|
||||||
val sub = PtSub(srcSub.name,
|
val sub = PtSub(srcSub.name,
|
||||||
srcSub.parameters.map { PtSubroutineParameter(it.name, it.type, it.position) },
|
srcSub.parameters.map { PtSubroutineParameter(it.name, it.type, it.position) },
|
||||||
srcSub.returntypes.singleOrNull(),
|
returntype,
|
||||||
srcSub.inline,
|
srcSub.inline,
|
||||||
srcSub.position)
|
srcSub.position)
|
||||||
sub.parameters.forEach { it.parent=sub }
|
sub.parameters.forEach { it.parent=sub }
|
||||||
|
@ -22,6 +22,7 @@ internal fun compileFile(
|
|||||||
outputDir: Path = prog8tests.helpers.outputDir,
|
outputDir: Path = prog8tests.helpers.outputDir,
|
||||||
errors: IErrorReporter? = null,
|
errors: IErrorReporter? = null,
|
||||||
writeAssembly: Boolean = true,
|
writeAssembly: Boolean = true,
|
||||||
|
keepIR: Boolean = true,
|
||||||
optFloatExpr: Boolean = true
|
optFloatExpr: Boolean = true
|
||||||
) : CompilationResult? {
|
) : CompilationResult? {
|
||||||
val filepath = fileDir.resolve(fileName)
|
val filepath = fileDir.resolve(fileName)
|
||||||
@ -36,7 +37,7 @@ internal fun compileFile(
|
|||||||
quietAssembler = true,
|
quietAssembler = true,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
keepIR = false,
|
keepIR = keepIR,
|
||||||
platform.name,
|
platform.name,
|
||||||
evalStackBaseAddress = null,
|
evalStackBaseAddress = null,
|
||||||
symbolDefs = emptyMap(),
|
symbolDefs = emptyMap(),
|
||||||
@ -57,12 +58,14 @@ internal fun compileText(
|
|||||||
sourceText: String,
|
sourceText: String,
|
||||||
errors: IErrorReporter? = null,
|
errors: IErrorReporter? = null,
|
||||||
writeAssembly: Boolean = true,
|
writeAssembly: Boolean = true,
|
||||||
|
keepIR: Boolean = true,
|
||||||
optFloatExpr: Boolean = true
|
optFloatExpr: Boolean = true
|
||||||
) : CompilationResult? {
|
) : CompilationResult? {
|
||||||
val filePath = outputDir.resolve("on_the_fly_test_" + sourceText.hashCode().toUInt().toString(16) + ".p8")
|
val filePath = outputDir.resolve("on_the_fly_test_" + sourceText.hashCode().toUInt().toString(16) + ".p8")
|
||||||
// we don't assumeNotExists(filePath) - should be ok to just overwrite it
|
// we don't assumeNotExists(filePath) - should be ok to just overwrite it
|
||||||
filePath.toFile().writeText(sourceText)
|
filePath.toFile().writeText(sourceText)
|
||||||
return compileFile(platform, optimize, filePath.parent, filePath.name, errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr)
|
return compileFile(platform, optimize, filePath.parent, filePath.name,
|
||||||
|
errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr, keepIR=keepIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
104
compiler/test/vm/TestCompilerVirtual.kt
Normal file
104
compiler/test/vm/TestCompilerVirtual.kt
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package prog8tests.vm
|
||||||
|
|
||||||
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
import io.kotest.matchers.shouldNotBe
|
||||||
|
import prog8.code.target.Cx16Target
|
||||||
|
import prog8.code.target.VMTarget
|
||||||
|
import prog8.vm.VmRunner
|
||||||
|
import prog8tests.helpers.compileText
|
||||||
|
import kotlin.io.path.readText
|
||||||
|
|
||||||
|
class TestCompilerVirtual: FunSpec({
|
||||||
|
test("compile virtual: any all sort reverse builtin funcs") {
|
||||||
|
val src = """
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
uword[] words = [1111,2222,0,4444,3333]
|
||||||
|
ubyte result = all(words)
|
||||||
|
result++
|
||||||
|
result = any(words)
|
||||||
|
result++
|
||||||
|
sort(words)
|
||||||
|
reverse(words)
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val target = VMTarget()
|
||||||
|
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
|
||||||
|
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
|
||||||
|
VmRunner().runProgram(virtfile.readText(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("compile virtual: array with pointers") {
|
||||||
|
val src = """
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
ubyte variable
|
||||||
|
uword[] words = [1111,2222,"three",&variable]
|
||||||
|
variable = 2222 in words
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
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().runProgram(virtfile.readText(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("compile virtual: str args and return type") {
|
||||||
|
val src = """
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
sub testsub(str s1) -> str {
|
||||||
|
return "result"
|
||||||
|
}
|
||||||
|
|
||||||
|
uword result = testsub("arg")
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val target = VMTarget()
|
||||||
|
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
|
||||||
|
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
|
||||||
|
VmRunner().runProgram(virtfile.readText(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("compile virtual: nested labels") {
|
||||||
|
val src = """
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
uword i
|
||||||
|
uword k
|
||||||
|
|
||||||
|
mylabel_outside:
|
||||||
|
for i in 0 to 10 {
|
||||||
|
mylabel_inside:
|
||||||
|
if i==100 {
|
||||||
|
goto mylabel_outside
|
||||||
|
goto mylabel_inside
|
||||||
|
}
|
||||||
|
while k <= 10 {
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
k--
|
||||||
|
} until k==0
|
||||||
|
for k in 0 to 5 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
repeat 10 {
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
|
||||||
|
val target = VMTarget()
|
||||||
|
val result = compileText(target, true, src, writeAssembly = true, keepIR=true)!!
|
||||||
|
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8virt")
|
||||||
|
VmRunner().runProgram(virtfile.readText(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
@ -8,7 +8,7 @@ import prog8.ast.expressions.*
|
|||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.parser.Prog8ANTLRParser
|
import prog8.parser.Prog8ANTLRParser
|
||||||
import java.nio.file.Path
|
import kotlin.io.path.Path
|
||||||
import kotlin.io.path.isRegularFile
|
import kotlin.io.path.isRegularFile
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ private data class NumericLiteralNode(val number: Double, val datatype: DataType
|
|||||||
private fun ParserRuleContext.toPosition() : Position {
|
private fun ParserRuleContext.toPosition() : Position {
|
||||||
val pathString = start.inputStream.sourceName
|
val pathString = start.inputStream.sourceName
|
||||||
val filename = if(SourceCode.isRegularFilesystemPath(pathString)) {
|
val filename = if(SourceCode.isRegularFilesystemPath(pathString)) {
|
||||||
val path = Path.of(pathString)
|
val path = Path(pathString)
|
||||||
if(path.isRegularFile()) {
|
if(path.isRegularFile()) {
|
||||||
SourceCode.relative(path).toString()
|
SourceCode.relative(path).toString()
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,8 +3,10 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- fix compiler crash in examples/vm/bsieve.p8
|
- fix vm crash in TestCompilerVirtual: while loop
|
||||||
- fix nullpointer in allocator in examples/vm/textelite.p8
|
- fix vm crash in TestCompilerVirtual: array with pointers
|
||||||
|
- fix vm crash (while loop) in examples/vm/bsieve.p8 (Assembler)
|
||||||
|
- fix vm crash (parseValue error) in examples/vm/textelite.p8 (Assembler)
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -26,13 +26,14 @@ main {
|
|||||||
@(flags_ptr + k) = false
|
@(flags_ptr + k) = false
|
||||||
k += prime
|
k += prime
|
||||||
}
|
}
|
||||||
; txt.print_uw(prime)
|
txt.print_uw(prime)
|
||||||
; txt.spc()
|
txt.spc()
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txt.nl()
|
||||||
txt.print_uw(count)
|
txt.print_uw(count)
|
||||||
txt.print(" primes\n")
|
txt.print(" primes\n")
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import org.takes.rs.RsJson
|
|||||||
import org.takes.tk.TkSlf4j
|
import org.takes.tk.TkSlf4j
|
||||||
import prog8.compiler.CompilerArguments
|
import prog8.compiler.CompilerArguments
|
||||||
import prog8.compiler.compileProgram
|
import prog8.compiler.compileProgram
|
||||||
import java.nio.file.Path
|
|
||||||
import javax.json.Json
|
import javax.json.Json
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
|
|
||||||
class Jsonding: RsJson.Source {
|
class Jsonding: RsJson.Source {
|
||||||
@ -31,7 +31,7 @@ class RequestParser : Take {
|
|||||||
val names = form.names()
|
val names = form.names()
|
||||||
val a = form.param("a").single()
|
val a = form.param("a").single()
|
||||||
val args = CompilerArguments(
|
val args = CompilerArguments(
|
||||||
Path.of(a),
|
Path(a),
|
||||||
optimize = true,
|
optimize = true,
|
||||||
optimizeFloatExpressions = false,
|
optimizeFloatExpressions = false,
|
||||||
dontReinitGlobals = false,
|
dontReinitGlobals = false,
|
||||||
|
@ -4,6 +4,7 @@ import prog8.code.*
|
|||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.code.target.*
|
import prog8.code.target.*
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.Path
|
||||||
import kotlin.io.path.bufferedReader
|
import kotlin.io.path.bufferedReader
|
||||||
import kotlin.io.path.div
|
import kotlin.io.path.div
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
var loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
var loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
||||||
var dontReinitGlobals = false
|
var dontReinitGlobals = false
|
||||||
var evalStackBaseAddress: UInt? = null
|
var evalStackBaseAddress: UInt? = null
|
||||||
|
var outputDir = Path("")
|
||||||
if(line!="<OPTIONS>")
|
if(line!="<OPTIONS>")
|
||||||
throw IRParseException("invalid OPTIONS")
|
throw IRParseException("invalid OPTIONS")
|
||||||
while(true) {
|
while(true) {
|
||||||
@ -82,6 +84,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
val (start, end) = value.split(',')
|
val (start, end) = value.split(',')
|
||||||
zpReserved.add(UIntRange(start.toUInt(), end.toUInt()))
|
zpReserved.add(UIntRange(start.toUInt(), end.toUInt()))
|
||||||
}
|
}
|
||||||
|
"outputDir" -> outputDir = Path(value)
|
||||||
else -> throw IRParseException("illegal OPTION $name")
|
else -> throw IRParseException("illegal OPTION $name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +99,8 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
target,
|
target,
|
||||||
loadAddress,
|
loadAddress,
|
||||||
dontReinitGlobals = dontReinitGlobals,
|
dontReinitGlobals = dontReinitGlobals,
|
||||||
evalStackBaseAddress = evalStackBaseAddress
|
evalStackBaseAddress = evalStackBaseAddress,
|
||||||
|
outputDir = outputDir
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +134,12 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
initArray = value.split(',').map { StArrayElement(it.toDouble(), null) }
|
initArray = value.split(',').map {
|
||||||
|
if(it.startsWith('&'))
|
||||||
|
StArrayElement(null, it.drop(1).split('.'))
|
||||||
|
else
|
||||||
|
StArrayElement(it.toDouble(), null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DataType.STR -> throw IRParseException("STR should have been converted to byte array")
|
DataType.STR -> throw IRParseException("STR should have been converted to byte array")
|
||||||
else -> throw IRParseException("weird dt")
|
else -> throw IRParseException("weird dt")
|
||||||
@ -173,7 +182,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
"uword" -> DataType.ARRAY_UW
|
"uword" -> DataType.ARRAY_UW
|
||||||
"float" -> DataType.ARRAY_F
|
"float" -> DataType.ARRAY_F
|
||||||
"bool" -> DataType.ARRAY_B
|
"bool" -> DataType.ARRAY_B
|
||||||
else -> throw IRParseException("invalid dt")
|
else -> throw IRParseException("invalid dt $type")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
@ -183,7 +192,8 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
"uword" -> DataType.UWORD
|
"uword" -> DataType.UWORD
|
||||||
"float" -> DataType.FLOAT
|
"float" -> DataType.FLOAT
|
||||||
"bool" -> DataType.BOOL
|
"bool" -> DataType.BOOL
|
||||||
else -> throw IRParseException("invalid dt")
|
// note: 'str' should not occur anymore in IR. Should be 'uword'
|
||||||
|
else -> throw IRParseException("invalid dt $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
|||||||
out.write("loadAddress=${irProgram.options.loadAddress}\n")
|
out.write("loadAddress=${irProgram.options.loadAddress}\n")
|
||||||
out.write("dontReinitGlobals=${irProgram.options.dontReinitGlobals}\n")
|
out.write("dontReinitGlobals=${irProgram.options.dontReinitGlobals}\n")
|
||||||
out.write("evalStackBaseAddress=${irProgram.options.evalStackBaseAddress}\n")
|
out.write("evalStackBaseAddress=${irProgram.options.evalStackBaseAddress}\n")
|
||||||
|
out.write("outputDir=${irProgram.options.outputDir.toAbsolutePath()}\n")
|
||||||
// other options not yet useful here?
|
// other options not yet useful here?
|
||||||
out.write("</OPTIONS>\n")
|
out.write("</OPTIONS>\n")
|
||||||
}
|
}
|
||||||
@ -117,7 +118,12 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
|||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
if(variable.onetimeInitializationArrayValue!==null) {
|
if(variable.onetimeInitializationArrayValue!==null) {
|
||||||
variable.onetimeInitializationArrayValue!!.joinToString(",") { it.number!!.toInt().toString() }
|
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||||
|
if(it.number!=null)
|
||||||
|
it.number!!.toInt().toString()
|
||||||
|
else
|
||||||
|
"&${it.addressOf!!.joinToString(".")}"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(1..variable.length!!).joinToString(",") { "0" }
|
(1..variable.length!!).joinToString(",") { "0" }
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,12 @@ class IRSubroutine(val name: String,
|
|||||||
throw IllegalArgumentException("subroutine name is not scoped: $name")
|
throw IllegalArgumentException("subroutine name is not scoped: $name")
|
||||||
if(name.startsWith("main.main."))
|
if(name.startsWith("main.main."))
|
||||||
throw IllegalArgumentException("subroutine name invalid main prefix: $name")
|
throw IllegalArgumentException("subroutine name invalid main prefix: $name")
|
||||||
|
|
||||||
|
// params and return value should not be str
|
||||||
|
if(parameters.any{ it.dt !in NumericDatatypes })
|
||||||
|
throw IllegalArgumentException("non-numeric parameter")
|
||||||
|
if(returnType!=null && returnType !in NumericDatatypes)
|
||||||
|
throw IllegalArgumentException("non-numeric returntype $returnType")
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun plusAssign(chunk: IRCodeChunkBase) { chunks+= chunk }
|
operator fun plusAssign(chunk: IRCodeChunkBase) { chunks+= chunk }
|
||||||
|
@ -12,17 +12,13 @@ import prog8.code.target.Cx16Target
|
|||||||
import prog8.intermediate.IRFileReader
|
import prog8.intermediate.IRFileReader
|
||||||
import prog8.intermediate.IRFileWriter
|
import prog8.intermediate.IRFileWriter
|
||||||
import prog8.intermediate.IRProgram
|
import prog8.intermediate.IRProgram
|
||||||
import java.nio.file.Path
|
import kotlin.io.path.*
|
||||||
import kotlin.io.path.deleteExisting
|
|
||||||
import kotlin.io.path.name
|
|
||||||
import kotlin.io.path.readLines
|
|
||||||
import kotlin.io.path.writeText
|
|
||||||
|
|
||||||
class TestIRFileInOut: FunSpec({
|
class TestIRFileInOut: FunSpec({
|
||||||
test("test IR writer") {
|
test("test IR writer") {
|
||||||
val st = SymbolTable()
|
val st = SymbolTable()
|
||||||
val target = Cx16Target()
|
val target = Cx16Target()
|
||||||
val tempdir = Path.of(System.getProperty("java.io.tmpdir"))
|
val tempdir = Path(System.getProperty("java.io.tmpdir"))
|
||||||
val options = CompilationOptions(
|
val options = CompilationOptions(
|
||||||
OutputType.RAW,
|
OutputType.RAW,
|
||||||
CbmPrgLauncherType.NONE,
|
CbmPrgLauncherType.NONE,
|
||||||
|
@ -2112,6 +2112,6 @@ class VmRunner: IVirtualMachineRunner {
|
|||||||
assembler.initializeMemory(memsrc, memory)
|
assembler.initializeMemory(memsrc, memory)
|
||||||
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(throttle = true)
|
vm.run(throttle = throttle)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user