diff --git a/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt b/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt index 00df2a552..2667c0baa 100644 --- a/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt +++ b/codeGeneration/src/prog8/compiler/target/c64/C64MachineDefinition.kt @@ -56,7 +56,7 @@ object C64MachineDefinition: IMachineDefinition { } } - override fun isRegularRAMaddress(address: Int): Boolean = address<0xa000 || address in 0xc000..0xcfff + override fun isIOAddress(address: Int): Boolean = address==0 || address==1 || address in 0xd000..0xdfff override fun initializeZeropage(compilerOptions: CompilationOptions) { zeropage = C64Zeropage(compilerOptions) diff --git a/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt b/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt index 45822a391..141438ed0 100644 --- a/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt +++ b/codeGeneration/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt @@ -67,7 +67,7 @@ object CX16MachineDefinition: IMachineDefinition { } } - override fun isRegularRAMaddress(address: Int): Boolean = address < 0x9f00 || address in 0xa000..0xbfff + override fun isIOAddress(address: Int): Boolean = address==0 || address==1 || address in 0x9f00..0x9fff override fun initializeZeropage(compilerOptions: CompilationOptions) { zeropage = CX16Zeropage(compilerOptions) diff --git a/codeGeneration/test/AsmGenSymbolsTests.kt b/codeGeneration/test/AsmGenSymbolsTests.kt index 75b20dd7c..c371671a6 100644 --- a/codeGeneration/test/AsmGenSymbolsTests.kt +++ b/codeGeneration/test/AsmGenSymbolsTests.kt @@ -69,7 +69,6 @@ class AsmGenSymbolsTests: StringSpec({ val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) return program } diff --git a/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt index 9270b1116..099982080 100644 --- a/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt +++ b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt @@ -15,7 +15,7 @@ import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.ICompilationTarget -import prog8.compilerinterface.isInRegularRAMof +import prog8.compilerinterface.isIOAddress class BinExprSplitter(private val program: Program, private val options: CompilationOptions, private val compTarget: ICompilationTarget) : AstWalker() { @@ -97,7 +97,7 @@ X = BinExpr X = LeftExpr private fun isSimpleTarget(target: AssignTarget) = if (target.identifier!=null || target.memoryAddress!=null) - target.isInRegularRAMof(compTarget.machine) + !target.isIOAddress(compTarget.machine) else false diff --git a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt index 708bf1cc0..0ae7ac634 100644 --- a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt @@ -12,7 +12,7 @@ import prog8.ast.walk.IAstModification import prog8.compilerinterface.CallGraph import prog8.compilerinterface.ICompilationTarget import prog8.compilerinterface.IErrorReporter -import prog8.compilerinterface.isInRegularRAMof +import prog8.compilerinterface.isIOAddress class UnusedCodeRemover(private val program: Program, @@ -121,7 +121,7 @@ class UnusedCodeRemover(private val program: Program, it.parent.parent as AssignTarget else null }.filter { - it.isInRegularRAMof(compTarget.machine) + !it.isIOAddress(compTarget.machine) } if(assignTargets.size==usages.size) { errors.warn("removing unused variable '${decl.name}'", decl.position) @@ -147,7 +147,7 @@ class UnusedCodeRemover(private val program: Program, val assign1 = stmtPairs[0] as? Assignment val assign2 = stmtPairs[1] as? Assignment if (assign1 != null && assign2 != null && !assign2.isAugmentable) { - if (assign1.target.isSameAs(assign2.target, program) && assign1.target.isInRegularRAMof(compTarget.machine)) { + if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) { if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(*(assign2.target.identifier!!.nameInSource.toTypedArray()))) // only remove the second assignment if its value is a simple expression! when(assign2.value) { diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 4b4b82dee..5e879184d 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -32,7 +32,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o // But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF. if(!assignment.isAugmentable && assignment.target.identifier != null - && assignment.target.isInRegularRAMof(options.compTarget.machine)) { + && !assignment.target.isIOAddress(options.compTarget.machine)) { val binExpr = assignment.value as? BinaryExpression if(binExpr!=null && binExpr.inferType(program).istype(DataType.FLOAT) && !options.optimizeFloatExpressions) diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index dd26c2237..5d4289217 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -12,8 +12,9 @@ import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.PrefixExpression import prog8.ast.statements.* +import prog8.compiler.printAst import prog8.compiler.target.C64Target -import prog8.compilerinterface.isInRegularRAMof +import prog8.compilerinterface.isIOAddress import prog8.parser.SourceCode import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyMemsizer @@ -22,80 +23,132 @@ import prog8tests.helpers.DummyStringEncoder class TestMemory: FunSpec({ - test("testInValidRamC64_memory_addresses") { + fun wrapWithProgram(statements: List): Program { + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) + val subroutine = Subroutine("test", mutableListOf(), emptyList(), statements.toMutableList(), false, Position.DUMMY) + val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) + program.addModule(module) + return program + } - var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY) + test("assignment target not in mapped IO space C64") { + + var memexpr = NumericLiteralValue.optimalInteger(0x0002, Position.DUMMY) var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe true + var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe true + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe true + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false + + memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe true + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe true - } + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false - test("testNotInValidRamC64_memory_addresses") { - - var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY) - var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe false - - memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY) + memexpr = NumericLiteralValue.optimalInteger(0xeeee, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe false - - memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe false + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY) target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe false + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false } - fun createTestProgramForMemoryRefViaVar(program: Program, address: Int, vartype: VarDeclType): AssignTarget { + test("assign target in mapped IO space C64") { + + var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY) + var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe true + + memexpr = NumericLiteralValue.optimalInteger(0x0001, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe true + + memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe true + + memexpr = NumericLiteralValue.optimalInteger(0xdfff, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe true + } + + fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget { val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - module.linkIntoProgram(program) + wrapWithProgram(listOf(decl, assignment)) return target } - test("testInValidRamC64_memory_identifiers") { - val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) - var target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.VAR) - target.isInRegularRAMof(C64Target.machine) shouldBe true - target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.VAR) - target.isInRegularRAMof(C64Target.machine) shouldBe false - target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.CONST) - target.isInRegularRAMof(C64Target.machine) shouldBe true - target = createTestProgramForMemoryRefViaVar(program, 0xd020, VarDeclType.CONST) - target.isInRegularRAMof(C64Target.machine) shouldBe false - target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.MEMORY) - target.isInRegularRAMof(C64Target.machine) shouldBe false + test("identifier mapped to IO memory on C64") { + var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR) + target.isIOAddress(C64Target.machine) shouldBe false + target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR) + target.isIOAddress(C64Target.machine) shouldBe false + target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST) + target.isIOAddress(C64Target.machine) shouldBe false + target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST) + target.isIOAddress(C64Target.machine) shouldBe true + target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY) + target.isIOAddress(C64Target.machine) shouldBe false + target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.MEMORY) + target.isIOAddress(C64Target.machine) shouldBe true } - test("testInValidRamC64_memory_expression") { - val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY) - val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - target.isInRegularRAMof(C64Target.machine) shouldBe false + test("memory expression mapped to IO memory on C64\"") { + var memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY) + var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + var assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + target.isIOAddress(C64Target.machine) shouldBe false + + memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0xd020, Position.DUMMY), Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + wrapWithProgram(listOf(assign)) + printAst(target.definingModule.program) + target.isIOAddress(C64Target.machine) shouldBe true } - test("testInValidRamC64_variable") { + test("regular variable not in mapped IO ram on C64") { val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) @@ -103,11 +156,10 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe true + target.isIOAddress(C64Target.machine) shouldBe false } - test("testInValidRamC64_memmap_variable") { + test("memory mapped variable not in mapped IO ram on C64") { val address = 0x1000 val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) @@ -116,11 +168,10 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe true + target.isIOAddress(C64Target.machine) shouldBe false } - test("testNotInValidRamC64_memmap_variable") { + test("memory mapped variable in mapped IO ram on C64") { val address = 0xd020 val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) @@ -129,11 +180,10 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe false + target.isIOAddress(C64Target.machine) shouldBe true } - test("testInValidRamC64_array") { + test("array not in mapped IO ram") { val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) @@ -142,11 +192,10 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe true + target.isIOAddress(C64Target.machine) shouldBe false } - test("testInValidRamC64_array_memmapped") { + test("memory mapped array not in mapped IO ram") { val address = 0x1000 val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) @@ -156,12 +205,11 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe true + target.isIOAddress(C64Target.machine) shouldBe false } - test("testNotValidRamC64_array_memmapped") { - val address = 0xe000 + test("memory mapped array in mapped IO ram") { + val address = 0xd800 val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) @@ -170,7 +218,6 @@ class TestMemory: FunSpec({ val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) - module.linkIntoProgram(program) - target.isInRegularRAMof(C64Target.machine) shouldBe false + target.isIOAddress(C64Target.machine) shouldBe true } }) diff --git a/compilerAst/src/prog8/ast/AstToplevel.kt b/compilerAst/src/prog8/ast/AstToplevel.kt index 66bffc8c2..49245a0e3 100644 --- a/compilerAst/src/prog8/ast/AstToplevel.kt +++ b/compilerAst/src/prog8/ast/AstToplevel.kt @@ -290,11 +290,6 @@ open class Module(final override var statements: MutableList, statements.forEach {it.linkParents(this)} } - fun linkIntoProgram(program: Program) { - this.program = program - linkParents(program.namespace) - } - override val definingScope: INameScope get() = program.namespace override fun replaceChildNode(node: Node, replacement: Node) { diff --git a/compilerAst/src/prog8/ast/Program.kt b/compilerAst/src/prog8/ast/Program.kt index 54cd2f289..735c49ac1 100644 --- a/compilerAst/src/prog8/ast/Program.kt +++ b/compilerAst/src/prog8/ast/Program.kt @@ -41,7 +41,8 @@ class Program(val name: String, require(null == _modules.firstOrNull { it.name == module.name }) { "module '${module.name}' already present" } _modules.add(module) - module.linkIntoProgram(this) + module.program = this + module.linkParents(namespace) return this } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index df6991bf5..ef5f8af56 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -94,7 +94,26 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid } override fun copy() = PrefixExpression(operator, expression.copy(), position) - override fun constValue(program: Program): NumericLiteralValue? = null + override fun constValue(program: Program): NumericLiteralValue? { + val constval = expression.constValue(program) ?: return null + return when(operator) { + "+" -> constval + "-" -> when (constval.type) { + in IntegerDatatypes -> NumericLiteralValue.optimalInteger(-constval.number.toInt(), constval.position) + DataType.FLOAT -> NumericLiteralValue(DataType.FLOAT, -constval.number, constval.position) + else -> throw ExpressionError("can only take negative of int or float", constval.position) + } + "~" -> when (constval.type) { + DataType.BYTE -> NumericLiteralValue(DataType.BYTE, constval.number.toInt().inv().toDouble(), constval.position) + DataType.UBYTE -> NumericLiteralValue(DataType.UBYTE, (constval.number.toInt().inv() and 255).toDouble(), constval.position) + DataType.WORD -> NumericLiteralValue(DataType.WORD, constval.number.toInt().inv().toDouble(), constval.position) + DataType.UWORD -> NumericLiteralValue(DataType.UWORD, (constval.number.toInt().inv() and 65535).toDouble(), constval.position) + else -> throw ExpressionError("can only take bitwise inversion of int", constval.position) + } + "not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position) + else -> throw FatalAstException("invalid operator") + } + } override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) diff --git a/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt b/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt index 2dc4bf163..f8926ed25 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/AstExtensions.kt @@ -8,47 +8,45 @@ import prog8.ast.expressions.RangeExpr import prog8.ast.statements.AssignTarget import kotlin.math.abs -fun AssignTarget.isInRegularRAMof(machine: IMachineDefinition): Boolean { +fun AssignTarget.isIOAddress(machine: IMachineDefinition): Boolean { val memAddr = memoryAddress val arrayIdx = arrayindexed val ident = identifier when { memAddr != null -> { + val addr = memAddr.addressExpression.constValue(definingModule.program) + if(addr!=null) + return machine.isIOAddress(addr.number.toInt()) return when (memAddr.addressExpression) { - is NumericLiteralValue -> { - machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt()) - } is IdentifierReference -> { - val program = definingModule.program - val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program) - if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue) - machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) + val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(definingModule.program) + val result = if ((decl?.type == VarDeclType.MEMORY || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue) + machine.isIOAddress((decl.value as NumericLiteralValue).number.toInt()) else false + result } else -> false } } arrayIdx != null -> { - val program = definingModule.program - val targetStmt = arrayIdx.arrayvar.targetVarDecl(program) + val targetStmt = arrayIdx.arrayvar.targetVarDecl(definingModule.program) return if (targetStmt?.type == VarDeclType.MEMORY) { val addr = targetStmt.value as? NumericLiteralValue if (addr != null) - machine.isRegularRAMaddress(addr.number.toInt()) + machine.isIOAddress(addr.number.toInt()) else false - } else true + } else false } ident != null -> { - val program = definingModule.program - val decl = ident.targetVarDecl(program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}") + val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}") return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue) - machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt()) + machine.isIOAddress((decl.value as NumericLiteralValue).number.toInt()) else - true + false } - else -> return true + else -> return false } } diff --git a/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt b/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt index 82294b855..e8ad74ea4 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/IMachineDefinition.kt @@ -32,5 +32,5 @@ interface IMachineDefinition { fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) - fun isRegularRAMaddress(address: Int): Boolean + fun isIOAddress(address: Int): Boolean } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 561dc6889..f9ff5b63b 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -23,7 +23,7 @@ Future - use UByte instead of Short - simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation - remove special code generation for while and util expression - by rewriting while and until expressions into if+jump (consider them syntactic sugar) + by rewriting while and until expressions into if+jump (just consider them syntactic sugar) but the result should not produce larger code ofcourse! - while-expression should now also get the simplifyConditionalExpression() treatment - fix the asm-labels problem (github issue #62)