actually (re)initialize block level variables with their init values

This commit is contained in:
Irmen de Jong 2019-01-27 18:33:21 +01:00
parent 3a8f069854
commit c4a28b8502
4 changed files with 65 additions and 35 deletions

View File

@ -10,6 +10,9 @@ fun Module.reorderStatements(namespace: INameScope, heap: HeapValues) {
this.process(checker) 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 { private class StatementReorderer(private val namespace: INameScope, private val heap: HeapValues): IAstProcessor {
// Reorders the statements in a way the compiler needs. // Reorders the statements in a way the compiler needs.
// - 'main' block must be the very first statement UNLESS it has an address set. // - '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) 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) return super.process(block)
} }

View File

@ -173,6 +173,12 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
out(" ldx #\$ff\t; init estack pointer") 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(" clc")
out(" jmp main.start\t; jump to program entrypoint") out(" jmp main.start\t; jump to program entrypoint")
out("") out("")

View File

@ -2,12 +2,11 @@
~ main { ~ main {
ubyte[256] sieve
ubyte candidate_prime = 2
sub start() { sub start() {
; clear the sieve, and mark 0 and 1 as not prime. memset(sieve, 256, false) ; clear the sieve
memset(sieve, 256, false)
sieve[0] = true
sieve[1] = true
; calculate primes ; calculate primes
c64scr.print("prime numbers up to 255:\n\n") c64scr.print("prime numbers up to 255:\n\n")
@ -21,21 +20,21 @@
c64.CHROUT('\n') c64.CHROUT('\n')
} }
ubyte[256] sieve
sub find_next_prime() -> ubyte { sub find_next_prime() -> ubyte {
for ubyte prime in 2 to 255 { while sieve[candidate_prime] {
if not sieve[prime] { candidate_prime++
; found one, mark the multiples and return it. if candidate_prime==0
sieve[prime] = true return 0 ; we wrapped; no more primes available in the sieve
uword multiple = prime**2 }
; found next one, mark the multiples and return it.
sieve[candidate_prime] = true
uword multiple = candidate_prime**2
while multiple < len(sieve) { while multiple < len(sieve) {
sieve[lsb(multiple)] = true sieve[lsb(multiple)] = true
multiple += prime multiple += candidate_prime
} }
return prime return candidate_prime
}
}
return 0
} }
} }

View File

@ -2,26 +2,17 @@
~ main { ~ main {
ubyte xx=99
word yy=12345
sub start() { sub start() {
while true { c64scr.print_ub(xx)
A=99 c64.CHROUT('\n')
} c64scr.print_w(yy)
c64.CHROUT('\n')
while true { foo.derp()
A=99 foo2.derp()
if A>100
break
}
repeat {
A=99
} until false
repeat {
A=99
if A>100
break
} until false
} }
@ -33,3 +24,21 @@
; push_byte ub:01 ; push_byte ub:01
; jnz _prog8stmt_7_loop ; jnz _prog8stmt_7_loop
} }
~ foo {
ubyte woo=2
sub derp() {
A=woo
}
}
~ foo2 {
sub derp() {
ubyte woo=3
A=99
}
}