fix Return when dealing with non-subroutine scopes

This commit is contained in:
Irmen de Jong 2019-06-25 01:44:57 +02:00
parent 268856823a
commit b11d10e2ff
3 changed files with 57 additions and 119 deletions

View File

@ -17,7 +17,6 @@ class RuntimeVariables {
val where = vars.getValue(scope) val where = vars.getValue(scope)
where[name] = initialValue where[name] = initialValue
vars[scope] = where vars[scope] = where
println("DEFINE RUNTIMEVAR: ${scope.name}.$name = $initialValue") // TODO
} }
fun set(scope: INameScope, name: String, value: RuntimeValue) { fun set(scope: INameScope, name: String, value: RuntimeValue) {
@ -27,7 +26,6 @@ class RuntimeVariables {
throw VmExecutionException("new value is of different datatype ${value.type} expected ${existing.type} for $name") throw VmExecutionException("new value is of different datatype ${value.type} expected ${existing.type} for $name")
where[name] = value where[name] = value
vars[scope] = where vars[scope] = where
println("SET RUNTIMEVAR: ${scope.name}.$name = $value") // TODO
} }
fun get(scope: INameScope, name: String): RuntimeValue { fun get(scope: INameScope, name: String): RuntimeValue {
@ -110,14 +108,11 @@ class AstVm(val program: Program) {
class LoopControlContinue: Exception() class LoopControlContinue: Exception()
class LoopControlReturn(val returnvalues: List<RuntimeValue>): Exception() class LoopControlReturn(val returnvalues: List<RuntimeValue>): Exception()
internal fun executeSubroutine(sub: INameScope, arguments: List<RuntimeValue>): List<RuntimeValue> { internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValue>): List<RuntimeValue> {
assert(!sub.isAsmSubroutine)
if (sub.statements.isEmpty()) if (sub.statements.isEmpty())
if(sub !is AnonymousScope) throw VmTerminationException("scope contains no statements: $sub")
throw VmTerminationException("scope contains no statements: $sub") // TODO process arguments if it's a subroutine
if(sub is Subroutine) {
assert(!sub.isAsmSubroutine)
// TODO process arguments if it's a subroutine
}
try { try {
for (s in sub.statements) { for (s in sub.statements) {
executeStatement(sub, s) executeStatement(sub, s)
@ -125,14 +120,18 @@ class AstVm(val program: Program) {
} catch (r: LoopControlReturn) { } catch (r: LoopControlReturn) {
return r.returnvalues return r.returnvalues
} }
if(sub !is AnonymousScope) throw VmTerminationException("instruction pointer overflow, is a return missing? $sub")
throw VmTerminationException("instruction pointer overflow, is a return missing? $sub") }
return emptyList()
internal fun executeAnonymousScope(scope: INameScope) {
for (s in scope.statements) {
executeStatement(scope, s)
}
} }
private fun executeStatement(sub: INameScope, stmt: IStatement) { private fun executeStatement(sub: INameScope, stmt: IStatement) {
instructionCounter++ instructionCounter++
if(instructionCounter % 10 == 0) if(instructionCounter % 100 == 0)
Thread.sleep(1) Thread.sleep(1)
when (stmt) { when (stmt) {
is NopStatement, is Label, is Subroutine -> { is NopStatement, is Label, is Subroutine -> {
@ -249,15 +248,13 @@ class AstVm(val program: Program) {
is InlineAssembly -> { is InlineAssembly -> {
throw VmExecutionException("can't execute inline assembly in $sub") throw VmExecutionException("can't execute inline assembly in $sub")
} }
is AnonymousScope -> { is AnonymousScope -> executeAnonymousScope(stmt)
throw VmExecutionException("anonymous scopes should have been flattened")
}
is IfStatement -> { is IfStatement -> {
val condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine) val condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
if(condition.asBoolean) if(condition.asBoolean)
executeSubroutine(stmt.truepart, emptyList()) executeAnonymousScope(stmt.truepart)
else else
executeSubroutine(stmt.elsepart, emptyList()) executeAnonymousScope(stmt.elsepart)
} }
is BranchStatement -> { is BranchStatement -> {
TODO("$stmt") TODO("$stmt")
@ -276,8 +273,7 @@ class AstVm(val program: Program) {
var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine) var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
while (condition.asBoolean) { while (condition.asBoolean) {
try { try {
println("STILL IN WHILE LOOP ${stmt.position}") executeAnonymousScope(stmt.body)
executeSubroutine(stmt.body, emptyList())
condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine) condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
} catch(b: LoopControlBreak) { } catch(b: LoopControlBreak) {
break break
@ -285,13 +281,12 @@ class AstVm(val program: Program) {
continue continue
} }
} }
println(">>>>WHILE LOOP EXITED")
} }
is RepeatLoop -> { is RepeatLoop -> {
do { do {
val condition = evaluate(stmt.untilCondition, program, runtimeVariables, ::executeSubroutine) val condition = evaluate(stmt.untilCondition, program, runtimeVariables, ::executeSubroutine)
try { try {
executeSubroutine(stmt.body, emptyList()) executeAnonymousScope(stmt.body)
} catch(b: LoopControlBreak) { } catch(b: LoopControlBreak) {
break break
} catch(c: LoopControlContinue){ } catch(c: LoopControlContinue){

View File

@ -56,7 +56,7 @@ fun evaluate(expr: IExpression, program: Program, runtimeVars: RuntimeVariables,
is AddressOf -> { is AddressOf -> {
// we support: address of heap var -> the heap id // we support: address of heap var -> the heap id
val heapId = expr.identifier.heapId(program.namespace) val heapId = expr.identifier.heapId(program.namespace)
return RuntimeValue(DataType.UWORD, heapId = heapId) return RuntimeValue(DataType.UWORD, heapId)
} }
is DirectMemoryRead -> { is DirectMemoryRead -> {
TODO("$expr") TODO("$expr")

View File

@ -3,106 +3,49 @@
~ main { ~ main {
ubyte[256] sieve
ubyte candidate_prime = 2 ; is increased in the loop
sub start() { sub start() {
memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs
ubyte ub = 10 ; calculate primes
byte bb=-100 c64scr.print("prime numbers up to 255:\n\n")
uword uw = 1000 ubyte amount=0
word ww = -25000 while true {
ubyte i = 0 ubyte prime = find_next_prime()
if prime==0
break
c64scr.print_ub(prime)
c64scr.print(", ")
amount++
}
c64.CHROUT('\n')
c64scr.print("number of primes (expected 54): ")
c64scr.print_ub(amount)
c64.CHROUT('\n')
}
while i < 100 {
bb += 10 sub find_next_prime() -> ubyte {
c64scr.print_b(bb)
c64.CHROUT(',') while sieve[candidate_prime] {
i++ candidate_prime++
if candidate_prime==0
return 0 ; we wrapped; no more primes available in the sieve
} }
; c64scr.print("while1\n") ; found next one, mark the multiples and return it.
; while(ub < 220) { sieve[candidate_prime] = true
; c64scr.print_ub(ub) uword multiple = candidate_prime
; c64.CHROUT(',')
; ub += 25
; if ub < 150 continue else break while multiple < len(sieve) {
; ub=99 sieve[lsb(multiple)] = true
; } multiple += candidate_prime
; c64.CHROUT('\n') ; c64scr.print_uw(multiple) ; TODO
; ; c4.CHROUT('\n') ; TODO
; c64scr.print("while2\n") }
; while(bb < 120) { return candidate_prime
; c64scr.print_b(bb)
; c64.CHROUT(',')
; bb += 25
; if bb < 50 continue else break
; bb=99
; }
; c64.CHROUT('\n')
;
; c64scr.print("while3\n")
; while(uw < 50000) {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; uw += 2500
; if uw < 30000 continue else break
; uw=9999
; }
; c64.CHROUT('\n')
;
; c64scr.print("while4\n")
; while(ww < 30000) {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; ww += 2500
; if ww < 10000 continue else break
; ww=9999
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; ub=22
; bb=-111
; uw=2222
; ww=-22222
;
; c64scr.print("repeat1\n")
; repeat {
; c64scr.print_ub(ub)
; c64.CHROUT(',')
; ub += 22
; ; if ub < 150 continue else break
; ;ub=99
; } until ub>200
; c64.CHROUT('\n')
;
; c64scr.print("repeat2\n")
; repeat {
; c64scr.print_b(bb)
; c64.CHROUT(',')
; bb += 22
; ;if bb < 50 continue else break
; ;bb=99
; } until bb > 100
; c64.CHROUT('\n')
;
; c64scr.print("repeat3\n")
; repeat {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; uw += 2222
; ;if uw < 30000 continue else break
; ;uw=9999
; } until uw>50000
; c64.CHROUT('\n')
;
; c64scr.print("repeat4\n")
; repeat {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; ww += 2222
; ;if ww < 10000 continue else break
; ;ww=9999
; } until ww > 20000
; c64.CHROUT('\n')
; c64.CHROUT('\n')
} }
} }