mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	Merge branch 'master' into structs
# Conflicts: # compiler/test/ast/TestVariousCompilerAst.kt
This commit is contained in:
		@@ -145,8 +145,6 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // re-initialize memory areas with final compilationOptions
 | 
					                // re-initialize memory areas with final compilationOptions
 | 
				
			||||||
                compilationOptions.compTarget.initializeMemoryAreas(compilationOptions)
 | 
					                compilationOptions.compTarget.initializeMemoryAreas(compilationOptions)
 | 
				
			||||||
                program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
 | 
					 | 
				
			||||||
                args.errors.report()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(args.printAst1) {
 | 
					                if(args.printAst1) {
 | 
				
			||||||
                    println("\n*********** COMPILER AST *************")
 | 
					                    println("\n*********** COMPILER AST *************")
 | 
				
			||||||
@@ -495,8 +493,21 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt
 | 
				
			|||||||
    program.verifyFunctionArgTypes(errors, compilerOptions)
 | 
					    program.verifyFunctionArgTypes(errors, compilerOptions)
 | 
				
			||||||
    errors.report()
 | 
					    errors.report()
 | 
				
			||||||
    program.moveMainBlockAsFirst(compilerOptions.compTarget)
 | 
					    program.moveMainBlockAsFirst(compilerOptions.compTarget)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val fixer = BeforeAsmAstChanger(program, compilerOptions, errors)
 | 
				
			||||||
 | 
					    fixer.visit(program)
 | 
				
			||||||
 | 
					    while (errors.noErrors() && fixer.applyModifications() > 0) {
 | 
				
			||||||
 | 
					        fixer.visit(program)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    program.checkValid(errors, compilerOptions)          // check if final tree is still valid
 | 
					    program.checkValid(errors, compilerOptions)          // check if final tree is still valid
 | 
				
			||||||
    errors.report()
 | 
					    errors.report()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val cleaner = BeforeAsmTypecastCleaner(program, errors)
 | 
				
			||||||
 | 
					    cleaner.visit(program)
 | 
				
			||||||
 | 
					    while (errors.noErrors() && cleaner.applyModifications() > 0) {
 | 
				
			||||||
 | 
					        cleaner.visit(program)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private fun createAssemblyAndAssemble(program: PtProgram,
 | 
					private fun createAssemblyAndAssemble(program: PtProgram,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,19 +20,6 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
 | 
				
			|||||||
    checker.visit(this)
 | 
					    checker.visit(this)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter) {
 | 
					 | 
				
			||||||
    val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
 | 
					 | 
				
			||||||
    fixer.visit(this)
 | 
					 | 
				
			||||||
    while (errors.noErrors() && fixer.applyModifications() > 0) {
 | 
					 | 
				
			||||||
        fixer.visit(this)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    val cleaner = BeforeAsmTypecastCleaner(this, errors)
 | 
					 | 
				
			||||||
    cleaner.visit(this)
 | 
					 | 
				
			||||||
    while (errors.noErrors() && cleaner.applyModifications() > 0) {
 | 
					 | 
				
			||||||
        cleaner.visit(this)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal fun Program.reorderStatements(errors: IErrorReporter) {
 | 
					internal fun Program.reorderStatements(errors: IErrorReporter) {
 | 
				
			||||||
    val reorder = StatementReorderer(this, errors)
 | 
					    val reorder = StatementReorderer(this, errors)
 | 
				
			||||||
    reorder.visit(this)
 | 
					    reorder.visit(this)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package prog8.compiler.astprocessing
 | 
				
			|||||||
import prog8.ast.IStatementContainer
 | 
					import prog8.ast.IStatementContainer
 | 
				
			||||||
import prog8.ast.Node
 | 
					import prog8.ast.Node
 | 
				
			||||||
import prog8.ast.Program
 | 
					import prog8.ast.Program
 | 
				
			||||||
 | 
					import prog8.ast.defaultZero
 | 
				
			||||||
import prog8.ast.expressions.BinaryExpression
 | 
					import prog8.ast.expressions.BinaryExpression
 | 
				
			||||||
import prog8.ast.expressions.NumericLiteral
 | 
					import prog8.ast.expressions.NumericLiteral
 | 
				
			||||||
import prog8.ast.statements.*
 | 
					import prog8.ast.statements.*
 | 
				
			||||||
@@ -51,19 +52,28 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
 | 
				
			|||||||
        // and if an assembly block doesn't contain a rts/rti.
 | 
					        // and if an assembly block doesn't contain a rts/rti.
 | 
				
			||||||
        if (!subroutine.isAsmSubroutine) {
 | 
					        if (!subroutine.isAsmSubroutine) {
 | 
				
			||||||
            if(subroutine.isEmpty()) {
 | 
					            if(subroutine.isEmpty()) {
 | 
				
			||||||
 | 
					                if(subroutine.returntypes.isNotEmpty())
 | 
				
			||||||
 | 
					                    errors.err("subroutine is missing a return statement with value(s)", subroutine.position)
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
                    val returnStmt = Return(arrayOf(), subroutine.position)
 | 
					                    val returnStmt = Return(arrayOf(), subroutine.position)
 | 
				
			||||||
                    mods += IAstModification.InsertLast(returnStmt, subroutine)
 | 
					                    mods += IAstModification.InsertLast(returnStmt, subroutine)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                val last = subroutine.statements.last()
 | 
					                val last = subroutine.statements.last()
 | 
				
			||||||
                if((last !is InlineAssembly || !last.hasReturnOrRts()) && last !is Return) {
 | 
					                if((last !is InlineAssembly || !last.hasReturnOrRts()) && last !is Return) {
 | 
				
			||||||
                    val lastStatement = subroutine.statements.reversed().firstOrNull { it !is Subroutine }
 | 
					                    val lastStatement = subroutine.statements.reversed().firstOrNull { it !is Subroutine }
 | 
				
			||||||
                    if(lastStatement !is Return) {
 | 
					                    if(lastStatement !is Return) {
 | 
				
			||||||
 | 
					                        if(subroutine.returntypes.isNotEmpty()) {
 | 
				
			||||||
 | 
					                            // .... we cannot return this as an error, because that also breaks legitimate cases where the return is done from within a nested scope somewhere
 | 
				
			||||||
 | 
					                            // errors.err("subroutine is missing a return statement with value(s)", subroutine.position)
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
                            val returnStmt = Return(arrayOf(), subroutine.position)
 | 
					                            val returnStmt = Return(arrayOf(), subroutine.position)
 | 
				
			||||||
                            mods += IAstModification.InsertLast(returnStmt, subroutine)
 | 
					                            mods += IAstModification.InsertLast(returnStmt, subroutine)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // precede a subroutine with a return to avoid falling through into the subroutine from code above it
 | 
					        // precede a subroutine with a return to avoid falling through into the subroutine from code above it
 | 
				
			||||||
        val outerScope = subroutine.definingScope
 | 
					        val outerScope = subroutine.definingScope
 | 
				
			||||||
@@ -76,9 +86,21 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
 | 
				
			|||||||
                && prevStmt !is Subroutine
 | 
					                && prevStmt !is Subroutine
 | 
				
			||||||
                && prevStmt !is Return
 | 
					                && prevStmt !is Return
 | 
				
			||||||
            ) {
 | 
					            ) {
 | 
				
			||||||
                val returnStmt = Return(arrayOf(), subroutine.position)
 | 
					                if(!subroutine.inline) {
 | 
				
			||||||
 | 
					                    if(outerScope is Subroutine && outerScope.returntypes.isNotEmpty()) {
 | 
				
			||||||
 | 
					                        if(outerScope.returntypes.size>1 || !outerScope.returntypes[0].isNumericOrBool) {
 | 
				
			||||||
 | 
					                            errors.err("subroutine is missing a return statement to avoid falling through into nested subroutine", outerStatements[subroutineStmtIdx-1].position)
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            val zero = defaultZero(outerScope.returntypes[0].base, Position.DUMMY)
 | 
				
			||||||
 | 
					                            val returnStmt = Return(arrayOf(zero), outerStatements[subroutineStmtIdx - 1].position)
 | 
				
			||||||
                            mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope)
 | 
					                            mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        val returnStmt = Return(arrayOf(), outerStatements[subroutineStmtIdx - 1].position)
 | 
				
			||||||
 | 
					                        mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!subroutine.inline) {
 | 
					        if (!subroutine.inline) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)
 | 
					        val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)
 | 
				
			||||||
        val statements = result!!.compilerAst.entrypoint.statements
 | 
					        val statements = result!!.compilerAst.entrypoint.statements
 | 
				
			||||||
        statements.size shouldBe 7
 | 
					        statements.size shouldBe 8
 | 
				
			||||||
        val a1 = statements[2] as Assignment
 | 
					        val a1 = statements[2] as Assignment
 | 
				
			||||||
        val a2 = statements[3] as Assignment
 | 
					        val a2 = statements[3] as Assignment
 | 
				
			||||||
        val a3 = statements[4] as Assignment
 | 
					        val a3 = statements[4] as Assignment
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -225,7 +225,7 @@ other {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val assignFF = result.compilerAst.entrypoint.statements.last() as Assignment
 | 
					        val assignFF = result.compilerAst.entrypoint.statements.dropLast(1).last() as Assignment
 | 
				
			||||||
        assignFF.isAugmentable shouldBe true
 | 
					        assignFF.isAugmentable shouldBe true
 | 
				
			||||||
        assignFF.target.identifier!!.nameInSource shouldBe listOf("ff")
 | 
					        assignFF.target.identifier!!.nameInSource shouldBe listOf("ff")
 | 
				
			||||||
        val value = assignFF.value as BinaryExpression
 | 
					        val value = assignFF.value as BinaryExpression
 | 
				
			||||||
@@ -252,7 +252,7 @@ other {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        result.compilerAst.entrypoint.statements.size shouldBe 7
 | 
					        result.compilerAst.entrypoint.statements.size shouldBe 8
 | 
				
			||||||
        val alldecls = result.compilerAst.entrypoint.allDefinedSymbols.toList()
 | 
					        val alldecls = result.compilerAst.entrypoint.allDefinedSymbols.toList()
 | 
				
			||||||
        alldecls.map { it.first } shouldBe listOf("unused_but_shared", "usedvar_only_written", "usedvar")
 | 
					        alldecls.map { it.first } shouldBe listOf("unused_but_shared", "usedvar_only_written", "usedvar")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -276,12 +276,12 @@ other {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        result.compilerAst.entrypoint.statements.size shouldBe 3
 | 
					        result.compilerAst.entrypoint.statements.size shouldBe 4
 | 
				
			||||||
        val ifstmt = result.compilerAst.entrypoint.statements[0] as IfElse
 | 
					        val ifstmt = result.compilerAst.entrypoint.statements[0] as IfElse
 | 
				
			||||||
        ifstmt.truepart.statements.size shouldBe 1
 | 
					        ifstmt.truepart.statements.size shouldBe 1
 | 
				
			||||||
        (ifstmt.truepart.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0")
 | 
					        (ifstmt.truepart.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0")
 | 
				
			||||||
        val func2 = result.compilerAst.entrypoint.statements[2] as Subroutine
 | 
					        val func2 = result.compilerAst.entrypoint.statements.last() as Subroutine
 | 
				
			||||||
        func2.statements.size shouldBe 2
 | 
					        func2.statements.size shouldBe 3
 | 
				
			||||||
        (func2.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0")
 | 
					        (func2.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -312,7 +312,7 @@ main {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        result.compilerAst.entrypoint.statements.size shouldBe 0
 | 
					        result.compilerAst.entrypoint.statements.size shouldBe 1
 | 
				
			||||||
        result.compilerAst.entrypoint.definingScope.statements.size shouldBe 1
 | 
					        result.compilerAst.entrypoint.definingScope.statements.size shouldBe 1
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -350,7 +350,7 @@ main {
 | 
				
			|||||||
        z6 = z1 - 5
 | 
					        z6 = z1 - 5
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        val statements = result.compilerAst.entrypoint.statements
 | 
					        val statements = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        statements.size shouldBe 12
 | 
					        statements.size shouldBe 13
 | 
				
			||||||
        val z1decl = statements[0] as VarDecl
 | 
					        val z1decl = statements[0] as VarDecl
 | 
				
			||||||
        val z1init = statements[1] as Assignment
 | 
					        val z1init = statements[1] as Assignment
 | 
				
			||||||
        val z2decl = statements[2] as VarDecl
 | 
					        val z2decl = statements[2] as VarDecl
 | 
				
			||||||
@@ -395,8 +395,8 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val assign=stmts.last() as Assignment
 | 
					        val assign=stmts[4] as Assignment
 | 
				
			||||||
        (assign.target.memoryAddress?.addressExpression as IdentifierReference).nameInSource shouldBe listOf("aa")
 | 
					        (assign.target.memoryAddress?.addressExpression as IdentifierReference).nameInSource shouldBe listOf("aa")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -412,8 +412,8 @@ main {
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val assign=stmts.last() as Assignment
 | 
					        val assign=stmts[4] as Assignment
 | 
				
			||||||
        (assign.target.memoryAddress?.addressExpression as IdentifierReference).nameInSource shouldBe listOf("aa")
 | 
					        (assign.target.memoryAddress?.addressExpression as IdentifierReference).nameInSource shouldBe listOf("aa")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -431,7 +431,7 @@ main {
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 10
 | 
					        stmts.size shouldBe 11
 | 
				
			||||||
        stmts.filterIsInstance<VarDecl>().size shouldBe 5
 | 
					        stmts.filterIsInstance<VarDecl>().size shouldBe 5
 | 
				
			||||||
        stmts.filterIsInstance<Assignment>().size shouldBe 5
 | 
					        stmts.filterIsInstance<Assignment>().size shouldBe 5
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -508,7 +508,7 @@ main {
 | 
				
			|||||||
        xx += 6
 | 
					        xx += 6
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 6
 | 
					        stmts.size shouldBe 7
 | 
				
			||||||
        stmts.filterIsInstance<VarDecl>().size shouldBe 3
 | 
					        stmts.filterIsInstance<VarDecl>().size shouldBe 3
 | 
				
			||||||
        stmts.filterIsInstance<Assignment>().size shouldBe 3
 | 
					        stmts.filterIsInstance<Assignment>().size shouldBe 3
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -537,13 +537,13 @@ main {
 | 
				
			|||||||
        xx += 10
 | 
					        xx += 10
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 7
 | 
					        stmts.size shouldBe 8
 | 
				
			||||||
        stmts.filterIsInstance<VarDecl>().size shouldBe 2
 | 
					        stmts.filterIsInstance<VarDecl>().size shouldBe 2
 | 
				
			||||||
        stmts.filterIsInstance<Assignment>().size shouldBe 5
 | 
					        stmts.filterIsInstance<Assignment>().size shouldBe 5
 | 
				
			||||||
        val assignXX1 = stmts[1] as Assignment
 | 
					        val assignXX1 = stmts[1] as Assignment
 | 
				
			||||||
        assignXX1.target.identifier!!.nameInSource shouldBe listOf("xx")
 | 
					        assignXX1.target.identifier!!.nameInSource shouldBe listOf("xx")
 | 
				
			||||||
        assignXX1.value shouldBe NumericLiteral(BaseDataType.UWORD, 20.0, Position.DUMMY)
 | 
					        assignXX1.value shouldBe NumericLiteral(BaseDataType.UWORD, 20.0, Position.DUMMY)
 | 
				
			||||||
        val assignXX2 = stmts.last() as Assignment
 | 
					        val assignXX2 = stmts[6] as Assignment
 | 
				
			||||||
        assignXX2.target.identifier!!.nameInSource shouldBe listOf("xx")
 | 
					        assignXX2.target.identifier!!.nameInSource shouldBe listOf("xx")
 | 
				
			||||||
        val xxValue = assignXX2.value as BinaryExpression
 | 
					        val xxValue = assignXX2.value as BinaryExpression
 | 
				
			||||||
        xxValue.operator shouldBe "+"
 | 
					        xxValue.operator shouldBe "+"
 | 
				
			||||||
@@ -577,7 +577,7 @@ main {
 | 
				
			|||||||
            thingy++
 | 
					            thingy++
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 6
 | 
					        stmts.size shouldBe 7
 | 
				
			||||||
        val ifStmt = stmts[5] as IfElse
 | 
					        val ifStmt = stmts[5] as IfElse
 | 
				
			||||||
        val containment = ifStmt.condition as ContainmentCheck
 | 
					        val containment = ifStmt.condition as ContainmentCheck
 | 
				
			||||||
        (containment.element as IdentifierReference).nameInSource shouldBe listOf("source")
 | 
					        (containment.element as IdentifierReference).nameInSource shouldBe listOf("source")
 | 
				
			||||||
@@ -612,7 +612,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val ifStmt = stmts[4] as IfElse
 | 
					        val ifStmt = stmts[4] as IfElse
 | 
				
			||||||
        val containment = ifStmt.condition as ContainmentCheck
 | 
					        val containment = ifStmt.condition as ContainmentCheck
 | 
				
			||||||
        (containment.element as IdentifierReference).nameInSource shouldBe listOf("source")
 | 
					        (containment.element as IdentifierReference).nameInSource shouldBe listOf("source")
 | 
				
			||||||
@@ -634,7 +634,7 @@ main {
 | 
				
			|||||||
        }"""
 | 
					        }"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val ifStmt = stmts[4] as IfElse
 | 
					        val ifStmt = stmts[4] as IfElse
 | 
				
			||||||
        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
					        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -652,7 +652,7 @@ main {
 | 
				
			|||||||
        }"""
 | 
					        }"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val ifStmt = stmts[4] as IfElse
 | 
					        val ifStmt = stmts[4] as IfElse
 | 
				
			||||||
        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
					        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -670,7 +670,7 @@ main {
 | 
				
			|||||||
        }"""
 | 
					        }"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 5
 | 
					        stmts.size shouldBe 6
 | 
				
			||||||
        val ifStmt = stmts[4] as IfElse
 | 
					        val ifStmt = stmts[4] as IfElse
 | 
				
			||||||
        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
					        ifStmt.condition shouldBe instanceOf<BinaryExpression>()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -687,7 +687,7 @@ main {
 | 
				
			|||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 3
 | 
					        stmts.size shouldBe 4
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("repeated assignments to IO register should remain") {
 | 
					    test("repeated assignments to IO register should remain") {
 | 
				
			||||||
@@ -828,7 +828,7 @@ main {
 | 
				
			|||||||
        val errors = ErrorReporterForTests()
 | 
					        val errors = ErrorReporterForTests()
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false, errors = errors)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false, errors = errors)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 4
 | 
					        st.size shouldBe 5
 | 
				
			||||||
        val xxConst = st[0] as VarDecl
 | 
					        val xxConst = st[0] as VarDecl
 | 
				
			||||||
        xxConst.type shouldBe VarDeclType.CONST
 | 
					        xxConst.type shouldBe VarDeclType.CONST
 | 
				
			||||||
        xxConst.name shouldBe "xx"
 | 
					        xxConst.name shouldBe "xx"
 | 
				
			||||||
@@ -872,7 +872,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 8
 | 
					        st.size shouldBe 9
 | 
				
			||||||
        val if1c = (st[4] as IfElse).condition as PrefixExpression
 | 
					        val if1c = (st[4] as IfElse).condition as PrefixExpression
 | 
				
			||||||
        val if2c = (st[5] as IfElse).condition as PrefixExpression
 | 
					        val if2c = (st[5] as IfElse).condition as PrefixExpression
 | 
				
			||||||
        val if3c = (st[6] as IfElse).condition as PrefixExpression
 | 
					        val if3c = (st[6] as IfElse).condition as PrefixExpression
 | 
				
			||||||
@@ -915,7 +915,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 12
 | 
					        st.size shouldBe 13
 | 
				
			||||||
        val if1 = st[4] as IfElse
 | 
					        val if1 = st[4] as IfElse
 | 
				
			||||||
        val if2 = st[5] as IfElse
 | 
					        val if2 = st[5] as IfElse
 | 
				
			||||||
        val if3 = st[6] as IfElse
 | 
					        val if3 = st[6] as IfElse
 | 
				
			||||||
@@ -970,7 +970,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 17
 | 
					        st.size shouldBe 18
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val answerValue = (st[3] as Assignment).value
 | 
					        val answerValue = (st[3] as Assignment).value
 | 
				
			||||||
        answerValue shouldBe NumericLiteral(BaseDataType.UWORD, 0.0, Position.DUMMY)
 | 
					        answerValue shouldBe NumericLiteral(BaseDataType.UWORD, 0.0, Position.DUMMY)
 | 
				
			||||||
@@ -1019,7 +1019,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 3
 | 
					        st.size shouldBe 4
 | 
				
			||||||
        val ifCond1 = (st[0] as IfElse).condition as BinaryExpression
 | 
					        val ifCond1 = (st[0] as IfElse).condition as BinaryExpression
 | 
				
			||||||
        val ifCond2 = (st[1] as IfElse).condition as BinaryExpression
 | 
					        val ifCond2 = (st[1] as IfElse).condition as BinaryExpression
 | 
				
			||||||
        val ifCond3 = (st[2] as IfElse).condition as BinaryExpression
 | 
					        val ifCond3 = (st[2] as IfElse).condition as BinaryExpression
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -511,7 +511,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 9
 | 
					        st.size shouldBe 10
 | 
				
			||||||
        (st[0] as VarDecl).name shouldBe "l1"
 | 
					        (st[0] as VarDecl).name shouldBe "l1"
 | 
				
			||||||
        (st[2] as VarDecl).name shouldBe "l2"
 | 
					        (st[2] as VarDecl).name shouldBe "l2"
 | 
				
			||||||
        st[4] shouldBe instanceOf<Assignment>()
 | 
					        st[4] shouldBe instanceOf<Assignment>()
 | 
				
			||||||
@@ -543,7 +543,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 10
 | 
					        st.size shouldBe 11
 | 
				
			||||||
        val dr0 = (st[2] as Assignment).value as PtrDereference
 | 
					        val dr0 = (st[2] as Assignment).value as PtrDereference
 | 
				
			||||||
        val dr1 = (st[3] as Assignment).target.pointerDereference!!
 | 
					        val dr1 = (st[3] as Assignment).target.pointerDereference!!
 | 
				
			||||||
        val dr2 = (st[4] as Assignment).value as PtrDereference
 | 
					        val dr2 = (st[4] as Assignment).value as PtrDereference
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,9 @@ class TestSubroutines: FunSpec({
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                asmsub asmfunc(str thing @AY) {
 | 
					                asmsub asmfunc(str thing @AY) {
 | 
				
			||||||
 | 
					                    %asm {{
 | 
				
			||||||
 | 
					                        rts
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sub func(str thing) {
 | 
					                sub func(str thing) {
 | 
				
			||||||
@@ -67,12 +70,12 @@ class TestSubroutines: FunSpec({
 | 
				
			|||||||
        val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
 | 
					        val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
 | 
				
			||||||
        val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
 | 
					        val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
 | 
				
			||||||
        asmfunc.isAsmSubroutine shouldBe true
 | 
					        asmfunc.isAsmSubroutine shouldBe true
 | 
				
			||||||
        asmfunc.statements.isEmpty() shouldBe true
 | 
					        asmfunc.statements.size shouldBe 1
 | 
				
			||||||
        func.isAsmSubroutine shouldBe false
 | 
					        func.isAsmSubroutine shouldBe false
 | 
				
			||||||
        withClue("str param for subroutines should be changed into UWORD") {
 | 
					        withClue("str param for subroutines should be changed into UWORD") {
 | 
				
			||||||
            asmfunc.parameters.single().type shouldBe DataType.UWORD
 | 
					            asmfunc.parameters.single().type shouldBe DataType.UWORD
 | 
				
			||||||
            func.parameters.single().type shouldBe DataType.UWORD
 | 
					            func.parameters.single().type shouldBe DataType.UWORD
 | 
				
			||||||
            func.statements.size shouldBe 4
 | 
					            func.statements.size shouldBe 5
 | 
				
			||||||
            val paramvar = func.statements[0] as VarDecl
 | 
					            val paramvar = func.statements[0] as VarDecl
 | 
				
			||||||
            paramvar.name shouldBe "thing"
 | 
					            paramvar.name shouldBe "thing"
 | 
				
			||||||
            paramvar.datatype shouldBe DataType.UWORD
 | 
					            paramvar.datatype shouldBe DataType.UWORD
 | 
				
			||||||
@@ -174,6 +177,9 @@ class TestSubroutines: FunSpec({
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                asmsub asmfunc(ubyte[] thing @AY) {
 | 
					                asmsub asmfunc(ubyte[] thing @AY) {
 | 
				
			||||||
 | 
					                    %asm {{
 | 
				
			||||||
 | 
					                        rts
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sub func(ubyte[] thing) {
 | 
					                sub func(ubyte[] thing) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,7 @@ class TestTypecasts: FunSpec({
 | 
				
			|||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 6
 | 
					        stmts.size shouldBe 7
 | 
				
			||||||
        val expr = (stmts[5] as Assignment).value as BinaryExpression
 | 
					        val expr = (stmts[5] as Assignment).value as BinaryExpression
 | 
				
			||||||
        expr.operator shouldBe "and"
 | 
					        expr.operator shouldBe "and"
 | 
				
			||||||
        (expr.left as IdentifierReference).nameInSource shouldBe listOf("bb2")  // no cast
 | 
					        (expr.left as IdentifierReference).nameInSource shouldBe listOf("bb2")  // no cast
 | 
				
			||||||
@@ -158,7 +158,7 @@ main {
 | 
				
			|||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 7
 | 
					        stmts.size shouldBe 8
 | 
				
			||||||
        val fcall1 = ((stmts[4] as Assignment).value as IFunctionCall)
 | 
					        val fcall1 = ((stmts[4] as Assignment).value as IFunctionCall)
 | 
				
			||||||
        fcall1.args[0] shouldBe NumericLiteral(BaseDataType.BOOL, 1.0, Position.DUMMY)
 | 
					        fcall1.args[0] shouldBe NumericLiteral(BaseDataType.BOOL, 1.0, Position.DUMMY)
 | 
				
			||||||
        fcall1.args[1] shouldBe NumericLiteral(BaseDataType.BOOL, 0.0, Position.DUMMY)
 | 
					        fcall1.args[1] shouldBe NumericLiteral(BaseDataType.BOOL, 0.0, Position.DUMMY)
 | 
				
			||||||
@@ -210,7 +210,7 @@ main {
 | 
				
			|||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 3
 | 
					        stmts.size shouldBe 4
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("ubyte to word casts") {
 | 
					    test("ubyte to word casts") {
 | 
				
			||||||
@@ -225,7 +225,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result = compileText(C64Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 4
 | 
					        stmts.size shouldBe 5
 | 
				
			||||||
        val assign1tc = (stmts[2] as Assignment).value as TypecastExpression
 | 
					        val assign1tc = (stmts[2] as Assignment).value as TypecastExpression
 | 
				
			||||||
        val assign2tc = (stmts[3] as Assignment).value as TypecastExpression
 | 
					        val assign2tc = (stmts[3] as Assignment).value as TypecastExpression
 | 
				
			||||||
        assign1tc.type shouldBe DataType.WORD
 | 
					        assign1tc.type shouldBe DataType.WORD
 | 
				
			||||||
@@ -256,7 +256,7 @@ main {
 | 
				
			|||||||
            }"""
 | 
					            }"""
 | 
				
			||||||
        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 8
 | 
					        stmts.size shouldBe 9
 | 
				
			||||||
        val arg1 = (stmts[2] as IFunctionCall).args.single()
 | 
					        val arg1 = (stmts[2] as IFunctionCall).args.single()
 | 
				
			||||||
        val arg2 = (stmts[3] as IFunctionCall).args.single()
 | 
					        val arg2 = (stmts[3] as IFunctionCall).args.single()
 | 
				
			||||||
        val arg3 = (stmts[4] as IFunctionCall).args.single()
 | 
					        val arg3 = (stmts[4] as IFunctionCall).args.single()
 | 
				
			||||||
@@ -894,7 +894,7 @@ main {
 | 
				
			|||||||
        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val program = result.compilerAst
 | 
					        val program = result.compilerAst
 | 
				
			||||||
        val st = program.entrypoint.statements
 | 
					        val st = program.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 1
 | 
					        st.size shouldBe 2
 | 
				
			||||||
        val assign = st[0] as Assignment
 | 
					        val assign = st[0] as Assignment
 | 
				
			||||||
        assign.target.inferType(program).getOrUndef().base shouldBe BaseDataType.BYTE
 | 
					        assign.target.inferType(program).getOrUndef().base shouldBe BaseDataType.BYTE
 | 
				
			||||||
        val ifexpr = assign.value as IfExpression
 | 
					        val ifexpr = assign.value as IfExpression
 | 
				
			||||||
@@ -919,7 +919,7 @@ main {
 | 
				
			|||||||
        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val program = result.compilerAst
 | 
					        val program = result.compilerAst
 | 
				
			||||||
        val st = program.entrypoint.statements
 | 
					        val st = program.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 6
 | 
					        st.size shouldBe 7
 | 
				
			||||||
        val v1 = (st[2] as Assignment).value as BinaryExpression
 | 
					        val v1 = (st[2] as Assignment).value as BinaryExpression
 | 
				
			||||||
        v1.operator shouldBe "+"
 | 
					        v1.operator shouldBe "+"
 | 
				
			||||||
        (v1.left as IdentifierReference).nameInSource shouldBe listOf("cx16", "r0")
 | 
					        (v1.left as IdentifierReference).nameInSource shouldBe listOf("cx16", "r0")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,7 @@ class TestConst: FunSpec({
 | 
				
			|||||||
//        cx16.r5s = llw - 1899
 | 
					//        cx16.r5s = llw - 1899
 | 
				
			||||||
//        cx16.r7s = llw + 99
 | 
					//        cx16.r7s = llw + 99
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 9
 | 
					        stmts.size shouldBe 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val addR0value = (stmts[4] as Assignment).value
 | 
					        val addR0value = (stmts[4] as Assignment).value
 | 
				
			||||||
        val binexpr0 = addR0value as BinaryExpression
 | 
					        val binexpr0 = addR0value as BinaryExpression
 | 
				
			||||||
@@ -109,7 +109,7 @@ class TestConst: FunSpec({
 | 
				
			|||||||
//        result++
 | 
					//        result++
 | 
				
			||||||
//        result = llw * 18.0
 | 
					//        result = llw * 18.0
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 12
 | 
					        stmts.size shouldBe 13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val mulR0Value = (stmts[3] as Assignment).value
 | 
					        val mulR0Value = (stmts[3] as Assignment).value
 | 
				
			||||||
        val binexpr0 = mulR0Value as BinaryExpression
 | 
					        val binexpr0 = mulR0Value as BinaryExpression
 | 
				
			||||||
@@ -157,7 +157,7 @@ class TestConst: FunSpec({
 | 
				
			|||||||
//        cx16.r3s = llw /2 *10
 | 
					//        cx16.r3s = llw /2 *10
 | 
				
			||||||
//        cx16.r4s = llw *90 /5
 | 
					//        cx16.r4s = llw *90 /5
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 7
 | 
					        stmts.size shouldBe 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val mulR0Value = (stmts[2] as Assignment).value
 | 
					        val mulR0Value = (stmts[2] as Assignment).value
 | 
				
			||||||
        val binexpr0 = mulR0Value as BinaryExpression
 | 
					        val binexpr0 = mulR0Value as BinaryExpression
 | 
				
			||||||
@@ -251,7 +251,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), true, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 5
 | 
					        st.size shouldBe 6
 | 
				
			||||||
        (st[0] as VarDecl).type shouldBe VarDeclType.CONST
 | 
					        (st[0] as VarDecl).type shouldBe VarDeclType.CONST
 | 
				
			||||||
        val assignv1 = (st[2] as Assignment).value
 | 
					        val assignv1 = (st[2] as Assignment).value
 | 
				
			||||||
        val assignv2 = (st[4] as Assignment).value
 | 
					        val assignv2 = (st[4] as Assignment).value
 | 
				
			||||||
@@ -274,7 +274,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 6
 | 
					        st.size shouldBe 7
 | 
				
			||||||
        ((st[0] as VarDecl).value as NumericLiteral).number shouldBe 0x2000
 | 
					        ((st[0] as VarDecl).value as NumericLiteral).number shouldBe 0x2000
 | 
				
			||||||
        ((st[1] as VarDecl).value as NumericLiteral).number shouldBe 0x9e00
 | 
					        ((st[1] as VarDecl).value as NumericLiteral).number shouldBe 0x9e00
 | 
				
			||||||
        ((st[2] as VarDecl).value as NumericLiteral).number shouldBe 0x9e00+2*30
 | 
					        ((st[2] as VarDecl).value as NumericLiteral).number shouldBe 0x9e00+2*30
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -907,7 +907,7 @@ class TestProg8Parser: FunSpec( {
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(), false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val start = result.compilerAst.entrypoint
 | 
					        val start = result.compilerAst.entrypoint
 | 
				
			||||||
        val containmentChecks = start.statements.takeLast(4)
 | 
					        val containmentChecks = start.statements.takeLast(5)
 | 
				
			||||||
        (containmentChecks[0] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
 | 
					        (containmentChecks[0] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
 | 
				
			||||||
        (containmentChecks[1] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
 | 
					        (containmentChecks[1] as IfElse).condition shouldBe instanceOf<ContainmentCheck>()
 | 
				
			||||||
        (containmentChecks[2] as Assignment).value shouldBe instanceOf<ContainmentCheck>()
 | 
					        (containmentChecks[2] as Assignment).value shouldBe instanceOf<ContainmentCheck>()
 | 
				
			||||||
@@ -948,7 +948,7 @@ class TestProg8Parser: FunSpec( {
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(C64Target(),  false, text, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(C64Target(),  false, text, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val stmt = result.compilerAst.entrypoint.statements
 | 
					        val stmt = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmt.size shouldBe 12
 | 
					        stmt.size shouldBe 13
 | 
				
			||||||
        val var1 = stmt[0] as VarDecl
 | 
					        val var1 = stmt[0] as VarDecl
 | 
				
			||||||
        var1.sharedWithAsm shouldBe true
 | 
					        var1.sharedWithAsm shouldBe true
 | 
				
			||||||
        var1.zeropage shouldBe ZeropageWish.REQUIRE_ZEROPAGE
 | 
					        var1.zeropage shouldBe ZeropageWish.REQUIRE_ZEROPAGE
 | 
				
			||||||
@@ -998,7 +998,7 @@ main {
 | 
				
			|||||||
    ; curly braces without newline
 | 
					    ; curly braces without newline
 | 
				
			||||||
    sub start () { foo() derp() other() }
 | 
					    sub start () { foo() derp() other() }
 | 
				
			||||||
    sub foo() { cx16.r0++ }
 | 
					    sub foo() { cx16.r0++ }
 | 
				
			||||||
    asmsub derp() { %asm {{ nop }} %ir {{ load.b r0,1 }} }
 | 
					    asmsub derp() { %asm {{ nop rts }} %ir {{ load.b r0,1 return }} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ; curly braces on next line
 | 
					    ; curly braces on next line
 | 
				
			||||||
    sub other()
 | 
					    sub other()
 | 
				
			||||||
@@ -1014,6 +1014,7 @@ main {
 | 
				
			|||||||
        {{
 | 
					        {{
 | 
				
			||||||
            txa
 | 
					            txa
 | 
				
			||||||
            tay
 | 
					            tay
 | 
				
			||||||
 | 
					            rts
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1022,6 +1023,7 @@ main {
 | 
				
			|||||||
        %ir
 | 
					        %ir
 | 
				
			||||||
        {{
 | 
					        {{
 | 
				
			||||||
            load.b r0,1
 | 
					            load.b r0,1
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}"""
 | 
					}"""
 | 
				
			||||||
@@ -1042,7 +1044,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(VMTarget(),  false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(VMTarget(),  false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 8
 | 
					        st.size shouldBe 9
 | 
				
			||||||
        val assigns = st.filterIsInstance<Assignment>()
 | 
					        val assigns = st.filterIsInstance<Assignment>()
 | 
				
			||||||
        (assigns[0].value as NumericLiteral).number shouldBe 12345
 | 
					        (assigns[0].value as NumericLiteral).number shouldBe 12345
 | 
				
			||||||
        (assigns[1].value as NumericLiteral).number shouldBe 0xffee
 | 
					        (assigns[1].value as NumericLiteral).number shouldBe 0xffee
 | 
				
			||||||
@@ -1053,11 +1055,11 @@ main {
 | 
				
			|||||||
    test("oneliner") {
 | 
					    test("oneliner") {
 | 
				
			||||||
        val src="""
 | 
					        val src="""
 | 
				
			||||||
            main { sub start() { cx16.r0++ cx16.r1++ } }
 | 
					            main { sub start() { cx16.r0++ cx16.r1++ } }
 | 
				
			||||||
            other { asmsub thing() { %asm {{ inx }} } }
 | 
					            other { asmsub thing() { %asm {{ inx  rts }} } }
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        val result = compileText(VMTarget(),  false, src, outputDir, writeAssembly = false)!!
 | 
					        val result = compileText(VMTarget(),  false, src, outputDir, writeAssembly = false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 2
 | 
					        st.size shouldBe 3
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -271,28 +271,6 @@ main {
 | 
				
			|||||||
            errors.errors[0] shouldContain "has result value"
 | 
					            errors.errors[0] shouldContain "has result value"
 | 
				
			||||||
            errors.errors[1] shouldContain "has result value"
 | 
					            errors.errors[1] shouldContain "has result value"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        test("missing return value is not a syntax error if there's an external goto") {
 | 
					 | 
				
			||||||
            val src="""
 | 
					 | 
				
			||||||
main {
 | 
					 | 
				
			||||||
    sub start() {
 | 
					 | 
				
			||||||
        cx16.r0 = runit1()
 | 
					 | 
				
			||||||
        runit2()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sub runit1() -> uword {
 | 
					 | 
				
			||||||
        repeat {
 | 
					 | 
				
			||||||
            cx16.r0++
 | 
					 | 
				
			||||||
            goto runit2
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sub runit2() {
 | 
					 | 
				
			||||||
        cx16.r0++
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}"""
 | 
					 | 
				
			||||||
            compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false) shouldNotBe null
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context("variable declarations") {
 | 
					    context("variable declarations") {
 | 
				
			||||||
@@ -355,7 +333,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
            val result = compileText(Cx16Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					            val result = compileText(Cx16Target(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
            val st = result.compilerAst.entrypoint.statements
 | 
					            val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
            st.size shouldBe 12
 | 
					            st.size shouldBe 13
 | 
				
			||||||
            st[0] shouldBe instanceOf<VarDecl>()    // x
 | 
					            st[0] shouldBe instanceOf<VarDecl>()    // x
 | 
				
			||||||
            st[2] shouldBe instanceOf<VarDecl>()    // y
 | 
					            st[2] shouldBe instanceOf<VarDecl>()    // y
 | 
				
			||||||
            st[4] shouldBe instanceOf<VarDecl>()    // z
 | 
					            st[4] shouldBe instanceOf<VarDecl>()    // z
 | 
				
			||||||
@@ -429,7 +407,7 @@ main {
 | 
				
			|||||||
            errors.warnings.all { "dirty variable" in it } shouldBe true
 | 
					            errors.warnings.all { "dirty variable" in it } shouldBe true
 | 
				
			||||||
            val start = result.compilerAst.entrypoint
 | 
					            val start = result.compilerAst.entrypoint
 | 
				
			||||||
            val st = start.statements
 | 
					            val st = start.statements
 | 
				
			||||||
            st.size shouldBe 9
 | 
					            st.size shouldBe 10
 | 
				
			||||||
            val assignments = st.filterIsInstance<Assignment>()
 | 
					            val assignments = st.filterIsInstance<Assignment>()
 | 
				
			||||||
            assignments.size shouldBe 2
 | 
					            assignments.size shouldBe 2
 | 
				
			||||||
            assignments[0].target.identifier?.nameInSource shouldBe listOf("locwi")
 | 
					            assignments[0].target.identifier?.nameInSource shouldBe listOf("locwi")
 | 
				
			||||||
@@ -523,7 +501,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 7
 | 
					        stmts.size shouldBe 8
 | 
				
			||||||
        val assign1expr = (stmts[3] as Assignment).value as BinaryExpression
 | 
					        val assign1expr = (stmts[3] as Assignment).value as BinaryExpression
 | 
				
			||||||
        val assign2expr = (stmts[5] as Assignment).value as BinaryExpression
 | 
					        val assign2expr = (stmts[5] as Assignment).value as BinaryExpression
 | 
				
			||||||
        assign1expr.operator shouldBe "<<"
 | 
					        assign1expr.operator shouldBe "<<"
 | 
				
			||||||
@@ -554,7 +532,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 9
 | 
					        stmts.size shouldBe 10
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("alternative notation for negative containment check") {
 | 
					    test("alternative notation for negative containment check") {
 | 
				
			||||||
@@ -570,7 +548,7 @@ main {
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val stmts = result.compilerAst.entrypoint.statements
 | 
					        val stmts = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        stmts.size shouldBe 4
 | 
					        stmts.size shouldBe 5
 | 
				
			||||||
        val value1 = (stmts[2] as Assignment).value as PrefixExpression
 | 
					        val value1 = (stmts[2] as Assignment).value as PrefixExpression
 | 
				
			||||||
        val value2 = (stmts[3] as Assignment).value as PrefixExpression
 | 
					        val value2 = (stmts[3] as Assignment).value as PrefixExpression
 | 
				
			||||||
        value1.operator shouldBe "not"
 | 
					        value1.operator shouldBe "not"
 | 
				
			||||||
@@ -764,7 +742,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result=compileText(VMTarget(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result=compileText(VMTarget(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 11
 | 
					        st.size shouldBe 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val ifCond = (st[8] as IfElse).condition as BinaryExpression
 | 
					        val ifCond = (st[8] as IfElse).condition as BinaryExpression
 | 
				
			||||||
        ifCond.operator shouldBe ">="
 | 
					        ifCond.operator shouldBe ">="
 | 
				
			||||||
@@ -792,7 +770,7 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val result=compileText(Cx16Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
					        val result=compileText(Cx16Target(), optimize=false, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 6
 | 
					        st.size shouldBe 7
 | 
				
			||||||
        val value = (st[5] as Assignment).value as BinaryExpression
 | 
					        val value = (st[5] as Assignment).value as BinaryExpression
 | 
				
			||||||
        value.operator shouldBe "%"
 | 
					        value.operator shouldBe "%"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -838,10 +816,9 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(VMTarget(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
					        val result = compileText(VMTarget(), optimize=true, src, outputDir, writeAssembly=false)!!
 | 
				
			||||||
        val st = result.compilerAst.entrypoint.statements
 | 
					        val st = result.compilerAst.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 8
 | 
					        st.size shouldBe 9
 | 
				
			||||||
        val assignUbbVal = ((st[5] as Assignment).value as TypecastExpression)
 | 
					        val assignUbbVal = (st[5] as Assignment).value as IdentifierReference
 | 
				
			||||||
        assignUbbVal.type shouldBe DataType.UBYTE
 | 
					        assignUbbVal.inferType(result.compilerAst) shouldBe InferredTypes.knownFor(BaseDataType.BYTE)
 | 
				
			||||||
        assignUbbVal.expression shouldBe instanceOf<IdentifierReference>()
 | 
					 | 
				
			||||||
        val assignVaddr = (st[7] as Assignment).value as FunctionCallExpression
 | 
					        val assignVaddr = (st[7] as Assignment).value as FunctionCallExpression
 | 
				
			||||||
        assignVaddr.target.nameInSource shouldBe listOf("mkword")
 | 
					        assignVaddr.target.nameInSource shouldBe listOf("mkword")
 | 
				
			||||||
        val tc = assignVaddr.args[0] as TypecastExpression
 | 
					        val tc = assignVaddr.args[0] as TypecastExpression
 | 
				
			||||||
@@ -970,6 +947,7 @@ main {
 | 
				
			|||||||
        if cx16.r0==0
 | 
					        if cx16.r0==0
 | 
				
			||||||
            return cx16.r0+cx16.r1
 | 
					            return cx16.r0+cx16.r1
 | 
				
			||||||
        defer cx16.r2++
 | 
					        defer cx16.r2++
 | 
				
			||||||
 | 
					        return 999
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(Cx16Target(), optimize=true, src, outputDir, writeAssembly=true)!!
 | 
					        val result = compileText(Cx16Target(), optimize=true, src, outputDir, writeAssembly=true)!!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -206,7 +206,7 @@ main {
 | 
				
			|||||||
}"""
 | 
					}"""
 | 
				
			||||||
        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!.compilerAst
 | 
					        val result = compileText(C64Target(), false, src, outputDir, writeAssembly = false)!!.compilerAst
 | 
				
			||||||
        val st = result.entrypoint.statements
 | 
					        val st = result.entrypoint.statements
 | 
				
			||||||
        st.size shouldBe 8
 | 
					        st.size shouldBe 9
 | 
				
			||||||
        st[0] shouldBe instanceOf<VarDecl>()
 | 
					        st[0] shouldBe instanceOf<VarDecl>()
 | 
				
			||||||
        st[1] shouldBe instanceOf<VarDecl>()
 | 
					        st[1] shouldBe instanceOf<VarDecl>()
 | 
				
			||||||
        st[2] shouldBe instanceOf<VarDecl>()
 | 
					        st[2] shouldBe instanceOf<VarDecl>()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -137,6 +137,26 @@ interface IStatementContainer {
 | 
				
			|||||||
        return null
 | 
					        return null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun hasReturnStatement(): Boolean {
 | 
				
			||||||
 | 
					        fun hasReturnStatement(stmt: Statement): Boolean {
 | 
				
			||||||
 | 
					            when(stmt) {
 | 
				
			||||||
 | 
					                is AnonymousScope -> return stmt.statements.any { hasReturnStatement(it) }
 | 
				
			||||||
 | 
					                is ForLoop -> return stmt.body.hasReturnStatement()
 | 
				
			||||||
 | 
					                is IfElse -> return stmt.truepart.hasReturnStatement() || stmt.elsepart.hasReturnStatement()
 | 
				
			||||||
 | 
					                is WhileLoop -> return stmt.body.hasReturnStatement()
 | 
				
			||||||
 | 
					                is RepeatLoop -> return stmt.body.hasReturnStatement()
 | 
				
			||||||
 | 
					                is UntilLoop -> return stmt.body.hasReturnStatement()
 | 
				
			||||||
 | 
					                is When -> return stmt.choices.any { it.statements.hasReturnStatement() }
 | 
				
			||||||
 | 
					                is ConditionalBranch -> return stmt.truepart.hasReturnStatement() || stmt.elsepart.hasReturnStatement()
 | 
				
			||||||
 | 
					                is UnrollLoop -> return stmt.body.hasReturnStatement()
 | 
				
			||||||
 | 
					                is Return -> return true
 | 
				
			||||||
 | 
					                else -> return false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return statements.any { hasReturnStatement(it) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val allDefinedSymbols: Sequence<Pair<String, Statement>>
 | 
					    val allDefinedSymbols: Sequence<Pair<String, Statement>>
 | 
				
			||||||
        get() {
 | 
					        get() {
 | 
				
			||||||
            return statements.asSequence().filterIsInstance<INamedStatement>().map { Pair(it.name, it as Statement) }
 | 
					            return statements.asSequence().filterIsInstance<INamedStatement>().map { Pair(it.name, it as Statement) }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user