mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +00:00
implemented Jump
This commit is contained in:
parent
53a4379c45
commit
75d8c832ad
@ -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!!)
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user