Fixed namespace lookup errors related to variable initialization. Removed many X register clobbers.

This commit is contained in:
Irmen de Jong 2019-01-24 23:29:09 +01:00
parent 56e0f4c525
commit 6e3820c6b8
8 changed files with 102 additions and 54 deletions

View File

@ -47,9 +47,10 @@ asmsub byte2decimal (ubyte value @ A) -> clobbers() -> (ubyte @ Y, ubyte @ X,
}} }}
} }
asmsub ubyte2hex (ubyte value @ A) -> clobbers(X) -> (ubyte @ A, ubyte @ Y) { asmsub ubyte2hex (ubyte value @ A) -> clobbers() -> (ubyte @ A, ubyte @ Y) {
; ---- A to hex string in AY (first hex char in A, second hex char in Y) ; ---- A to hex string in AY (first hex char in A, second hex char in Y)
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
pha pha
and #$0f and #$0f
tax tax
@ -61,6 +62,7 @@ asmsub ubyte2hex (ubyte value @ A) -> clobbers(X) -> (ubyte @ A, ubyte @ Y) {
lsr a lsr a
tax tax
lda hex_digits,x lda hex_digits,x
ldx c64.SCRATCH_ZPREGX
rts rts
hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well
@ -69,13 +71,13 @@ hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as
str word2hex_output = "1234" ; 0-terminated, to make printing easier str word2hex_output = "1234" ; 0-terminated, to make printing easier
asmsub uword2hex (uword value @ AY) -> clobbers(A,X,Y) -> () { asmsub uword2hex (uword value @ AY) -> clobbers(A,Y) -> () {
; ---- convert 16 bit uword in A/Y into 4-character hexadecimal string into memory 'word2hex_output' ; ---- convert 16 bit uword in A/Y into 4-character hexadecimal string into memory 'word2hex_output'
%asm {{ %asm {{
sta c64.SCRATCH_ZPREG sta c64.SCRATCH_ZPREG
tya tya
jsr ubyte2hex jsr ubyte2hex
stx word2hex_output sta word2hex_output
sty word2hex_output+1 sty word2hex_output+1
lda c64.SCRATCH_ZPREG lda c64.SCRATCH_ZPREG
jsr ubyte2hex jsr ubyte2hex
@ -86,7 +88,7 @@ asmsub uword2hex (uword value @ AY) -> clobbers(A,X,Y) -> () {
} }
ubyte[3] word2bcd_bcdbuff = [0, 0, 0] ubyte[3] word2bcd_bcdbuff = [0, 0, 0]
asmsub uword2bcd (uword value @ AY) -> clobbers(A,X) -> () { asmsub uword2bcd (uword value @ AY) -> clobbers(A,Y) -> () {
; Convert an 16 bit binary value to BCD ; Convert an 16 bit binary value to BCD
; ;
; This function converts a 16 bit binary value in A/Y into a 24 bit BCD. It ; This function converts a 16 bit binary value in A/Y into a 24 bit BCD. It
@ -103,7 +105,7 @@ asmsub uword2bcd (uword value @ AY) -> clobbers(A,X) -> () {
sta word2bcd_bcdbuff+0 sta word2bcd_bcdbuff+0
sta word2bcd_bcdbuff+1 sta word2bcd_bcdbuff+1
sta word2bcd_bcdbuff+2 sta word2bcd_bcdbuff+2
ldx #16 ; the number of source bits ldy #16 ; the number of source bits
- asl c64.SCRATCH_ZPB1 ; shift out one bit - asl c64.SCRATCH_ZPB1 ; shift out one bit
rol c64.SCRATCH_ZPREG rol c64.SCRATCH_ZPREG
@ -116,7 +118,7 @@ asmsub uword2bcd (uword value @ AY) -> clobbers(A,X) -> () {
lda word2bcd_bcdbuff+2 ; ... thru whole result lda word2bcd_bcdbuff+2 ; ... thru whole result
adc word2bcd_bcdbuff+2 adc word2bcd_bcdbuff+2
sta word2bcd_bcdbuff+2 sta word2bcd_bcdbuff+2
dex ; and repeat for next bit dey ; and repeat for next bit
bne - bne -
cld ; back to binary cld ; back to binary
cli ; enable interrupts again cli ; enable interrupts again
@ -126,7 +128,7 @@ asmsub uword2bcd (uword value @ AY) -> clobbers(A,X) -> () {
ubyte[5] word2decimal_output = 0 ubyte[5] word2decimal_output = 0
asmsub uword2decimal (uword value @ AY) -> clobbers(A,X,Y) -> () { asmsub uword2decimal (uword value @ AY) -> clobbers(A,Y) -> () {
; ---- convert 16 bit uword in A/Y into decimal string into memory 'word2decimal_output' ; ---- convert 16 bit uword in A/Y into decimal string into memory 'word2decimal_output'
%asm {{ %asm {{
jsr uword2bcd jsr uword2bcd
@ -471,11 +473,12 @@ _loop sta c64.Colors,y
} }
asmsub scroll_left_full (ubyte alsocolors @ Pc) -> clobbers(A, X, Y) -> () { asmsub scroll_left_full (ubyte alsocolors @ Pc) -> clobbers(A, Y) -> () {
; ---- scroll the whole screen 1 character to the left ; ---- scroll the whole screen 1 character to the left
; contents of the rightmost column are unchanged, you should clear/refill this yourself ; contents of the rightmost column are unchanged, you should clear/refill this yourself
; Carry flag determines if screen color data must be scrolled too ; Carry flag determines if screen color data must be scrolled too
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
bcs + bcs +
jmp _scroll_screen jmp _scroll_screen
@ -525,16 +528,18 @@ _scroll_screen ; scroll the screen memory
dey dey
bpl - bpl -
ldx c64.SCRATCH_ZPREGX
rts rts
}} }}
} }
asmsub scroll_right_full (ubyte alsocolors @ Pc) -> clobbers(A,X) -> () { asmsub scroll_right_full (ubyte alsocolors @ Pc) -> clobbers(A) -> () {
; ---- scroll the whole screen 1 character to the right ; ---- scroll the whole screen 1 character to the right
; contents of the leftmost column are unchanged, you should clear/refill this yourself ; contents of the leftmost column are unchanged, you should clear/refill this yourself
; Carry flag determines if screen color data must be scrolled too ; Carry flag determines if screen color data must be scrolled too
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
bcs + bcs +
jmp _scroll_screen jmp _scroll_screen
@ -576,16 +581,18 @@ _scroll_screen ; scroll the screen memory
dex dex
bpl - bpl -
ldx c64.SCRATCH_ZPREGX
rts rts
}} }}
} }
asmsub scroll_up_full (ubyte alsocolors @ Pc) -> clobbers(A,X) -> () { asmsub scroll_up_full (ubyte alsocolors @ Pc) -> clobbers(A) -> () {
; ---- scroll the whole screen 1 character up ; ---- scroll the whole screen 1 character up
; contents of the bottom row are unchanged, you should refill/clear this yourself ; contents of the bottom row are unchanged, you should refill/clear this yourself
; Carry flag determines if screen color data must be scrolled too ; Carry flag determines if screen color data must be scrolled too
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
bcs + bcs +
jmp _scroll_screen jmp _scroll_screen
@ -627,16 +634,18 @@ _scroll_screen ; scroll the screen memory
dex dex
bpl - bpl -
ldx c64.SCRATCH_ZPREGX
rts rts
}} }}
} }
asmsub scroll_down_full (ubyte alsocolors @ Pc) -> clobbers(A,X) -> () { asmsub scroll_down_full (ubyte alsocolors @ Pc) -> clobbers(A) -> () {
; ---- scroll the whole screen 1 character down ; ---- scroll the whole screen 1 character down
; contents of the top row are unchanged, you should refill/clear this yourself ; contents of the top row are unchanged, you should refill/clear this yourself
; Carry flag determines if screen color data must be scrolled too ; Carry flag determines if screen color data must be scrolled too
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
bcs + bcs +
jmp _scroll_screen jmp _scroll_screen
@ -678,6 +687,7 @@ _scroll_screen ; scroll the screen memory
dex dex
bpl - bpl -
ldx c64.SCRATCH_ZPREGX
rts rts
}} }}
} }
@ -693,7 +703,7 @@ asmsub print (str text @ AY) -> clobbers(A,Y) -> () {
sta c64.SCRATCH_ZPB1 sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG sty c64.SCRATCH_ZPREG
ldy #0 ldy #0
- lda (c64.SCRATCH_ZPB1),y - lda (c64.SCRATCH_ZPB1),y
beq + beq +
jsr c64.CHROUT jsr c64.CHROUT
iny iny
@ -703,11 +713,12 @@ asmsub print (str text @ AY) -> clobbers(A,Y) -> () {
} }
asmsub print_p (str_p text @ AY) -> clobbers(A,X) -> (ubyte @ Y) { asmsub print_p (str_p text @ AY) -> clobbers(A) -> (ubyte @ Y) {
; ---- print pstring (length as first byte) from A/Y, returns str len in Y ; ---- print pstring (length as first byte) from A/Y, returns str len in Y
%asm {{ %asm {{
sta c64.SCRATCH_ZPB1 sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG sty c64.SCRATCH_ZPREG
stx c64.SCRATCH_ZPREGX
ldy #0 ldy #0
lda (c64.SCRATCH_ZPB1),y lda (c64.SCRATCH_ZPB1),y
beq + beq +
@ -717,14 +728,16 @@ asmsub print_p (str_p text @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
jsr c64.CHROUT jsr c64.CHROUT
dex dex
bne - bne -
+ rts ; output string length is in Y + ldx c64.SCRATCH_ZPREGX
rts ; output string length is in Y
}} }}
} }
asmsub print_ub0 (ubyte value @ A) -> clobbers(A,X,Y) -> () { asmsub print_ub0 (ubyte value @ A) -> clobbers(A,Y) -> () {
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total) ; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
jsr c64utils.ubyte2decimal jsr c64utils.ubyte2decimal
pha pha
tya tya
@ -732,14 +745,17 @@ asmsub print_ub0 (ubyte value @ A) -> clobbers(A,X,Y) -> () {
txa txa
jsr c64.CHROUT jsr c64.CHROUT
pla pla
jmp c64.CHROUT jsr c64.CHROUT
ldx c64.SCRATCH_ZPREGX
rts
}} }}
} }
asmsub print_ub (ubyte value @ A) -> clobbers(A,X,Y) -> () { asmsub print_ub (ubyte value @ A) -> clobbers(A,Y) -> () {
; ---- print the ubyte in A in decimal form, without left padding 0s ; ---- print the ubyte in A in decimal form, without left padding 0s
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
jsr c64utils.ubyte2decimal jsr c64utils.ubyte2decimal
_print_byte_digits _print_byte_digits
pha pha
@ -754,13 +770,16 @@ _print_hundreds tya
_print_tens txa _print_tens txa
jsr c64.CHROUT jsr c64.CHROUT
pla pla
jmp c64.CHROUT jsr c64.CHROUT
ldx c64.SCRATCH_ZPREGX
rts
}} }}
} }
asmsub print_b (byte value @ A) -> clobbers(A,X,Y) -> () { asmsub print_b (byte value @ A) -> clobbers(A,Y) -> () {
; ---- print the byte in A in decimal form, without left padding 0s ; ---- print the byte in A in decimal form, without left padding 0s
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
pha pha
cmp #0 cmp #0
bpl + bpl +
@ -768,14 +787,17 @@ asmsub print_b (byte value @ A) -> clobbers(A,X,Y) -> () {
jsr c64.CHROUT jsr c64.CHROUT
+ pla + pla
jsr c64utils.byte2decimal jsr c64utils.byte2decimal
jmp print_ub._print_byte_digits jsr print_ub._print_byte_digits
ldx c64.SCRATCH_ZPREGX
rts
}} }}
} }
asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) -> () { asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,Y) -> () {
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) ; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
bcc + bcc +
pha pha
lda #'$' lda #'$'
@ -784,14 +806,17 @@ asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) ->
+ jsr c64utils.ubyte2hex + jsr c64utils.ubyte2hex
jsr c64.CHROUT jsr c64.CHROUT
tya tya
jmp c64.CHROUT jsr c64.CHROUT
ldx c64.SCRATCH_ZPREGX
rts
}} }}
} }
asmsub print_ubbin (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) ->() { asmsub print_ubbin (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,Y) ->() {
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well) ; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
%asm {{ %asm {{
stx c64.SCRATCH_ZPREGX
sta c64.SCRATCH_ZPB1 sta c64.SCRATCH_ZPB1
bcc + bcc +
lda #'%' lda #'%'
@ -804,12 +829,13 @@ asmsub print_ubbin (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) ->(
+ jsr c64.CHROUT + jsr c64.CHROUT
dey dey
bne - bne -
ldx c64.SCRATCH_ZPREGX
rts rts
}} }}
} }
asmsub print_uwbin (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) ->() { asmsub print_uwbin (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,Y) ->() {
; ---- print the uword in A/Y in binary form (if Carry is set, a radix prefix '%' is printed as well) ; ---- print the uword in A/Y in binary form (if Carry is set, a radix prefix '%' is printed as well)
%asm {{ %asm {{
pha pha
@ -822,7 +848,7 @@ asmsub print_uwbin (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) ->
} }
asmsub print_uwhex (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) -> () { asmsub print_uwhex (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,Y) -> () {
; ---- print the uword in A/Y in hexadecimal form (4 digits) ; ---- print the uword in A/Y in hexadecimal form (4 digits)
; (if Carry is set, a radix prefix '$' is printed as well) ; (if Carry is set, a radix prefix '$' is printed as well)
%asm {{ %asm {{
@ -836,7 +862,7 @@ asmsub print_uwhex (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) ->
} }
asmsub print_uw0 (uword value @ AY) -> clobbers(A,X,Y) -> () { asmsub print_uw0 (uword value @ AY) -> clobbers(A,Y) -> () {
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total) ; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
%asm {{ %asm {{
jsr c64utils.uword2decimal jsr c64utils.uword2decimal
@ -851,7 +877,7 @@ asmsub print_uw0 (uword value @ AY) -> clobbers(A,X,Y) -> () {
} }
asmsub print_uw (uword value @ AY) -> clobbers(A,X,Y) -> () { asmsub print_uw (uword value @ AY) -> clobbers(A,Y) -> () {
; ---- print the uword in A/Y in decimal form, without left padding 0s ; ---- print the uword in A/Y in decimal form, without left padding 0s
%asm {{ %asm {{
jsr c64utils.uword2decimal jsr c64utils.uword2decimal
@ -883,7 +909,7 @@ _pr_decimal
}} }}
} }
asmsub print_w (word value @ AY) -> clobbers(A,X,Y) -> () { asmsub print_w (word value @ AY) -> clobbers(A,Y) -> () {
; ---- print the (signed) word in A/Y in decimal form, without left padding 0s ; ---- print the (signed) word in A/Y in decimal form, without left padding 0s
%asm {{ %asm {{
cpy #0 cpy #0
@ -904,7 +930,7 @@ asmsub print_w (word value @ AY) -> clobbers(A,X,Y) -> () {
}} }}
} }
asmsub input_chars (uword buffer @ AY) -> clobbers(A, X) -> (ubyte @ Y) { asmsub input_chars (uword buffer @ AY) -> clobbers(A) -> (ubyte @ Y) {
; ---- Input a string (max. 80 chars) from the keyboard. Returns length in Y. ; ---- Input a string (max. 80 chars) from the keyboard. Returns length in Y.
; It assumes the keyboard is selected as I/O channel! ; It assumes the keyboard is selected as I/O channel!

View File

@ -88,7 +88,7 @@ private fun compileMain(args: Array<String>) {
} }
//println(" time2: $time2") //println(" time2: $time2")
val time3 = measureTimeMillis { val time3 = measureTimeMillis {
StatementReorderer(namespace, heap).process(moduleAst) // reorder statements to please the compiler later moduleAst.reorderStatements(namespace,heap) // reorder statements to please the compiler later
} }
//println(" time3: $time3") //println(" time3: $time3")
val time4 = measureTimeMillis { val time4 = measureTimeMillis {

View File

@ -692,7 +692,7 @@ class VarDecl(val type: VarDeclType,
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)" return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
} }
fun asDefaultValueDecl(): VarDecl { fun asDefaultValueDecl(parent: Node?): VarDecl {
val constValue = when(declaredDatatype) { val constValue = when(declaredDatatype) {
DataType.UBYTE -> LiteralValue(DataType.UBYTE, 0, position=position) DataType.UBYTE -> LiteralValue(DataType.UBYTE, 0, position=position)
DataType.BYTE -> LiteralValue(DataType.BYTE, 0, position=position) DataType.BYTE -> LiteralValue(DataType.BYTE, 0, position=position)
@ -701,7 +701,10 @@ class VarDecl(val type: VarDeclType,
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue=0.0, position=position) DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue=0.0, position=position)
else -> throw FatalAstException("can only set a default value for a numeric type") else -> throw FatalAstException("can only set a default value for a numeric type")
} }
return VarDecl(type, declaredDatatype, arrayspec, name, constValue, position) val decl = VarDecl(type, declaredDatatype, arrayspec, name, constValue, position)
if(parent!=null)
decl.linkParents(parent)
return decl
} }
} }

View File

@ -46,7 +46,7 @@ fun printWarning(msg: String, position: Position, detailInfo: String?=null) {
} }
class AstChecker(private val namespace: INameScope, private class AstChecker(private val namespace: INameScope,
private val compilerOptions: CompilationOptions, private val compilerOptions: CompilationOptions,
private val heap: HeapValues) : IAstProcessor { private val heap: HeapValues) : IAstProcessor {
private val checkResult: MutableList<AstException> = mutableListOf() private val checkResult: MutableList<AstException> = mutableListOf()

View File

@ -40,7 +40,7 @@ fun Module.checkIdentifiers(heap: HeapValues): MutableMap<String, IStatement> {
} }
class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor { private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
private val checkResult: MutableList<AstException> = mutableListOf() private val checkResult: MutableList<AstException> = mutableListOf()
var symbols: MutableMap<String, IStatement> = mutableMapOf() var symbols: MutableMap<String, IStatement> = mutableMapOf()

View File

@ -11,7 +11,7 @@ fun Module.checkRecursion(namespace: INameScope) {
} }
class DirectedGraph<VT> { private class DirectedGraph<VT> {
private val graph = mutableMapOf<VT, MutableSet<VT>>() private val graph = mutableMapOf<VT, MutableSet<VT>>()
private var uniqueVertices = mutableSetOf<VT>() private var uniqueVertices = mutableSetOf<VT>()
val numVertices : Int val numVertices : Int
@ -81,7 +81,7 @@ class DirectedGraph<VT> {
} }
class AstRecursionChecker(private val namespace: INameScope) : IAstProcessor { private class AstRecursionChecker(private val namespace: INameScope) : IAstProcessor {
private val callGraph = DirectedGraph<INameScope>() private val callGraph = DirectedGraph<INameScope>()
fun result(): List<AstException> { fun result(): List<AstException> {

View File

@ -13,7 +13,7 @@ fun Module.checkImportedValid() {
} }
class ImportedAstChecker : IAstProcessor { private class ImportedAstChecker : IAstProcessor {
private val checkResult: MutableList<SyntaxError> = mutableListOf() private val checkResult: MutableList<SyntaxError> = mutableListOf()
fun result(): List<SyntaxError> { fun result(): List<SyntaxError> {

View File

@ -2,7 +2,15 @@ package prog8.ast
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
class StatementReorderer(private val namespace: INameScope, private val heap: HeapValues): IAstProcessor { fun Module.reorderStatements(namespace: INameScope, heap: HeapValues) {
val initvalueCreator = VarInitValueCreator()
this.process(initvalueCreator)
val checker = StatementReorderer(namespace, heap)
this.process(checker)
}
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.
// - blocks are ordered by address, where blocks without address are put at the end. // - blocks are ordered by address, where blocks without address are put at the end.
@ -14,9 +22,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
// - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives. // - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives.
// - all other subroutines will be moved to the end of their block. // - all other subroutines will be moved to the end of their block.
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option") private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option")
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()
override fun process(module: Module) { override fun process(module: Module) {
super.process(module) super.process(module)
@ -37,14 +43,6 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
module.statements.removeAll(directives) module.statements.removeAll(directives)
module.statements.addAll(0, directives) module.statements.addAll(0, directives)
// add any new vardecls
// @todo doing it this late causes problems with namespace lookups elsewhere in sortConstantAssignments
for(decl in vardeclsToAdd)
for(d in decl.value) {
d.linkParents(decl.key as Node)
decl.key.statements.add(0, d)
}
sortConstantAssignments(module.statements) sortConstantAssignments(module.statements)
} }
@ -155,7 +153,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
} }
private fun sortConstantAssignmentSequence(first: Assignment, stmtIter: MutableIterator<IStatement>): Pair<List<Assignment>, IStatement?> { private fun sortConstantAssignmentSequence(first: Assignment, stmtIter: MutableIterator<IStatement>): Pair<List<Assignment>, IStatement?> {
val sequence= mutableListOf<Assignment>(first) val sequence= mutableListOf(first)
var trailing: IStatement? = null var trailing: IStatement? = null
while(stmtIter.hasNext()) { while(stmtIter.hasNext()) {
val next = stmtIter.next() val next = stmtIter.next()
@ -176,20 +174,40 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
return Pair(sorted, trailing) return Pair(sorted, trailing)
} }
}
private class VarInitValueCreator: IAstProcessor {
// Replace the var decl with an assignment and add a new vardecl with the default constant value.
// This makes sure the variables get reset to the intended value on a next run of the program.
// Variable decls without a value don't get this treatment, which means they retain the last
// value they had when restarting the program.
// This is done in a separate step because it interferes with the namespace lookup of symbols
// in other ast processors.
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()
override fun process(module: Module) {
super.process(module)
// add any new vardecls to the various scopes
for(decl in vardeclsToAdd)
for(d in decl.value) {
d.linkParents(decl.key as Node)
decl.key.statements.add(0, d)
}
}
override fun process(decl: VarDecl): IStatement { override fun process(decl: VarDecl): IStatement {
super.process(decl) super.process(decl)
if(decl.type!=VarDeclType.VAR || decl.value==null) if(decl.type!=VarDeclType.VAR || decl.value==null)
return decl return decl
// Replace the var decl with an assignment and add a new vardecl with the default constant value.
// This makes sure the variables get reset to the intended value on a next run of the program.
// Variable decls without a value don't get this treatment, which means they retain the last
// value they had when restarting the program.
if(decl.datatype in NumericDatatypes) { if(decl.datatype in NumericDatatypes) {
val scope = decl.definingScope() val scope = decl.definingScope()
if(scope !in vardeclsToAdd) if(scope !in vardeclsToAdd)
vardeclsToAdd[scope] = mutableListOf() vardeclsToAdd[scope] = mutableListOf()
vardeclsToAdd[scope]!!.add(decl.asDefaultValueDecl()) vardeclsToAdd[scope]!!.add(decl.asDefaultValueDecl(null))
val declvalue = decl.value!! val declvalue = decl.value!!
val value = val value =
if(declvalue is LiteralValue) { if(declvalue is LiteralValue) {
@ -207,4 +225,5 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
} }
return decl return decl
} }
} }