reducing dependencies

This commit is contained in:
Irmen de Jong 2021-02-09 18:38:44 +01:00
parent 7d98275763
commit bc37097df2
7 changed files with 53 additions and 62 deletions

View File

@ -11,7 +11,7 @@ import prog8.ast.walk.IAstModification
import prog8.compiler.target.ICompilationTarget
internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: ErrorReporter) : AstWalker() {
internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: ErrorReporter, private val compTarget: ICompilationTarget) : AstWalker() {
private val noModifications = emptyList<IAstModification>()
@ -38,7 +38,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
// But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF.
if(!assignment.isAugmentable
&& assignment.target.identifier != null
&& ICompilationTarget.instance.isInRegularRAM(assignment.target, program)) {
&& compTarget.isInRegularRAM(assignment.target, program)) {
val binExpr = assignment.value as? BinaryExpression
if (binExpr != null && binExpr.operator !in comparisonOperators) {
if (binExpr.left !is BinaryExpression) {

View File

@ -11,8 +11,8 @@ import prog8.ast.statements.Directive
import prog8.compiler.astprocessing.*
import prog8.compiler.functions.*
import prog8.compiler.target.C64Target
import prog8.compiler.target.ICompilationTarget
import prog8.compiler.target.Cx16Target
import prog8.compiler.target.ICompilationTarget
import prog8.compiler.target.asmGeneratorFor
import prog8.optimizer.*
import prog8.parser.ModuleImporter
@ -90,10 +90,10 @@ fun compileProgram(filepath: Path,
compilationOptions.optimize = optimize
programAst = ast
importedFiles = imported
processAst(programAst, errors, compilationOptions)
processAst(programAst, errors, compilationOptions, ICompilationTarget.instance)
if (compilationOptions.optimize)
optimizeAst(programAst, errors, BuiltinFunctionsFacade(BuiltinFunctions))
postprocessAst(programAst, errors, compilationOptions)
postprocessAst(programAst, errors, compilationOptions, ICompilationTarget.instance)
// printAst(programAst)
@ -237,10 +237,10 @@ private fun determineCompilationOptions(program: Program): CompilationOptions {
)
}
private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) {
private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions, compTarget: ICompilationTarget) {
// perform initial syntax checks and processings
println("Processing for target ${ICompilationTarget.instance.name}...")
programAst.checkIdentifiers(errors)
println("Processing for target ${compTarget.name}...")
programAst.checkIdentifiers(errors, compTarget)
errors.handle()
programAst.constantFold(errors)
errors.handle()
@ -249,9 +249,9 @@ private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptio
programAst.addTypecasts(errors)
errors.handle()
programAst.variousCleanups()
programAst.checkValid(compilerOptions, errors)
programAst.checkValid(compilerOptions, errors, compTarget)
errors.handle()
programAst.checkIdentifiers(errors)
programAst.checkIdentifiers(errors, compTarget)
errors.handle()
}
@ -275,11 +275,11 @@ private fun optimizeAst(programAst: Program, errors: ErrorReporter, functions: I
errors.handle()
}
private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) {
private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions, compTarget: ICompilationTarget) {
programAst.addTypecasts(errors)
errors.handle()
programAst.variousCleanups()
programAst.checkValid(compilerOptions, errors) // check if final tree is still valid
programAst.checkValid(compilerOptions, errors, compTarget) // check if final tree is still valid
errors.handle()
val callGraph = CallGraph(programAst)
callGraph.checkRecursiveCalls(errors)
@ -291,7 +291,7 @@ private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerO
private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir: Path,
compilerOptions: CompilationOptions): String {
// asm generation directly from the Ast,
programAst.processAstBeforeAsmGeneration(errors)
programAst.processAstBeforeAsmGeneration(errors, ICompilationTarget.instance)
errors.handle()
// printAst(programAst)

View File

@ -12,13 +12,14 @@ import prog8.compiler.ErrorReporter
import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.functions.builtinFunctionReturnType
import prog8.compiler.target.C64Target
import prog8.compiler.target.ICompilationTarget
import prog8.compiler.target.Cx16Target
import prog8.compiler.target.ICompilationTarget
import java.io.File
internal class AstChecker(private val program: Program,
private val compilerOptions: CompilationOptions,
private val errors: ErrorReporter
private val errors: ErrorReporter,
private val compTarget: ICompilationTarget
) : IAstVisitor {
override fun visit(program: Program) {
@ -1286,7 +1287,7 @@ internal class AstChecker(private val program: Program,
// check if the floating point values are all within range
val doubles = value.value.map {it.constValue(program)?.number!!.toDouble()}.toDoubleArray()
if(doubles.any { it < ICompilationTarget.instance.machine.FLOAT_MAX_NEGATIVE || it > ICompilationTarget.instance.machine.FLOAT_MAX_POSITIVE })
if(doubles.any { it < compTarget.machine.FLOAT_MAX_NEGATIVE || it > compTarget.machine.FLOAT_MAX_POSITIVE })
return err("floating point value overflow")
return true
}

View File

@ -6,15 +6,16 @@ import prog8.ast.base.FatalAstException
import prog8.ast.statements.Directive
import prog8.compiler.BeforeAsmGenerationAstChanger
import prog8.compiler.CompilationOptions
import prog8.compiler.target.ICompilationTarget
internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: ErrorReporter) {
val checker = AstChecker(this, compilerOptions, errors)
internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: ErrorReporter, compTarget: ICompilationTarget) {
val checker = AstChecker(this, compilerOptions, errors, compTarget)
checker.visit(this)
}
internal fun Program.processAstBeforeAsmGeneration(errors: ErrorReporter) {
val fixer = BeforeAsmGenerationAstChanger(this, errors)
internal fun Program.processAstBeforeAsmGeneration(errors: ErrorReporter, compTarget: ICompilationTarget) {
val fixer = BeforeAsmGenerationAstChanger(this, errors, compTarget)
fixer.visit(this)
fixer.applyModifications()
}
@ -36,9 +37,9 @@ internal fun Program.verifyFunctionArgTypes() {
fixer.visit(this)
}
internal fun Program.checkIdentifiers(errors: ErrorReporter) {
internal fun Program.checkIdentifiers(errors: ErrorReporter, compTarget: ICompilationTarget) {
val checker2 = AstIdentifiersChecker(this, errors)
val checker2 = AstIdentifiersChecker(this, errors, compTarget)
checker2.visit(this)
if(errors.isEmpty()) {

View File

@ -14,7 +14,7 @@ import prog8.ast.walk.IAstVisitor
import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.target.ICompilationTarget
internal class AstIdentifiersChecker(private val program: Program, private val errors: ErrorReporter) : IAstVisitor {
internal class AstIdentifiersChecker(private val program: Program, private val errors: ErrorReporter, private val compTarget: ICompilationTarget) : IAstVisitor {
private var blocks = mutableMapOf<String, Block>()
private fun nameError(name: String, position: Position, existing: Statement) {
@ -28,7 +28,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
}
override fun visit(block: Block) {
if(block.name in ICompilationTarget.instance.machine.opcodeNames)
if(block.name in compTarget.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position)
val existing = blocks[block.name]
@ -50,8 +50,8 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
override fun visit(directive: Directive) {
if(directive.directive=="%target") {
val compatibleTarget = directive.args.single().name
if (compatibleTarget != ICompilationTarget.instance.name)
errors.err("module's compilation target ($compatibleTarget) differs from active target (${ICompilationTarget.instance.name})", directive.position)
if (compatibleTarget != compTarget.name)
errors.err("module's compilation target ($compatibleTarget) differs from active target (${compTarget.name})", directive.position)
}
super.visit(directive)
@ -63,7 +63,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
if(decl.name in BuiltinFunctions)
errors.err("builtin function cannot be redefined", decl.position)
if(decl.name in ICompilationTarget.instance.machine.opcodeNames)
if(decl.name in compTarget.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
if(decl.datatype==DataType.STRUCT) {
@ -102,7 +102,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
}
override fun visit(subroutine: Subroutine) {
if(subroutine.name in ICompilationTarget.instance.machine.opcodeNames) {
if(subroutine.name in compTarget.machine.opcodeNames) {
errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position)
} else if(subroutine.name in BuiltinFunctions) {
// the builtin functions can't be redefined
@ -142,7 +142,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
}
override fun visit(label: Label) {
if(label.name in ICompilationTarget.instance.machine.opcodeNames)
if(label.name in compTarget.machine.opcodeNames)
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
if(label.name in BuiltinFunctions) {

View File

@ -24,7 +24,7 @@ internal interface ICompilationTarget: IStringEncoding {
fun memorySize(dt: DataType): Int
companion object {
lateinit var instance: ICompilationTarget
lateinit var instance: ICompilationTarget // TODO reduce dependency on this by just passing the instance as a parameter
}
fun isInRegularRAM(target: AssignTarget, program: Program): Boolean {

View File

@ -14,7 +14,6 @@ import prog8.ast.statements.*
import prog8.ast.toHex
import prog8.compiler.*
import prog8.compiler.target.C64Target
import prog8.compiler.target.ICompilationTarget
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
@ -415,67 +414,64 @@ class TestMemory {
@Test
fun testInValidRamC64_memory_addresses() {
ICompilationTarget.instance = C64Target
var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY)
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
val program = Program("test", mutableListOf(), DummyFunctions())
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testNotInValidRamC64_memory_addresses() {
ICompilationTarget.instance = C64Target
var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY)
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
val program = Program("test", mutableListOf(), DummyFunctions())
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_memory_identifiers() {
ICompilationTarget.instance = C64Target
var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR)
val program = Program("test", mutableListOf(), DummyFunctions())
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
@ -492,16 +488,14 @@ class TestMemory {
@Test
fun testInValidRamC64_memory_expression() {
ICompilationTarget.instance = C64Target
val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
val program = Program("test", mutableListOf(), DummyFunctions())
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_variable() {
ICompilationTarget.instance = C64Target
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, null, 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)
@ -509,12 +503,11 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_memmap_variable() {
ICompilationTarget.instance = C64Target
val address = 0x1000
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
@ -523,12 +516,11 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testNotInValidRamC64_memmap_variable() {
ICompilationTarget.instance = C64Target
val address = 0xd020
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
@ -537,12 +529,11 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_array() {
ICompilationTarget.instance = C64Target
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, null, 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)
@ -551,12 +542,11 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_array_memmapped() {
ICompilationTarget.instance = C64Target
val address = 0x1000
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
@ -566,12 +556,11 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertTrue(ICompilationTarget.instance.isInRegularRAM(target, program))
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testNotValidRamC64_array_memmapped() {
ICompilationTarget.instance = C64Target
val address = 0xe000
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
@ -581,6 +570,6 @@ class TestMemory {
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions())
module.linkParents(ParentSentinel)
assertFalse(ICompilationTarget.instance.isInRegularRAM(target, program))
assertFalse(C64Target.isInRegularRAM(target, program))
}
}