From b11d10e2ff9f776002e0e4acbfbe312b7384512b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 25 Jun 2019 01:44:57 +0200 Subject: [PATCH] fix Return when dealing with non-subroutine scopes --- compiler/src/prog8/astvm/AstVm.kt | 39 +++---- compiler/src/prog8/astvm/Expressions.kt | 2 +- examples/test.p8 | 135 +++++++----------------- 3 files changed, 57 insertions(+), 119 deletions(-) diff --git a/compiler/src/prog8/astvm/AstVm.kt b/compiler/src/prog8/astvm/AstVm.kt index 3229e37a3..f8fd8270d 100644 --- a/compiler/src/prog8/astvm/AstVm.kt +++ b/compiler/src/prog8/astvm/AstVm.kt @@ -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): Exception() - internal fun executeSubroutine(sub: INameScope, arguments: List): List { + internal fun executeSubroutine(sub: Subroutine, arguments: List): List { + 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){ diff --git a/compiler/src/prog8/astvm/Expressions.kt b/compiler/src/prog8/astvm/Expressions.kt index 047b78ab6..bf5e1e016 100644 --- a/compiler/src/prog8/astvm/Expressions.kt +++ b/compiler/src/prog8/astvm/Expressions.kt @@ -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") diff --git a/examples/test.p8 b/examples/test.p8 index 613990b8c..b2b548c9a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 } }