mirror of
https://github.com/irmen/prog8.git
synced 2025-07-04 08:24:02 +00:00
cleanup RTS insertion and ast postprocessing before assembly generation
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
|
||||||
|
@ -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) {
|
||||||
|
@ -54,7 +54,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
|
||||||
@ -157,7 +157,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)
|
||||||
@ -209,7 +209,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") {
|
||||||
@ -224,7 +224,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 BaseDataType.WORD
|
assign1tc.type shouldBe BaseDataType.WORD
|
||||||
@ -255,7 +255,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()
|
||||||
@ -903,7 +903,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
|
||||||
@ -928,7 +928,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 BaseDataType.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>()
|
||||||
|
@ -7,7 +7,9 @@ import prog8.ast.expressions.NumericLiteral
|
|||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.code.core.*
|
import prog8.code.core.BaseDataType
|
||||||
|
import prog8.code.core.Encoding
|
||||||
|
import prog8.code.core.Position
|
||||||
import prog8.code.source.SourceCode
|
import prog8.code.source.SourceCode
|
||||||
|
|
||||||
|
|
||||||
@ -135,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