mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
optimizing
This commit is contained in:
parent
7a27fbc001
commit
e0913a39ab
@ -12,6 +12,9 @@ class SymbolTable : StNode("", StNodeType.GLOBAL, Position.DUMMY) {
|
||||
* The table as a flat mapping of scoped names to the StNode.
|
||||
* This gives the fastest lookup possible (no need to traverse tree nodes)
|
||||
*/
|
||||
|
||||
// TODO key as dotted string instead of list
|
||||
|
||||
val flat: Map<List<String>, StNode> by lazy {
|
||||
val result = mutableMapOf<List<String>, StNode>()
|
||||
fun flatten(node: StNode) {
|
||||
@ -88,13 +91,13 @@ open class StNode(val name: String,
|
||||
parent.scopedName + name
|
||||
}
|
||||
|
||||
fun lookup(name: String) =
|
||||
lookupUnqualified(name)
|
||||
open fun lookup(scopedName: List<String>) =
|
||||
if(scopedName.size>1) lookupQualified(scopedName) else lookupUnqualified(scopedName[0])
|
||||
fun lookupOrElse(name: String, default: () -> StNode) =
|
||||
|
||||
fun lookupUnqualifiedOrElse(name: String, default: () -> StNode) =
|
||||
lookupUnqualified(name) ?: default()
|
||||
fun lookupOrElse(scopedName: List<String>, default: () -> StNode) =
|
||||
|
||||
fun lookupUnqualifiedOrElse(scopedName: List<String>, default: () -> StNode) =
|
||||
lookup(scopedName) ?: default()
|
||||
|
||||
private fun lookupQualified(scopedName: List<String>): StNode? {
|
||||
@ -112,7 +115,7 @@ open class StNode(val name: String,
|
||||
return node
|
||||
}
|
||||
|
||||
private fun lookupUnqualified(name: String): StNode? {
|
||||
fun lookupUnqualified(name: String): StNode? {
|
||||
// first consider the builtin functions
|
||||
var globalscope = this
|
||||
while(globalscope.type!= StNodeType.GLOBAL)
|
||||
@ -215,7 +218,7 @@ class StRomSub(name: String,
|
||||
|
||||
class StSubroutineParameter(val name: String, val type: DataType)
|
||||
class StRomSubParameter(val register: RegisterOrStatusflag, val type: DataType)
|
||||
class StArrayElement(val number: Double?, val addressOf: List<String>?)
|
||||
class StArrayElement(val number: Double?, val addressOfSymbol: String?)
|
||||
|
||||
typealias StString = Pair<String, Encoding>
|
||||
typealias StArray = List<StArrayElement>
|
||||
|
@ -1,6 +1,8 @@
|
||||
package prog8.code.ast
|
||||
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.IMemSizer
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.Position
|
||||
import java.nio.file.Path
|
||||
|
||||
// New simplified AST for the code generator.
|
||||
@ -43,14 +45,14 @@ class PtNodeGroup : PtNode(Position.DUMMY) {
|
||||
|
||||
|
||||
sealed class PtNamedNode(val name: String, position: Position): PtNode(position) {
|
||||
val scopedName: List<String> by lazy {
|
||||
val scopedName: String by lazy {
|
||||
var namedParent: PtNode = this.parent
|
||||
if(namedParent is PtProgram)
|
||||
listOf(name)
|
||||
name
|
||||
else {
|
||||
while (namedParent !is PtNamedNode)
|
||||
namedParent = namedParent.parent
|
||||
namedParent.scopedName + name
|
||||
namedParent.scopedName + "." + name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
is PtArrayIndexer -> other is PtArrayIndexer && other.type==type && other.variable isSameAs variable && other.index isSameAs index
|
||||
is PtBinaryExpression -> other is PtBinaryExpression && other.left isSameAs left && other.right isSameAs right
|
||||
is PtContainmentCheck -> other is PtContainmentCheck && other.type==type && other.element isSameAs element && other.iterable isSameAs iterable
|
||||
is PtIdentifier -> other is PtIdentifier && other.type==type && other.targetName==targetName
|
||||
is PtIdentifier -> other is PtIdentifier && other.type==type && other.name==name
|
||||
is PtMachineRegister -> other is PtMachineRegister && other.type==type && other.register==register
|
||||
is PtMemoryByte -> other is PtMemoryByte && other.address isSameAs address
|
||||
is PtNumber -> other is PtNumber && other.type==type && other.number==number
|
||||
@ -108,7 +108,7 @@ class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, posit
|
||||
}
|
||||
|
||||
|
||||
class PtFunctionCall(val functionName: List<String>,
|
||||
class PtFunctionCall(val name: String,
|
||||
val void: Boolean,
|
||||
type: DataType,
|
||||
position: Position) : PtExpression(type, position) {
|
||||
@ -120,14 +120,14 @@ class PtFunctionCall(val functionName: List<String>,
|
||||
val args: List<PtExpression>
|
||||
get() = children.map { it as PtExpression }
|
||||
override fun printProperties() {
|
||||
print("${functionName.joinToString(".")} void=$void")
|
||||
print("$name void=$void")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PtIdentifier(val ref: List<String>, val targetName: List<String>, type: DataType, position: Position) : PtExpression(type, position) {
|
||||
class PtIdentifier(val name: String, type: DataType, position: Position) : PtExpression(type, position) {
|
||||
override fun printProperties() {
|
||||
print("$ref --> $targetName $type")
|
||||
print("$name $type")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ class PtAssignment(position: Position) : PtNode(position) {
|
||||
}
|
||||
false
|
||||
}
|
||||
is PtIdentifier -> target is PtIdentifier && target.type==source.type && target.targetName==source.targetName
|
||||
is PtIdentifier -> target is PtIdentifier && target.type==source.type && target.name==source.name
|
||||
is PtMachineRegister -> target is PtMachineRegister && target.register==source.register
|
||||
is PtMemoryByte -> target is PtMemoryByte && target.address isSameAs source.address
|
||||
is PtNumber -> target is PtNumber && target.type == source.type && target.number==source.number
|
||||
@ -74,7 +74,7 @@ class PtAssignment(position: Position) : PtNode(position) {
|
||||
is PtPrefix -> {
|
||||
(target is PtPrefix && target.operator==source.operator && target.value isSameAs source.value)
|
||||
||
|
||||
(target is PtIdentifier && (source.value as? PtIdentifier)?.targetName==target.targetName)
|
||||
(target is PtIdentifier && (source.value as? PtIdentifier)?.name==target.name)
|
||||
}
|
||||
is PtTypeCast -> target is PtTypeCast && target.type==source.type && target.value isSameAs source.value
|
||||
is PtBinaryExpression ->
|
||||
|
@ -450,7 +450,7 @@ private fun getAddressArg(line: String, program: Program): UInt? {
|
||||
val identMatch = identifierRegex.find(loadArg)
|
||||
if(identMatch!=null) {
|
||||
val identifier = identMatch.value
|
||||
val decl = program.toplevelModule.lookup(identifier.split(".")) as? VarDecl
|
||||
val decl = program.toplevelModule.lookup(identifier.split('.')) as? VarDecl
|
||||
if(decl!=null) {
|
||||
when(decl.type){
|
||||
VarDeclType.VAR -> null
|
||||
|
@ -223,7 +223,7 @@ internal class ProgramAndVarsGen(
|
||||
scope.children.filter { it.value.type in arrayOf(StNodeType.STATICVAR, StNodeType.CONSTANT, StNodeType.MEMVAR) }
|
||||
|
||||
private fun createBlockVariables(block: Block) {
|
||||
val scope = symboltable.lookupOrElse(block.name) { throw AssemblyError("lookup") }
|
||||
val scope = symboltable.lookupUnqualifiedOrElse(block.name) { throw AssemblyError("lookup") }
|
||||
require(scope.type==StNodeType.BLOCK)
|
||||
val varsInBlock = getVars(scope)
|
||||
|
||||
@ -286,7 +286,7 @@ internal class ProgramAndVarsGen(
|
||||
// regular subroutine
|
||||
asmgen.out("${sub.name}\t$asmStartScope")
|
||||
|
||||
val scope = symboltable.lookupOrElse(sub.scopedName) { throw AssemblyError("lookup") }
|
||||
val scope = symboltable.lookupUnqualifiedOrElse(sub.scopedName) { throw AssemblyError("lookup") }
|
||||
require(scope.type==StNodeType.SUBROUTINE)
|
||||
val varsInSubroutine = getVars(scope)
|
||||
|
||||
@ -620,8 +620,8 @@ internal class ProgramAndVarsGen(
|
||||
if(it.number!=null) {
|
||||
"$" + it.number!!.toInt().toString(16).padStart(4, '0')
|
||||
}
|
||||
else if(it.addressOf!=null) {
|
||||
asmgen.asmSymbolName(it.addressOf!!)
|
||||
else if(it.addressOfSymbol!=null) {
|
||||
asmgen.asmSymbolName(it.addressOfSymbol!!)
|
||||
}
|
||||
else
|
||||
throw AssemblyError("weird array elt")
|
||||
|
@ -24,7 +24,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val array = assignment.target.array
|
||||
|
||||
return if(ident!=null) {
|
||||
assignSelfInMemory(ident.targetName.joinToString("."), assignment.value, assignment)
|
||||
assignSelfInMemory(ident.name, assignment.value, assignment)
|
||||
} else if(memory != null) {
|
||||
if(memory.address is PtNumber)
|
||||
assignSelfInMemoryKnownAddress((memory.address as PtNumber).number.toInt(), assignment.value, assignment)
|
||||
@ -186,20 +186,19 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
}
|
||||
}
|
||||
if(ident!=null) {
|
||||
val symbol = ident.targetName.joinToString(".")
|
||||
val instruction = if(zero) {
|
||||
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = ident.name)
|
||||
} else {
|
||||
if (vmDt == IRDataType.FLOAT)
|
||||
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = ident.name)
|
||||
else
|
||||
IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = ident.name)
|
||||
}
|
||||
result += IRCodeChunk(null, null).also { it += instruction }
|
||||
return result
|
||||
}
|
||||
else if(array!=null) {
|
||||
val variable = array.variable.targetName.joinToString(".")
|
||||
val variable = array.variable.name
|
||||
val itemsize = codeGen.program.memsizer.memorySize(array.type)
|
||||
|
||||
if(array.variable.type==DataType.UWORD) {
|
||||
|
@ -60,7 +60,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.name.split('.')) as StStaticVariable
|
||||
val syscall =
|
||||
when (array.dt) {
|
||||
DataType.ARRAY_UB,
|
||||
@ -83,7 +83,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
private fun funcAll(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.name.split('.')) as StStaticVariable
|
||||
val syscall =
|
||||
when(array.dt) {
|
||||
DataType.ARRAY_UB,
|
||||
@ -204,7 +204,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
private fun funcReverse(call: PtBuiltinFunctionCall): IRCodeChunks {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.name.split('.')) as StStaticVariable
|
||||
val syscall =
|
||||
when(array.dt) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> IMSyscall.REVERSE_BYTES
|
||||
@ -223,7 +223,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
private fun funcSort(call: PtBuiltinFunctionCall): IRCodeChunks {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.name.split('.')) as StStaticVariable
|
||||
val syscall =
|
||||
when(array.dt) {
|
||||
DataType.ARRAY_UB -> IMSyscall.SORT_UBYTE
|
||||
|
@ -39,22 +39,21 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val vmDt = codeGen.irType(expr.type)
|
||||
val symbol = expr.targetName.joinToString(".")
|
||||
val code = IRCodeChunk(null, null)
|
||||
code += if (expr.type in PassByValueDatatypes) {
|
||||
if(vmDt==IRDataType.FLOAT)
|
||||
IRInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = expr.name)
|
||||
else
|
||||
IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = expr.name)
|
||||
} else {
|
||||
// for strings and arrays etc., load the *address* of the value instead
|
||||
IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = expr.name)
|
||||
}
|
||||
listOf(code)
|
||||
}
|
||||
is PtAddressOf -> {
|
||||
val vmDt = codeGen.irType(expr.type)
|
||||
val symbol = expr.identifier.targetName.joinToString(".")
|
||||
val symbol = expr.identifier.name
|
||||
// note: LOAD <symbol> gets you the address of the symbol, whereas LOADM <symbol> would get you the value stored at that location
|
||||
val code = IRCodeChunk(null, null)
|
||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = symbol)
|
||||
@ -89,7 +88,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
private fun translate(check: PtContainmentCheck, resultRegister: Int, resultFpRegister: Int): IRCodeChunks {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
result += translateExpression(check.element, resultRegister, -1) // load the element to check in resultRegister
|
||||
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
|
||||
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.name.split('.')) as StStaticVariable
|
||||
when(iterable.dt) {
|
||||
DataType.STR -> {
|
||||
result += translateExpression(check.element, SyscallRegisterBase, -1)
|
||||
@ -121,7 +120,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported")
|
||||
else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.targetName}")
|
||||
else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.name}")
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -131,7 +130,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val vmDt = codeGen.irType(arrayIx.type)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val idxReg = codeGen.registers.nextFree()
|
||||
val arrayVarSymbol = arrayIx.variable.targetName.joinToString(".")
|
||||
val arrayVarSymbol = arrayIx.variable.name
|
||||
|
||||
if(arrayIx.variable.type==DataType.UWORD) {
|
||||
// indexing a pointer var instead of a real array or string
|
||||
@ -932,12 +931,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
|
||||
fun translate(fcall: PtFunctionCall, resultRegister: Int, resultFpRegister: Int): IRCodeChunks {
|
||||
when (val callTarget = codeGen.symbolTable.flat.getValue(fcall.functionName)) {
|
||||
when (val callTarget = codeGen.symbolTable.flat.getValue(fcall.name.split('.'))) {
|
||||
is StSub -> {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
for ((arg, parameter) in fcall.args.zip(callTarget.parameters)) {
|
||||
val paramDt = codeGen.irType(parameter.type)
|
||||
val symbol = (fcall.functionName + parameter.name).joinToString(".")
|
||||
val symbol = "${fcall.name}.${parameter.name}"
|
||||
if(codeGen.isZero(arg)) {
|
||||
addInstr(result, IRInstruction(Opcode.STOREZM, paramDt, labelSymbol = symbol), null)
|
||||
} else {
|
||||
@ -952,7 +951,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
}
|
||||
addInstr(result, IRInstruction(Opcode.CALL, labelSymbol=fcall.functionName.joinToString(".")), null)
|
||||
addInstr(result, IRInstruction(Opcode.CALL, labelSymbol=fcall.name), null)
|
||||
if(fcall.type==DataType.FLOAT) {
|
||||
if (!fcall.void && resultFpRegister != 0) {
|
||||
// Call convention: result value is in fr0, so put it in the required register instead.
|
||||
|
@ -170,7 +170,7 @@ class IRCodeGen(
|
||||
flattenRecurse(program)
|
||||
|
||||
renameLabels.forEach { (parent, label) ->
|
||||
val renamedLabel = PtLabel(label.scopedName.joinToString("."), label.position)
|
||||
val renamedLabel = PtLabel(label.scopedName, label.position)
|
||||
val idx = parent.children.indexOf(label)
|
||||
parent.children.removeAt(idx)
|
||||
parent.children.add(idx, renamedLabel)
|
||||
@ -188,7 +188,7 @@ class IRCodeGen(
|
||||
val renameAsmSubs = mutableListOf<Pair<PtBlock, PtAsmSub>>()
|
||||
|
||||
fun flattenNestedAsmSub(block: PtBlock, parentSub: PtSub, asmsub: PtAsmSub) {
|
||||
val flattened = PtAsmSub(asmsub.scopedName.joinToString("."),
|
||||
val flattened = PtAsmSub(asmsub.scopedName,
|
||||
asmsub.address,
|
||||
asmsub.clobbers,
|
||||
asmsub.parameters,
|
||||
@ -204,7 +204,7 @@ class IRCodeGen(
|
||||
fun flattenNestedSub(block: PtBlock, parentSub: PtSub, sub: PtSub) {
|
||||
sub.children.filterIsInstance<PtSub>().forEach { subsub->flattenNestedSub(block, sub, subsub) }
|
||||
sub.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsmSub(block, sub, asmsubsub) }
|
||||
val flattened = PtSub(sub.scopedName.joinToString("."),
|
||||
val flattened = PtSub(sub.scopedName,
|
||||
sub.parameters,
|
||||
sub.returntype,
|
||||
sub.inline,
|
||||
@ -232,13 +232,13 @@ class IRCodeGen(
|
||||
flattenedSubs.forEach { (block, sub) -> block.add(sub) }
|
||||
flattenedAsmSubs.forEach { (block, asmsub) -> block.add(asmsub) }
|
||||
renameSubs.forEach { (parent, sub) ->
|
||||
val renamedSub = PtSub(sub.scopedName.joinToString("."), sub.parameters, sub.returntype, sub.inline, sub.position)
|
||||
val renamedSub = PtSub(sub.scopedName, sub.parameters, sub.returntype, sub.inline, sub.position)
|
||||
sub.children.forEach { renamedSub.add(it) }
|
||||
val subindex = parent.children.indexOf(sub)
|
||||
parent.children[subindex] = renamedSub // keep the order of nodes the same
|
||||
}
|
||||
renameAsmSubs.forEach { (parent, sub) ->
|
||||
val renamedSub = PtAsmSub(sub.scopedName.joinToString("."),
|
||||
val renamedSub = PtAsmSub(sub.scopedName,
|
||||
sub.address,
|
||||
sub.clobbers,
|
||||
sub.parameters,
|
||||
@ -338,7 +338,7 @@ class IRCodeGen(
|
||||
}
|
||||
addInstr(result, branchIns, null)
|
||||
} else {
|
||||
val label = if(goto.generatedLabel!=null) goto.generatedLabel else goto.identifier!!.targetName.joinToString(".")
|
||||
val label = if(goto.generatedLabel!=null) goto.generatedLabel else goto.identifier!!.name
|
||||
val branchIns = when(branch.condition) {
|
||||
BranchCondition.CS -> IRInstruction(Opcode.BSTCS, labelSymbol = label)
|
||||
BranchCondition.CC -> IRInstruction(Opcode.BSTCC, labelSymbol = label)
|
||||
@ -454,7 +454,7 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
private fun translate(forLoop: PtForLoop): IRCodeChunks {
|
||||
val loopvar = symbolTable.lookup(forLoop.variable.targetName)!!
|
||||
val loopvar = symbolTable.lookup(forLoop.variable.name.split('.'))!!
|
||||
val iterable = forLoop.iterable
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
when(iterable) {
|
||||
@ -465,8 +465,7 @@ class IRCodeGen(
|
||||
result += translateForInNonConstantRange(forLoop, loopvar)
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val symbol = iterable.targetName.joinToString(".")
|
||||
val iterableVar = symbolTable.lookup(iterable.targetName) as StStaticVariable
|
||||
val iterableVar = symbolTable.lookup(iterable.name.split('.')) as StStaticVariable
|
||||
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
||||
val indexReg = registers.nextFree()
|
||||
val tmpReg = registers.nextFree()
|
||||
@ -476,7 +475,7 @@ class IRCodeGen(
|
||||
// iterate over a zero-terminated string
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=indexReg, value=0), null)
|
||||
val chunk = IRCodeChunk(loopLabel, null)
|
||||
chunk += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = symbol)
|
||||
chunk += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = iterable.name)
|
||||
chunk += IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel)
|
||||
chunk += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
result += chunk
|
||||
@ -498,7 +497,7 @@ class IRCodeGen(
|
||||
chunk += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=lengthReg, value=lengthBytes)
|
||||
result += chunk
|
||||
val chunk2 = IRCodeChunk(loopLabel, null)
|
||||
chunk2 += IRInstruction(Opcode.LOADX, irType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
chunk2 += IRInstruction(Opcode.LOADX, irType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=iterable.name)
|
||||
chunk2 += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
result += chunk2
|
||||
result += translateNode(forLoop.statements)
|
||||
@ -507,7 +506,7 @@ class IRCodeGen(
|
||||
} else if(lengthBytes==256) {
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=indexReg, value=0), null)
|
||||
val chunk = IRCodeChunk(loopLabel, null)
|
||||
chunk += IRInstruction(Opcode.LOADX, irType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
chunk += IRInstruction(Opcode.LOADX, irType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=iterable.name)
|
||||
chunk += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
result += chunk
|
||||
result += translateNode(forLoop.statements)
|
||||
@ -962,7 +961,7 @@ class IRCodeGen(
|
||||
else if(goto.generatedLabel!=null)
|
||||
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, labelSymbol = goto.generatedLabel), null)
|
||||
else
|
||||
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, labelSymbol = goto.identifier!!.targetName.joinToString(".")), null)
|
||||
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, labelSymbol = goto.identifier!!.name), null)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -1094,7 +1093,7 @@ class IRCodeGen(
|
||||
val irDt = irType(postIncrDecr.target.type)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
if(ident!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.targetName.joinToString(".")), null)
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
|
||||
} else if(memory!=null) {
|
||||
if(memory.address is PtNumber) {
|
||||
val address = (memory.address as PtNumber).number.toInt()
|
||||
@ -1110,7 +1109,7 @@ class IRCodeGen(
|
||||
result += chunk
|
||||
}
|
||||
} else if (array!=null) {
|
||||
val variable = array.variable.targetName.joinToString(".")
|
||||
val variable = array.variable.name
|
||||
val itemsize = program.memsizer.memorySize(array.type)
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(fixedIndex!=null) {
|
||||
@ -1166,7 +1165,7 @@ class IRCodeGen(
|
||||
if (jump.generatedLabel != null)
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
|
||||
else if (jump.identifier != null)
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.targetName.joinToString("."))
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name)
|
||||
else
|
||||
throw AssemblyError("weird jump")
|
||||
}
|
||||
@ -1248,9 +1247,9 @@ class IRCodeGen(
|
||||
|
||||
private fun translate(parameters: List<PtSubroutineParameter>) =
|
||||
parameters.map {
|
||||
val flattenedName = (it.definingSub()!!.scopedName + it.name)
|
||||
val orig = symbolTable.flat.getValue(flattenedName) as StStaticVariable
|
||||
IRSubroutine.IRParam(flattenedName.joinToString("."), orig.dt)
|
||||
val flattenedName = it.definingSub()!!.scopedName + "." + it.name
|
||||
val orig = symbolTable.flat.getValue(flattenedName.split('.')) as StStaticVariable
|
||||
IRSubroutine.IRParam(flattenedName, orig.dt)
|
||||
}
|
||||
|
||||
private fun translate(alignment: PtBlock.BlockAlignment): IRBlock.BlockAlignment {
|
||||
|
@ -111,19 +111,19 @@ class IntermediateAstMaker(private val program: Program, private val symbolTable
|
||||
return target
|
||||
}
|
||||
|
||||
private fun targetOf(identifier: IdentifierReference): Pair<List<String>, DataType> {
|
||||
private fun targetOf(identifier: IdentifierReference): Pair<String, DataType> {
|
||||
val target=identifier.targetStatement(program)!! as INamedStatement
|
||||
val targetname = if(target.name in program.builtinFunctions.names)
|
||||
listOf("<builtin>", target.name)
|
||||
val targetname: String = if(target.name in program.builtinFunctions.names)
|
||||
"<builtin>.${target.name}"
|
||||
else
|
||||
target.scopedName
|
||||
target.scopedName.joinToString(".")
|
||||
val type = identifier.inferType(program).getOr(DataType.UNDEFINED)
|
||||
return Pair(targetname, type)
|
||||
}
|
||||
|
||||
private fun transform(identifier: IdentifierReference): PtIdentifier {
|
||||
val (target, type) = targetOf(identifier)
|
||||
return PtIdentifier(identifier.nameInSource, target, type, identifier.position)
|
||||
return PtIdentifier(target, type, identifier.position)
|
||||
}
|
||||
|
||||
private fun transform(srcBlock: Block): PtBlock {
|
||||
|
@ -104,8 +104,8 @@ internal class SymbolTableMaker: IAstVisitor {
|
||||
return null
|
||||
return arrayLit.value.map {
|
||||
when(it){
|
||||
is AddressOf -> StArrayElement(null, it.identifier.nameInSource)
|
||||
is IdentifierReference -> StArrayElement(null, it.nameInSource)
|
||||
is AddressOf -> StArrayElement(null, it.identifier.nameInSource.joinToString("."))
|
||||
is IdentifierReference -> StArrayElement(null, it.nameInSource.joinToString("."))
|
||||
is NumericLiteral -> StArrayElement(it.number, null)
|
||||
else -> throw FatalAstException("weird element dt in array literal")
|
||||
}
|
||||
|
@ -30,41 +30,41 @@ class TestSymbolTable: FunSpec({
|
||||
|
||||
test("symboltable global lookups") {
|
||||
val st = makeSt()
|
||||
st.lookup("undefined") shouldBe null
|
||||
st.lookupUnqualified("undefined") shouldBe null
|
||||
st.lookup(listOf("undefined")) shouldBe null
|
||||
var default = st.lookupOrElse("undefined") { StNode("default", StNodeType.LABEL, Position.DUMMY) }
|
||||
var default = st.lookupUnqualifiedOrElse("undefined") { StNode("default", StNodeType.LABEL, Position.DUMMY) }
|
||||
default.name shouldBe "default"
|
||||
default = st.lookupOrElse(listOf("undefined")) { StNode("default", StNodeType.LABEL, Position.DUMMY) }
|
||||
default = st.lookupUnqualifiedOrElse(listOf("undefined")) { StNode("default", StNodeType.LABEL, Position.DUMMY) }
|
||||
default.name shouldBe "default"
|
||||
|
||||
val msbFunc = st.lookupOrElse("msb") { fail("msb must be found") }
|
||||
val msbFunc = st.lookupUnqualifiedOrElse("msb") { fail("msb must be found") }
|
||||
msbFunc.type shouldBe StNodeType.BUILTINFUNC
|
||||
|
||||
val variable = st.lookupOrElse(listOf("block1", "sub2", "v2")) { fail("v2 must be found") }
|
||||
val variable = st.lookupUnqualifiedOrElse(listOf("block1", "sub2", "v2")) { fail("v2 must be found") }
|
||||
variable.type shouldBe StNodeType.STATICVAR
|
||||
}
|
||||
|
||||
test("symboltable nested lookups") {
|
||||
val st = makeSt()
|
||||
|
||||
val sub1 = st.lookupOrElse(listOf("block1", "sub1")) { fail("should find sub1") }
|
||||
val sub1 = st.lookupUnqualifiedOrElse(listOf("block1", "sub1")) { fail("should find sub1") }
|
||||
sub1.name shouldBe "sub1"
|
||||
sub1.scopedName shouldBe listOf("block1", "sub1")
|
||||
sub1.type shouldBe StNodeType.SUBROUTINE
|
||||
sub1.children.size shouldBe 2
|
||||
|
||||
val v1 = sub1.lookupOrElse("v1") { fail("v1 must be found") } as StStaticVariable
|
||||
val v1 = sub1.lookupUnqualifiedOrElse("v1") { fail("v1 must be found") } as StStaticVariable
|
||||
v1.type shouldBe StNodeType.STATICVAR
|
||||
v1.name shouldBe "v1"
|
||||
v1.dt shouldBe DataType.BYTE
|
||||
|
||||
val blockc = sub1.lookupOrElse("blockc") { fail("blockc") } as StConstant
|
||||
val blockc = sub1.lookupUnqualifiedOrElse("blockc") { fail("blockc") } as StConstant
|
||||
blockc.type shouldBe StNodeType.CONSTANT
|
||||
blockc.value shouldBe 999.0
|
||||
|
||||
val subsub = st.lookupOrElse(listOf("block2", "sub2", "subsub")) { fail("should find subsub") }
|
||||
subsub.lookup("blockc") shouldBe null
|
||||
subsub.lookup("label") shouldNotBe null
|
||||
val subsub = st.lookupUnqualifiedOrElse(listOf("block2", "sub2", "subsub")) { fail("should find subsub") }
|
||||
subsub.lookupUnqualified("blockc") shouldBe null
|
||||
subsub.lookupUnqualified("label") shouldNotBe null
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -45,20 +45,20 @@ class TestIntermediateAst: FunSpec({
|
||||
val entry = ast.entrypoint() ?: fail("no main.start() found")
|
||||
entry.children.size shouldBe 4
|
||||
entry.name shouldBe "start"
|
||||
entry.scopedName shouldBe listOf("main", "start")
|
||||
entry.scopedName shouldBe "main.start"
|
||||
val blocks = ast.allBlocks().toList()
|
||||
blocks.size shouldBeGreaterThan 1
|
||||
blocks[0].name shouldBe "main"
|
||||
blocks[0].scopedName shouldBe listOf("main")
|
||||
blocks[0].scopedName shouldBe "main"
|
||||
|
||||
val vars = entry.children[0] as PtScopeVarsDecls
|
||||
val ccInit = entry.children[1] as PtAssignment
|
||||
ccInit.target.identifier?.targetName shouldBe listOf("main","start","cc")
|
||||
ccInit.target.identifier?.name shouldBe "main.start.cc"
|
||||
(ccInit.value as PtNumber).number shouldBe 0.0
|
||||
|
||||
val ccdecl = vars.children[0] as PtVariable
|
||||
ccdecl.name shouldBe "cc"
|
||||
ccdecl.scopedName shouldBe listOf("main", "start", "cc")
|
||||
ccdecl.scopedName shouldBe "main.start.cc"
|
||||
ccdecl.type shouldBe DataType.UBYTE
|
||||
val arraydecl = vars.children[1] as PtVariable
|
||||
arraydecl.name shouldBe "array"
|
||||
|
@ -3,6 +3,8 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- optimize scoped symbols: .split('.') / .joinToString(".")
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -221,7 +221,7 @@ class IRFileReader {
|
||||
bss = false
|
||||
initArray = value.split(',').map {
|
||||
if (it.startsWith('@'))
|
||||
StArrayElement(null, it.drop(1).split('.'))
|
||||
StArrayElement(null, it.drop(1))
|
||||
else
|
||||
StArrayElement(parseIRValue(it).toDouble(), null)
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
if(it.number!=null)
|
||||
it.number!!.toInt().toHex()
|
||||
else
|
||||
"@${it.addressOf!!.joinToString(".")}"
|
||||
"@${it.addressOfSymbol}"
|
||||
}
|
||||
} else {
|
||||
"" // array will be zero'd out at program start
|
||||
|
@ -27,9 +27,9 @@ class IRSymbolTable(sourceSt: SymbolTable?) {
|
||||
allVariables().forEach {variable ->
|
||||
variable.onetimeInitializationArrayValue?.let {
|
||||
it.forEach { arrayElt ->
|
||||
if(arrayElt.addressOf!=null) {
|
||||
require(arrayElt.addressOf!!.size > 1) {
|
||||
"pointer var in array should be properly scoped: ${arrayElt.addressOf!!} in ${variable.name}"
|
||||
if(arrayElt.addressOfSymbol!=null) {
|
||||
require(arrayElt.addressOfSymbol!!.contains('.')) {
|
||||
"pointer var in array should be properly scoped: ${arrayElt.addressOfSymbol} in ${variable.name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,9 +61,9 @@ class IRSymbolTable(sourceSt: SymbolTable?) {
|
||||
return null
|
||||
val newArray = mutableListOf<StArrayElement>()
|
||||
array.forEach {
|
||||
if(it.addressOf!=null) {
|
||||
val target = variable.lookup(it.addressOf!!)!!
|
||||
newArray.add(StArrayElement(null, target.scopedName))
|
||||
if(it.addressOfSymbol!=null) {
|
||||
val target = variable.lookup(it.addressOfSymbol!!.split('.'))!!
|
||||
newArray.add(StArrayElement(null, target.scopedName.joinToString(".")))
|
||||
} else {
|
||||
newArray.add(it)
|
||||
}
|
||||
|
@ -284,10 +284,10 @@ class VmProgramLoader {
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
for(elt in it) {
|
||||
if(elt.addressOf!=null) {
|
||||
val name = elt.addressOf!!.joinToString(".")
|
||||
if(elt.addressOfSymbol!=null) {
|
||||
val name = elt.addressOfSymbol!!
|
||||
val symbolAddress = symbolAddresses[name]
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: ${name}") // TODO
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name") // TODO
|
||||
memory.setUW(addr, symbolAddress.toUShort())
|
||||
} else {
|
||||
memory.setUW(addr, elt.number!!.toInt().toUShort())
|
||||
|
Loading…
Reference in New Issue
Block a user