mirror of
https://github.com/irmen/prog8.git
synced 2024-09-29 08:57:51 +00:00
fix symbol lookup in new ast and minor codegen errors
This commit is contained in:
parent
e31e5b2477
commit
5b6534bb28
@ -23,4 +23,8 @@ class CompilationOptions(val output: OutputType,
|
||||
var evalStackBaseAddress: UInt? = null,
|
||||
var outputDir: Path = Path(""),
|
||||
var symbolDefs: Map<String, String> = emptyMap()
|
||||
)
|
||||
) {
|
||||
init {
|
||||
compTarget.machine.initializeMemoryAreas(this)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<PtNamedNode>().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? =
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user