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)
}
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)
}

View File

@ -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("")

View File

@ -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
}
}

View File

@ -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
}
}