implemented Jump

This commit is contained in:
Irmen de Jong 2019-06-28 01:21:31 +02:00
parent 53a4379c45
commit 75d8c832ad
3 changed files with 72 additions and 21 deletions

View File

@ -136,7 +136,7 @@ class AstVm(val program: Program) {
for (s in b.statements.filterIsInstance<Subroutine>()) { for (s in b.statements.filterIsInstance<Subroutine>()) {
if (s.name == initvarsSubName) { if (s.name == initvarsSubName) {
try { try {
executeSubroutine(s, emptyList()) executeSubroutine(s, emptyList(), null)
} catch (x: LoopControlReturn) { } catch (x: LoopControlReturn) {
// regular return // regular return
} }
@ -145,11 +145,36 @@ class AstVm(val program: Program) {
} }
} }
val entrypoint = program.entrypoint() ?: throw VmTerminationException("no valid entrypoint found") var entrypoint: Subroutine? = program.entrypoint() ?: throw VmTerminationException("no valid entrypoint found")
try { var startlabel: Label? = null
executeSubroutine(entrypoint, emptyList())
} catch (x: LoopControlReturn) { while(entrypoint!=null) {
// regular return try {
executeSubroutine(entrypoint, emptyList(), startlabel)
entrypoint = null
} catch (rx: LoopControlReturn) {
// regular return
} catch (jx: LoopControlJump) {
if (jx.address != null)
throw VmTerminationException("doesn't support jumping to machine address ${jx.address}")
when {
jx.generatedLabel != null -> {
val label = entrypoint.getLabelOrVariable(jx.generatedLabel) as Label
TODO("$label")
}
jx.identifier != null -> {
when (val jumptarget = entrypoint.lookup(jx.identifier.nameInSource, jx.identifier.parent)) {
is Label -> {
startlabel = jumptarget
entrypoint = jumptarget.definingSubroutine()
}
is Subroutine -> entrypoint = jumptarget
else -> throw VmTerminationException("weird jump target $jumptarget")
}
}
else -> throw VmTerminationException("unspecified jump target")
}
}
} }
println("PROGRAM EXITED!") println("PROGRAM EXITED!")
dialog.title = "PROGRAM EXITED" dialog.title = "PROGRAM EXITED"
@ -167,8 +192,10 @@ class AstVm(val program: Program) {
class LoopControlBreak : Exception() class LoopControlBreak : Exception()
class LoopControlContinue : Exception() class LoopControlContinue : Exception()
class LoopControlReturn(val returnvalues: List<RuntimeValue>) : Exception() class LoopControlReturn(val returnvalues: List<RuntimeValue>) : Exception()
class LoopControlJump(val identifier: IdentifierReference?, val address: Int?, val generatedLabel: String?) : Exception()
internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValue>): List<RuntimeValue> {
internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValue>, startlabel: Label?=null): List<RuntimeValue> {
assert(!sub.isAsmSubroutine) assert(!sub.isAsmSubroutine)
if (sub.statements.isEmpty()) if (sub.statements.isEmpty())
throw VmTerminationException("scope contains no statements: $sub") throw VmTerminationException("scope contains no statements: $sub")
@ -182,8 +209,16 @@ class AstVm(val program: Program) {
EvalContext(program, mem, statusflags, runtimeVariables, functions, ::executeSubroutine)) EvalContext(program, mem, statusflags, runtimeVariables, functions, ::executeSubroutine))
} }
val statements = sub.statements.iterator()
if(startlabel!=null) {
do {
val stmt = statements.next()
} while(stmt!==startlabel)
}
try { try {
for (s in sub.statements) { while(statements.hasNext()) {
val s = statements.next()
try { try {
executeStatement(sub, s) executeStatement(sub, s)
} }
@ -230,7 +265,7 @@ class AstVm(val program: Program) {
if (target.isAsmSubroutine) { if (target.isAsmSubroutine) {
performSyscall(target, args) performSyscall(target, args)
} else { } else {
executeSubroutine(target, args) executeSubroutine(target, args, null)
// any return value(s) are discarded // any return value(s) are discarded
} }
} }
@ -286,18 +321,11 @@ class AstVm(val program: Program) {
} }
} }
} }
is Jump -> { is Jump -> throw LoopControlJump(stmt.identifier, stmt.address, stmt.generatedLabel)
TODO("jump $stmt")
}
is InlineAssembly -> { is InlineAssembly -> {
if (sub is Subroutine) { if (sub is Subroutine) {
when (sub.scopedname) { val args = sub.parameters.map { runtimeVariables.get(sub, it.name) }
"c64flt.print_f" -> { performSyscall(sub, args)
val arg = runtimeVariables.get(sub, sub.parameters.single().name)
performSyscall(sub, listOf(arg))
}
else -> TODO("simulate asm subroutine ${sub.scopedname}")
}
throw LoopControlReturn(emptyList()) throw LoopControlReturn(emptyList())
} }
throw VmExecutionException("can't execute inline assembly in $sub") throw VmExecutionException("can't execute inline assembly in $sub")
@ -497,6 +525,18 @@ class AstVm(val program: Program) {
val number = args[1].byteval!! val number = args[1].byteval!!
dialog.canvas.printText("$prefix${number.toString(2).padStart(8, '0')}", 1, true) dialog.canvas.printText("$prefix${number.toString(2).padStart(8, '0')}", 1, true)
} }
"c64scr.clear_screenchars" -> {
dialog.canvas.clearScreen(6)
}
"c64scr.clear_screen" -> {
dialog.canvas.clearScreen(args[0].integerValue())
}
"c64scr.setcc" -> {
dialog.canvas.setChar(args[0].integerValue(), args[1].integerValue(), args[2].integerValue().toShort())
}
"c64scr.plot" -> {
dialog.canvas.setCursorPos(args[0].integerValue(), args[1].integerValue())
}
"c64.CHROUT" -> { "c64.CHROUT" -> {
dialog.canvas.printChar(args[0].byteval!!) dialog.canvas.printChar(args[0].byteval!!)
} }

View File

@ -7,7 +7,7 @@ import kotlin.math.abs
class EvalContext(val program: Program, val mem: Memory, val statusflags: StatusFlags, class EvalContext(val program: Program, val mem: Memory, val statusflags: StatusFlags,
val runtimeVars: RuntimeVariables, val functions: BuiltinFunctions, val runtimeVars: RuntimeVariables, val functions: BuiltinFunctions,
val executeSubroutine: (sub: Subroutine, args: List<RuntimeValue>) -> List<RuntimeValue>) val executeSubroutine: (sub: Subroutine, args: List<RuntimeValue>, startlabel: Label?) -> List<RuntimeValue>)
fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
val constval = expr.constValue(ctx.program) val constval = expr.constValue(ctx.program)
@ -117,7 +117,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
val args = expr.arglist.map { evaluate(it, ctx) } val args = expr.arglist.map { evaluate(it, ctx) }
return when(sub) { return when(sub) {
is Subroutine -> { is Subroutine -> {
val results = ctx.executeSubroutine(sub, args) val results = ctx.executeSubroutine(sub, args, null)
if(results.size!=1) if(results.size!=1)
throw VmExecutionException("expected 1 result from functioncall $expr") throw VmExecutionException("expected 1 result from functioncall $expr")
results[0] results[0]

View File

@ -9,7 +9,18 @@
ubyte[100] arr1 ubyte[100] arr1
ubyte[100] arr2 ubyte[100] arr2
_lp:
memcopy(arr1, arr2, len(arr2)) memcopy(arr1, arr2, len(arr2))
c64scr.setcc(20,10,65,2)
goto x
c64scr.setcc(20,10,65,2)
}
sub x() {
derp:
c64scr.print("ey\n")
goto derp
} }