From e0913a39ab14fd42323d2aa93922c5e3167d55b3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 30 Dec 2022 18:07:53 +0100 Subject: [PATCH] optimizing --- codeCore/src/prog8/code/SymbolTable.kt | 15 +++++--- codeCore/src/prog8/code/ast/AstBase.kt | 10 +++-- codeCore/src/prog8/code/ast/AstExpressions.kt | 10 ++--- codeCore/src/prog8/code/ast/AstStatements.kt | 4 +- .../src/prog8/codegen/cpu6502/AsmOptimizer.kt | 2 +- .../codegen/cpu6502/ProgramAndVarsGen.kt | 8 ++-- .../codegen/intermediate/AssignmentGen.kt | 11 +++--- .../codegen/intermediate/BuiltinFuncGen.kt | 8 ++-- .../codegen/intermediate/ExpressionGen.kt | 21 +++++------ .../prog8/codegen/intermediate/IRCodeGen.kt | 37 +++++++++---------- .../astprocessing/IntermediateAstMaker.kt | 10 ++--- .../astprocessing/SymbolTableMaker.kt | 4 +- compiler/test/TestSymbolTable.kt | 22 +++++------ compiler/test/ast/TestIntermediateAst.kt | 8 ++-- docs/source/todo.rst | 2 + .../src/prog8/intermediate/IRFileReader.kt | 2 +- .../src/prog8/intermediate/IRFileWriter.kt | 2 +- .../src/prog8/intermediate/IRSymbolTable.kt | 12 +++--- .../src/prog8/vm/VmProgramLoader.kt | 6 +-- 19 files changed, 99 insertions(+), 95 deletions(-) diff --git a/codeCore/src/prog8/code/SymbolTable.kt b/codeCore/src/prog8/code/SymbolTable.kt index 1abc222bb..3f8f218df 100644 --- a/codeCore/src/prog8/code/SymbolTable.kt +++ b/codeCore/src/prog8/code/SymbolTable.kt @@ -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, StNode> by lazy { val result = mutableMapOf, 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) = 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, default: () -> StNode) = + + fun lookupUnqualifiedOrElse(scopedName: List, default: () -> StNode) = lookup(scopedName) ?: default() private fun lookupQualified(scopedName: List): 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?) +class StArrayElement(val number: Double?, val addressOfSymbol: String?) typealias StString = Pair typealias StArray = List diff --git a/codeCore/src/prog8/code/ast/AstBase.kt b/codeCore/src/prog8/code/ast/AstBase.kt index fb665f6bb..c2e619227 100644 --- a/codeCore/src/prog8/code/ast/AstBase.kt +++ b/codeCore/src/prog8/code/ast/AstBase.kt @@ -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 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 } } } diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 11d92603d..1e1cbe084 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -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, +class PtFunctionCall(val name: String, val void: Boolean, type: DataType, position: Position) : PtExpression(type, position) { @@ -120,14 +120,14 @@ class PtFunctionCall(val functionName: List, val args: List get() = children.map { it as PtExpression } override fun printProperties() { - print("${functionName.joinToString(".")} void=$void") + print("$name void=$void") } } -class PtIdentifier(val ref: List, val targetName: List, 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") } } diff --git a/codeCore/src/prog8/code/ast/AstStatements.kt b/codeCore/src/prog8/code/ast/AstStatements.kt index 32aa8d24c..94a7cf328 100644 --- a/codeCore/src/prog8/code/ast/AstStatements.kt +++ b/codeCore/src/prog8/code/ast/AstStatements.kt @@ -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 -> diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt index c63b00ebe..41cd9a00e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt @@ -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 diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index fcd61da8a..d0820ad6e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -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") diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 302427406..e5b2b0428 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -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) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 4678e12ff..3699e0b7f 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -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 diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 4f140f37a..6d3a19ebe 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -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 gets you the address of the symbol, whereas LOADM 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() 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() 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() 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. diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 7cd782bf2..8147c3881 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -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>() 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().forEach { subsub->flattenNestedSub(block, sub, subsub) } sub.children.filterIsInstance().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() 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() 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) = 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 { diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index d2531d7f0..4d73890b3 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -111,19 +111,19 @@ class IntermediateAstMaker(private val program: Program, private val symbolTable return target } - private fun targetOf(identifier: IdentifierReference): Pair, DataType> { + private fun targetOf(identifier: IdentifierReference): Pair { val target=identifier.targetStatement(program)!! as INamedStatement - val targetname = if(target.name in program.builtinFunctions.names) - listOf("", target.name) + val targetname: String = if(target.name in program.builtinFunctions.names) + ".${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 { diff --git a/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt b/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt index 846c8fc9f..0fb3d7051 100644 --- a/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt @@ -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") } diff --git a/compiler/test/TestSymbolTable.kt b/compiler/test/TestSymbolTable.kt index e54754a3c..95a6c3e05 100644 --- a/compiler/test/TestSymbolTable.kt +++ b/compiler/test/TestSymbolTable.kt @@ -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 } }) diff --git a/compiler/test/ast/TestIntermediateAst.kt b/compiler/test/ast/TestIntermediateAst.kt index 777abb2f9..a621d6b95 100644 --- a/compiler/test/ast/TestIntermediateAst.kt +++ b/compiler/test/ast/TestIntermediateAst.kt @@ -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" diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3c46b7546..c72f70645 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- optimize scoped symbols: .split('.') / .joinToString(".") + ... diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index fb0754daa..f3782b138 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -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) } diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index 893e10093..36244f88a 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -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 diff --git a/intermediate/src/prog8/intermediate/IRSymbolTable.kt b/intermediate/src/prog8/intermediate/IRSymbolTable.kt index ebcc491f8..d76cb982f 100644 --- a/intermediate/src/prog8/intermediate/IRSymbolTable.kt +++ b/intermediate/src/prog8/intermediate/IRSymbolTable.kt @@ -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() 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) } diff --git a/virtualmachine/src/prog8/vm/VmProgramLoader.kt b/virtualmachine/src/prog8/vm/VmProgramLoader.kt index a048026de..8de6a244a 100644 --- a/virtualmachine/src/prog8/vm/VmProgramLoader.kt +++ b/virtualmachine/src/prog8/vm/VmProgramLoader.kt @@ -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())