mirror of
https://github.com/irmen/prog8.git
synced 2025-02-28 09:29:26 +00:00
fix Return when dealing with non-subroutine scopes
This commit is contained in:
parent
268856823a
commit
b11d10e2ff
@ -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){
|
||||||
|
@ -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")
|
||||||
|
135
examples/test.p8
135
examples/test.p8
@ -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')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user