optimizing

This commit is contained in:
Irmen de Jong 2022-12-30 18:07:53 +01:00
parent 7a27fbc001
commit e0913a39ab
19 changed files with 99 additions and 95 deletions

View File

@ -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>

View File

@ -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
}
}
}

View File

@ -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")
}
}

View File

@ -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 ->

View File

@ -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

View File

@ -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")

View File

@ -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) {

View File

@ -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

View File

@ -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.

View File

@ -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 {

View File

@ -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 {

View File

@ -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")
}

View File

@ -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
}
})

View File

@ -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"

View File

@ -3,6 +3,8 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- optimize scoped symbols: .split('.') / .joinToString(".")
...

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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())