diff --git a/compiler/src/prog8/ast/StmtReorderer.kt b/compiler/src/prog8/ast/StmtReorderer.kt index c75663bcd..753ddea88 100644 --- a/compiler/src/prog8/ast/StmtReorderer.kt +++ b/compiler/src/prog8/ast/StmtReorderer.kt @@ -10,6 +10,9 @@ fun Module.reorderStatements(namespace: INameScope, heap: HeapValues) { this.process(checker) } +const val initvarsSubName="prog8_init_vars" // the name of the subroutine that should be called for every block to initialize its variables + + private class StatementReorderer(private val namespace: INameScope, private val heap: HeapValues): IAstProcessor { // Reorders the statements in a way the compiler needs. // - 'main' block must be the very first statement UNLESS it has an address set. @@ -93,6 +96,19 @@ private class StatementReorderer(private val namespace: INameScope, private val sortConstantAssignments(block.statements) + val varInits = block.statements.withIndex().filter { it.value is VariableInitializationAssignment } + if(varInits.isNotEmpty()) { + val statements = varInits.map{it.value}.toMutableList() + val varInitSub = Subroutine(initvarsSubName, emptyList(), emptyList(), emptyList(), emptyList(), + emptySet(), null, false, statements, block.position) + varInitSub.linkParents(block) + block.statements.add(varInitSub) + + // remove the varinits from the block's statements + for(index in varInits.map{it.index}.reversed()) + block.statements.removeAt(index) + } + return super.process(block) } diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index a80278da5..e85667af1 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -173,6 +173,12 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } out(" ldx #\$ff\t; init estack pointer") + out(" ; initialize the variables in each block") + for(block in program.blocks) { + val initVarsLabel = block.instructions.firstOrNull { it is LabelInstr && it.name==initvarsSubName } as? LabelInstr + if(initVarsLabel!=null) + out(" jsr ${block.scopedname}.${initVarsLabel.name}") + } out(" clc") out(" jmp main.start\t; jump to program entrypoint") out("") diff --git a/examples/primes.p8 b/examples/primes.p8 index 443acf5b5..9590140c0 100644 --- a/examples/primes.p8 +++ b/examples/primes.p8 @@ -2,12 +2,11 @@ ~ main { + ubyte[256] sieve + ubyte candidate_prime = 2 sub start() { - ; clear the sieve, and mark 0 and 1 as not prime. - memset(sieve, 256, false) - sieve[0] = true - sieve[1] = true + memset(sieve, 256, false) ; clear the sieve ; calculate primes c64scr.print("prime numbers up to 255:\n\n") @@ -21,21 +20,21 @@ c64.CHROUT('\n') } - ubyte[256] sieve sub find_next_prime() -> ubyte { - for ubyte prime in 2 to 255 { - if not sieve[prime] { - ; found one, mark the multiples and return it. - sieve[prime] = true - uword multiple = prime**2 - while multiple < len(sieve) { - sieve[lsb(multiple)] = true - multiple += prime - } - return prime - } + while sieve[candidate_prime] { + candidate_prime++ + if candidate_prime==0 + return 0 ; we wrapped; no more primes available in the sieve } - return 0 + + ; found next one, mark the multiples and return it. + sieve[candidate_prime] = true + uword multiple = candidate_prime**2 + while multiple < len(sieve) { + sieve[lsb(multiple)] = true + multiple += candidate_prime + } + return candidate_prime } } diff --git a/examples/test.p8 b/examples/test.p8 index a752922c2..668332c28 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,26 +2,17 @@ ~ main { + ubyte xx=99 + word yy=12345 + sub start() { - while true { - A=99 - } + c64scr.print_ub(xx) + c64.CHROUT('\n') + c64scr.print_w(yy) + c64.CHROUT('\n') - while true { - A=99 - if A>100 - break - } - - repeat { - A=99 - } until false - - repeat { - A=99 - if A>100 - break - } until false + foo.derp() + foo2.derp() } @@ -33,3 +24,21 @@ ; push_byte ub:01 ; jnz _prog8stmt_7_loop } + + +~ foo { + + ubyte woo=2 + + sub derp() { + A=woo + } +} + +~ foo2 { + + sub derp() { + ubyte woo=3 + A=99 + } +}