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

View File

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

View File

@ -3,106 +3,49 @@
~ main {
ubyte[256] sieve
ubyte candidate_prime = 2 ; is increased in the loop
sub start() {
memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs
ubyte ub = 10
byte bb=-100
uword uw = 1000
word ww = -25000
ubyte i = 0
; calculate primes
c64scr.print("prime numbers up to 255:\n\n")
ubyte amount=0
while true {
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
c64scr.print_b(bb)
c64.CHROUT(',')
i++
sub find_next_prime() -> ubyte {
while sieve[candidate_prime] {
candidate_prime++
if candidate_prime==0
return 0 ; we wrapped; no more primes available in the sieve
}
; c64scr.print("while1\n")
; while(ub < 220) {
; c64scr.print_ub(ub)
; c64.CHROUT(',')
; ub += 25
; if ub < 150 continue else break
; ub=99
; }
; c64.CHROUT('\n')
;
; c64scr.print("while2\n")
; while(bb < 120) {
; 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')
; found next one, mark the multiples and return it.
sieve[candidate_prime] = true
uword multiple = candidate_prime
while multiple < len(sieve) {
sieve[lsb(multiple)] = true
multiple += candidate_prime
; c64scr.print_uw(multiple) ; TODO
; c4.CHROUT('\n') ; TODO
}
return candidate_prime
}
}