diff --git a/codeCore/src/prog8/code/core/CompilationOptions.kt b/codeCore/src/prog8/code/core/CompilationOptions.kt index 5b5d8f08c..2a12fd878 100644 --- a/codeCore/src/prog8/code/core/CompilationOptions.kt +++ b/codeCore/src/prog8/code/core/CompilationOptions.kt @@ -23,4 +23,8 @@ class CompilationOptions(val output: OutputType, var evalStackBaseAddress: UInt? = null, var outputDir: Path = Path(""), var symbolDefs: Map = emptyMap() -) +) { + init { + compTarget.machine.initializeMemoryAreas(this) + } +} diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt index ba312db61..871151ea3 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt @@ -3,7 +3,6 @@ package prog8.codegen.cpu6502 import prog8.code.StConstant import prog8.code.StMemVar import prog8.code.SymbolTable -import prog8.code.core.AssemblyError import prog8.code.core.IMachineDefinition @@ -448,6 +447,7 @@ private fun optimizeStoreLoadSame( private val identifierRegex = Regex("""^([a-zA-Z_$][a-zA-Z\d_\.$]*)""") private fun getAddressArg(line: String, symbolTable: SymbolTable): UInt? { + // try to get the constant value address, could return null if it's a symbol instead val loadArg = line.trimStart().substring(3).trim() return when { loadArg.startsWith('$') -> loadArg.substring(1).toUIntOrNull(16) @@ -461,8 +461,7 @@ private fun getAddressArg(line: String, symbolTable: SymbolTable): UInt? { when (val symbol = symbolTable.flat[identifier]) { is StConstant -> symbol.value.toUInt() is StMemVar -> symbol.address - null -> null - else -> throw AssemblyError("expected constant or memvar for address $line") + else -> null } } else null } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt index 54b8a7804..efd4914a1 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt @@ -66,29 +66,46 @@ internal fun PtIdentifier.targetStatement(program: PtProgram): PtNode { } internal fun PtProgram.lookup(name: String): PtNode { - val remainder = name.split('.').toMutableList() // TODO optimize split to not use memory allocations - - fun recurse(node: PtNode): PtNode { + fun searchLocalSymbol(node: PtNode, namePart: String): PtNode? { when(node) { is PtProgram -> { - val blockName = remainder.removeFirst() - return recurse(allBlocks().single { it.name==blockName }) + return node.allBlocks().single { it.name==namePart } } - is PtAsmSub -> { - require(remainder.isEmpty()) - return node - } - is PtBlock, is PtSub, is PtNamedNode -> { - if(remainder.isEmpty()) + is PtNamedNode -> { + if(node.name==namePart) return node - val childName = remainder.removeFirst() - return recurse(node.children.filterIsInstance().single { it.name==childName}) } - else -> throw IllegalArgumentException("invalid name $name in parent $node") + is PtNodeGroup -> { + node.children.forEach { + val found = searchLocalSymbol(it, namePart) + if(found!=null) + return found + } + } + is PtIdentifier -> { + if(node.name==namePart) + return node + } + is PtSubroutineParameter -> { + if(node.name==namePart) + return node + } + else -> { + // NOTE: when other nodes containing scopes are introduced, + // these should be added here as well to look into! + } } + + node.children.forEach { + val found = searchLocalSymbol(it, namePart) + if(found!=null) + return found + } + return null } - return recurse(this) + val remainder = name.splitToSequence('.') + return remainder.fold(this as PtNode) { acc, namePart -> searchLocalSymbol(acc, namePart)!! } } internal fun PtIdentifier.targetVarDecl(program: PtProgram): PtVariable? = diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 611671157..2d35e8df7 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -142,7 +142,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as if(!isArgumentTypeCompatible(value.type, parameter.type)) throw AssemblyError("argument type incompatible") - val varName = asmgen.asmVariableName(sub.scopedName + parameter.name) + val varName = asmgen.asmVariableName(sub.scopedName + "." + parameter.name) asmgen.assignExpressionToVariable(value, varName, parameter.type, sub) } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt index 6556d9a3e..1b0688c24 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt @@ -202,7 +202,7 @@ internal class AsmAssignment(val source: AsmAssignSource, if(target.register !in arrayOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY)) require(source.datatype != DataType.UNDEFINED) { "must not be placeholder/undefined datatype at $position" } require(memsizer.memorySize(source.datatype) <= memsizer.memorySize(target.datatype)) { - "source dt size must be less or equal to target dt size at $position" + "source dt size must be less or equal to target dt size at $position srcdt=${source.datatype} targetdt=${target.datatype}" } } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 66107ab44..42c6eda1c 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -1100,6 +1100,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, private fun assignCastViaLsbFunc(value: PtExpression, target: AsmAssignTarget) { val lsb = PtBuiltinFunctionCall("lsb", false, true, DataType.UBYTE, value.position) + lsb.parent = value.parent lsb.add(value) val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UBYTE, expression = lsb) val assign = AsmAssignment(src, target, false, program.memsizer, value.position) diff --git a/compiler/test/codegeneration/TestAsmGenSymbols.kt b/compiler/test/codegeneration/TestAsmGenSymbols.kt index 8b9b7dead..b2982a6e6 100644 --- a/compiler/test/codegeneration/TestAsmGenSymbols.kt +++ b/compiler/test/codegeneration/TestAsmGenSymbols.kt @@ -15,7 +15,6 @@ import prog8.code.ast.PtIdentifier import prog8.code.core.* import prog8.code.target.C64Target import prog8.code.target.VMTarget -import prog8.code.target.c64.C64Zeropage import prog8.codegen.cpu6502.AsmGen import prog8.compiler.astprocessing.IntermediateAstMaker import prog8.compiler.astprocessing.SymbolTableMaker @@ -75,7 +74,6 @@ class TestAsmGenSymbols: StringSpec({ fun createTestAsmGen(program: Program): AsmGen { val errors = ErrorReporterForTests() val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target(), 999u) - options.compTarget.machine.zeropage = C64Zeropage(options) val st = SymbolTableMaker(program, options).make() val ptProgram = IntermediateAstMaker(program, st, options).transform() return AsmGen(ptProgram, st, options, errors) diff --git a/compiler/test/helpers/Dummies.kt b/compiler/test/helpers/Dummies.kt index 16a81bdc4..0915d98b6 100644 --- a/compiler/test/helpers/Dummies.kt +++ b/compiler/test/helpers/Dummies.kt @@ -5,6 +5,7 @@ import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteral import prog8.code.core.* +import prog8.code.target.virtual.VirtualMachineDefinition internal object DummyFunctions : IBuiltinFunctions { @@ -44,8 +45,7 @@ internal object AsciiStringEncoder : IStringEncoding { internal object DummyCompilationTarget : ICompilationTarget { override val name: String = "dummy" - override val machine: IMachineDefinition - get() = throw NotImplementedError("dummy") + override val machine: IMachineDefinition = VirtualMachineDefinition() // not really true but I don't want to implement a full dummy machinedef override val supportedEncodings = setOf(Encoding.PETSCII, Encoding.SCREENCODES, Encoding.ISO) override val defaultEncoding = Encoding.PETSCII