replace java Stack by kotlin ArrayDeque

This commit is contained in:
Irmen de Jong 2024-09-02 00:15:28 +02:00
parent 97c2dadd16
commit 2c2ae64194
8 changed files with 69 additions and 74 deletions

View File

@ -3,7 +3,8 @@ package prog8.code
import prog8.code.ast.* import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.VMTarget import prog8.code.target.VMTarget
import java.util.* import kotlin.collections.ArrayDeque
class SymbolTableMaker(private val program: PtProgram, private val options: CompilationOptions) { class SymbolTableMaker(private val program: PtProgram, private val options: CompilationOptions) {
fun make(): SymbolTable { fun make(): SymbolTable {
@ -13,8 +14,8 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
st.add(StNode(it.key, StNodeType.BUILTINFUNC, PtIdentifier(it.key, it.value.returnType ?: DataType.UNDEFINED, Position.DUMMY))) st.add(StNode(it.key, StNodeType.BUILTINFUNC, PtIdentifier(it.key, it.value.returnType ?: DataType.UNDEFINED, Position.DUMMY)))
} }
val scopestack = Stack<StNode>() val scopestack = ArrayDeque<StNode>()
scopestack.push(st) scopestack.add(st)
program.children.forEach { program.children.forEach {
addToSt(it, scopestack) addToSt(it, scopestack)
} }
@ -35,7 +36,7 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
return st return st
} }
private fun addToSt(node: PtNode, scope: Stack<StNode>) { private fun addToSt(node: PtNode, scope: ArrayDeque<StNode>) {
val stNode = when(node) { val stNode = when(node) {
is PtAsmSub -> { is PtAsmSub -> {
val parameters = node.parameters.map { StRomSubParameter(it.first, it.second.type) } val parameters = node.parameters.map { StRomSubParameter(it.first, it.second.type) }
@ -104,7 +105,7 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
val size = (node.args[1] as PtNumber).number.toUInt() val size = (node.args[1] as PtNumber).number.toUInt()
val align = (node.args[2] as PtNumber).number.toUInt() val align = (node.args[2] as PtNumber).number.toUInt()
// don't add memory slabs in nested scope, just put them in the top level of the ST // don't add memory slabs in nested scope, just put them in the top level of the ST
scope.firstElement().add(StMemorySlab("prog8_memoryslab_$slabname", size, align, node)) scope.first().add(StMemorySlab("prog8_memoryslab_$slabname", size, align, node))
} }
null null
} }
@ -112,14 +113,14 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
} }
if(stNode!=null) { if(stNode!=null) {
scope.peek().add(stNode) scope.last().add(stNode)
scope.push(stNode) scope.add(stNode)
} }
node.children.forEach { node.children.forEach {
addToSt(it, scope) addToSt(it, scope)
} }
if(stNode!=null) if(stNode!=null)
scope.pop() scope.removeLast()
} }
private fun makeInitialArray(value: PtArray): List<StArrayElement> { private fun makeInitialArray(value: PtArray): List<StArrayElement> {

View File

@ -1,7 +1,7 @@
package prog8.code.ast package prog8.code.ast
import prog8.code.core.* import prog8.code.core.*
import java.util.* import java.util.Objects
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.truncate import kotlin.math.truncate
@ -227,12 +227,6 @@ class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position)
class PtBool(val value: Boolean, position: Position) : PtExpression(DataType.BOOL, position) { class PtBool(val value: Boolean, position: Position) : PtExpression(DataType.BOOL, position) {
companion object {
fun fromNumber(number: Number, position: Position): PtBool =
PtBool(number != 0.0, position)
}
override fun hashCode(): Int = Objects.hash(type, value) override fun hashCode(): Int = Objects.hash(type, value)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -9,7 +9,7 @@ import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.Cx16Target import prog8.code.target.Cx16Target
import prog8.codegen.cpu6502.assignment.* import prog8.codegen.cpu6502.assignment.*
import java.util.* import kotlin.collections.ArrayDeque
import kotlin.io.path.Path import kotlin.io.path.Path
import kotlin.io.path.writeLines import kotlin.io.path.writeLines
@ -772,7 +772,7 @@ class AsmGen6502Internal (
private fun translate(stmt: PtRepeatLoop) { private fun translate(stmt: PtRepeatLoop) {
val endLabel = makeLabel("repeatend") val endLabel = makeLabel("repeatend")
loopEndLabels.push(endLabel) loopEndLabels.add(endLabel)
when (stmt.count) { when (stmt.count) {
is PtNumber -> { is PtNumber -> {
@ -816,7 +816,7 @@ class AsmGen6502Internal (
} }
} }
loopEndLabels.pop() loopEndLabels.removeLast()
} }
private fun repeatWordCount(iterations: Int, stmt: PtRepeatLoop) { private fun repeatWordCount(iterations: Int, stmt: PtRepeatLoop) {

View File

@ -37,7 +37,7 @@ internal class ForLoopsAsmGen(
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
val modifiedLabel = asmgen.makeLabel("for_modified") val modifiedLabel = asmgen.makeLabel("for_modified")
val modifiedLabel2 = asmgen.makeLabel("for_modifiedb") val modifiedLabel2 = asmgen.makeLabel("for_modifiedb")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val stepsize=range.step.asConstInteger()!! val stepsize=range.step.asConstInteger()!!
if(stepsize < -1) { if(stepsize < -1) {
@ -277,7 +277,7 @@ $endLabel""")
else -> throw AssemblyError("range expression can only be byte or word") else -> throw AssemblyError("range expression can only be byte or word")
} }
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun precheckFromToWord(iterableDt: DataType, stepsize: Int, fromVar: String, endLabel: String) { private fun precheckFromToWord(iterableDt: DataType, stepsize: Int, fromVar: String, endLabel: String) {
@ -333,7 +333,7 @@ $endLabel""")
private fun translateForOverIterableVar(stmt: PtForLoop, iterableDt: DataType, ident: PtIdentifier) { private fun translateForOverIterableVar(stmt: PtForLoop, iterableDt: DataType, ident: PtIdentifier) {
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val iterableName = asmgen.asmVariableName(ident) val iterableName = asmgen.asmVariableName(ident)
val numElements = when(val symbol = asmgen.symbolTable.lookup(ident.name)) { val numElements = when(val symbol = asmgen.symbolTable.lookup(ident.name)) {
is StStaticVariable -> symbol.length!! is StStaticVariable -> symbol.length!!
@ -477,7 +477,7 @@ $loopLabel sty $indexVar
} }
else -> throw AssemblyError("can't iterate over $iterableDt") else -> throw AssemblyError("can't iterate over $iterableDt")
} }
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun translateForOverConstRange(stmt: PtForLoop, iterableDt: DataType, range: IntProgression) { private fun translateForOverConstRange(stmt: PtForLoop, iterableDt: DataType, range: IntProgression) {
@ -495,7 +495,7 @@ $loopLabel sty $indexVar
// not one of the easy cases, generate more complex code... // not one of the easy cases, generate more complex code...
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
when(iterableDt) { when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> { DataType.ARRAY_B, DataType.ARRAY_UB -> {
// loop over byte range via loopvar, step >= 2 or <= -2 // loop over byte range via loopvar, step >= 2 or <= -2
@ -601,13 +601,13 @@ $loopLabel""")
} }
else -> throw AssemblyError("range expression can only be byte or word") else -> throw AssemblyError("range expression can only be byte or word")
} }
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun translateForSimpleByteRangeAsc(stmt: PtForLoop, range: IntProgression) { private fun translateForSimpleByteRangeAsc(stmt: PtForLoop, range: IntProgression) {
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val varname = asmgen.asmVariableName(stmt.variable) val varname = asmgen.asmVariableName(stmt.variable)
asmgen.out(""" asmgen.out("""
lda #${range.first} lda #${range.first}
@ -627,13 +627,13 @@ $endLabel""")
bne $loopLabel bne $loopLabel
$endLabel""") $endLabel""")
} }
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun translateForSimpleByteRangeDesc(stmt: PtForLoop, range: IntProgression) { private fun translateForSimpleByteRangeDesc(stmt: PtForLoop, range: IntProgression) {
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val varname = asmgen.asmVariableName(stmt.variable) val varname = asmgen.asmVariableName(stmt.variable)
asmgen.out(""" asmgen.out("""
lda #${range.first} lda #${range.first}
@ -664,13 +664,13 @@ $endLabel""")
$endLabel""") $endLabel""")
} }
} }
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun translateForSimpleWordRangeAsc(stmt: PtForLoop, range: IntProgression) { private fun translateForSimpleWordRangeAsc(stmt: PtForLoop, range: IntProgression) {
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val varname = asmgen.asmVariableName(stmt.variable) val varname = asmgen.asmVariableName(stmt.variable)
asmgen.out(""" asmgen.out("""
lda #<${range.first} lda #<${range.first}
@ -691,13 +691,13 @@ $loopLabel""")
inc $varname+1""") inc $varname+1""")
asmgen.jmp(loopLabel) asmgen.jmp(loopLabel)
asmgen.out(endLabel) asmgen.out(endLabel)
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun translateForSimpleWordRangeDesc(stmt: PtForLoop, range: IntProgression) { private fun translateForSimpleWordRangeDesc(stmt: PtForLoop, range: IntProgression) {
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.add(endLabel)
val varname = asmgen.asmVariableName(stmt.variable) val varname = asmgen.asmVariableName(stmt.variable)
asmgen.out(""" asmgen.out("""
lda #<${range.first} lda #<${range.first}
@ -719,7 +719,7 @@ $loopLabel""")
+ dec $varname""") + dec $varname""")
asmgen.jmp(loopLabel) asmgen.jmp(loopLabel)
asmgen.out(endLabel) asmgen.out(endLabel)
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.removeLast()
} }
private fun assignLoopvarWord(stmt: PtForLoop, range: PtRange) = private fun assignLoopvarWord(stmt: PtForLoop, range: PtRange) =

View File

@ -11,9 +11,9 @@ import prog8.ast.statements.*
import prog8.code.ast.* import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
import prog8.compiler.builtinFunctionReturnType import prog8.compiler.builtinFunctionReturnType
import java.io.File
import kotlin.io.path.Path import kotlin.io.path.Path
import kotlin.io.path.isRegularFile import kotlin.io.path.isRegularFile
import java.io.File
/** /**

View File

@ -12,7 +12,7 @@ import prog8.ast.walk.IAstVisitor
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.encodings.JapaneseCharacterConverter import prog8.code.target.encodings.JapaneseCharacterConverter
import java.io.CharConversionException import java.io.CharConversionException
import java.util.* import java.util.Objects
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.truncate import kotlin.math.truncate

View File

@ -1,7 +1,7 @@
package prog8.ast.expressions package prog8.ast.expressions
import prog8.code.core.* import prog8.code.core.*
import java.util.* import java.util.Objects
object InferredTypes { object InferredTypes {

View File

@ -6,7 +6,7 @@ import prog8.code.target.virtual.VirtualMachineDefinition
import prog8.intermediate.* import prog8.intermediate.*
import java.awt.Color import java.awt.Color
import java.awt.Toolkit import java.awt.Toolkit
import java.util.* import kotlin.collections.ArrayDeque
import kotlin.math.* import kotlin.math.*
import kotlin.random.Random import kotlin.random.Random
@ -39,8 +39,8 @@ class VirtualMachine(irProgram: IRProgram) {
val program: List<IRCodeChunk> val program: List<IRCodeChunk>
val artificialLabelAddresses: Map<Int, IRCodeChunk> val artificialLabelAddresses: Map<Int, IRCodeChunk>
val registers = Registers() val registers = Registers()
val callStack = Stack<CallSiteContext>() val callStack = ArrayDeque<CallSiteContext>()
val valueStack = Stack<UByte>() // max 128 entries val valueStack = ArrayDeque<UByte>() // max 128 entries
var breakpointHandler: ((pcChunk: IRCodeChunk, pcIndex: Int) -> Unit)? = null // can set custom breakpoint handler var breakpointHandler: ((pcChunk: IRCodeChunk, pcIndex: Int) -> Unit)? = null // can set custom breakpoint handler
var pcChunk = IRCodeChunk(null, null) var pcChunk = IRCodeChunk(null, null)
var pcIndex = 0 var pcIndex = 0
@ -360,7 +360,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> { IRDataType.BYTE -> {
val value = registers.getUB(i.reg1!!) val value = registers.getUB(i.reg1!!)
valueStack.push(value) valueStack.add(value)
} }
IRDataType.WORD -> { IRDataType.WORD -> {
val value = registers.getUW(i.reg1!!) val value = registers.getUW(i.reg1!!)
@ -376,7 +376,7 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsPOP(i: IRInstruction) { private fun InsPOP(i: IRInstruction) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> setResultReg(i.reg1!!, valueStack.pop().toInt(), i.type!!) IRDataType.BYTE -> setResultReg(i.reg1!!, valueStack.removeLast().toInt(), i.type!!)
IRDataType.WORD -> setResultReg(i.reg1!!, valueStack.popw().toInt(), i.type!!) IRDataType.WORD -> setResultReg(i.reg1!!, valueStack.popw().toInt(), i.type!!)
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, valueStack.popf()) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, valueStack.popf())
} }
@ -392,12 +392,12 @@ class VirtualMachine(irProgram: IRProgram) {
if(statusCarry) if(statusCarry)
status = status or 0b00000001u status = status or 0b00000001u
// TODO overflow not yet supported // TODO overflow not yet supported
valueStack.push(status) valueStack.add(status)
nextPc() nextPc()
} }
private fun InsPOPST() { private fun InsPOPST() {
val status = valueStack.pop().toInt() val status = valueStack.removeLast().toInt()
statusNegative = status and 0b10000000 != 0 statusNegative = status and 0b10000000 != 0
statusZero = status and 0b00000010 != 0 statusZero = status and 0b00000010 != 0
statusCarry = status and 0b00000001 != 0 statusCarry = status and 0b00000001 != 0
@ -411,7 +411,7 @@ class VirtualMachine(irProgram: IRProgram) {
if(value.dt==null) if(value.dt==null)
break break
when(value.dt!!) { when(value.dt!!) {
IRDataType.BYTE -> valueStack.push(value.value as UByte) IRDataType.BYTE -> valueStack.add(value.value as UByte)
IRDataType.WORD -> valueStack.pushw(value.value as UShort) IRDataType.WORD -> valueStack.pushw(value.value as UShort)
IRDataType.FLOAT -> valueStack.pushf(value.value as Double) IRDataType.FLOAT -> valueStack.pushf(value.value as Double)
} }
@ -633,7 +633,7 @@ class VirtualMachine(irProgram: IRProgram) {
} }
} }
// store the call site and jump // store the call site and jump
callStack.push(CallSiteContext(pcChunk, pcIndex+1, i.fcallArgs!!)) callStack.add(CallSiteContext(pcChunk, pcIndex+1, i.fcallArgs!!))
branchTo(i) branchTo(i)
} }
@ -641,7 +641,7 @@ class VirtualMachine(irProgram: IRProgram) {
if(callStack.isEmpty()) if(callStack.isEmpty())
exit(0) exit(0)
else { else {
val context = callStack.pop() val context = callStack.removeLast()
pcChunk = context.returnChunk pcChunk = context.returnChunk
pcIndex = context.returnIndex pcIndex = context.returnIndex
// ignore any return values. // ignore any return values.
@ -652,7 +652,7 @@ class VirtualMachine(irProgram: IRProgram) {
if(callStack.isEmpty()) if(callStack.isEmpty())
exit(0) exit(0)
else { else {
val context = callStack.pop() val context = callStack.removeLast()
val returns = context.fcallSpec.returns val returns = context.fcallSpec.returns
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> { IRDataType.BYTE -> {
@ -1487,16 +1487,16 @@ class VirtualMachine(irProgram: IRProgram) {
val right = registers.getUB(reg2) val right = registers.getUB(reg2)
val division = if(right==0.toUByte()) 0xffu else left / right val division = if(right==0.toUByte()) 0xffu else left / right
val remainder = if(right==0.toUByte()) 0u else left % right val remainder = if(right==0.toUByte()) 0u else left % right
valueStack.push(division.toUByte()) valueStack.add(division.toUByte())
valueStack.push(remainder.toUByte()) valueStack.add(remainder.toUByte())
} }
private fun divAndModConstUByte(reg1: Int, value: UByte) { private fun divAndModConstUByte(reg1: Int, value: UByte) {
val left = registers.getUB(reg1) val left = registers.getUB(reg1)
val division = if(value==0.toUByte()) 0xffu else left / value val division = if(value==0.toUByte()) 0xffu else left / value
val remainder = if(value==0.toUByte()) 0u else left % value val remainder = if(value==0.toUByte()) 0u else left % value
valueStack.push(division.toUByte()) valueStack.add(division.toUByte())
valueStack.push(remainder.toUByte()) valueStack.add(remainder.toUByte())
} }
private fun divAndModUWord(reg1: Int, reg2: Int) { private fun divAndModUWord(reg1: Int, reg2: Int) {
@ -2491,47 +2491,47 @@ class VirtualMachine(irProgram: IRProgram) {
} }
} }
internal fun Stack<UByte>.pushw(value: UShort) { internal fun ArrayDeque<UByte>.pushw(value: UShort) {
push((value and 255u).toUByte()) add((value and 255u).toUByte())
push((value.toInt() ushr 8).toUByte()) add((value.toInt() ushr 8).toUByte())
} }
internal fun Stack<UByte>.pushf(value: Double) { internal fun ArrayDeque<UByte>.pushf(value: Double) {
// push float; lsb first, msb last // push float; lsb first, msb last
var bits = value.toBits() var bits = value.toBits()
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
bits = bits ushr 8 bits = bits ushr 8
push(bits.toUByte()) add(bits.toUByte())
} }
internal fun Stack<UByte>.popw(): UShort { internal fun ArrayDeque<UByte>.popw(): UShort {
val msb = pop() val msb = removeLast()
val lsb = pop() val lsb = removeLast()
return ((msb.toInt() shl 8) + lsb.toInt()).toUShort() return ((msb.toInt() shl 8) + lsb.toInt()).toUShort()
} }
internal fun Stack<UByte>.popf(): Double { internal fun ArrayDeque<UByte>.popf(): Double {
// pop float; lsb is on bottom, msb on top // pop float; lsb is on bottom, msb on top
val b0 = pop().toLong() val b0 = removeLast().toLong()
val b1 = pop().toLong() val b1 = removeLast().toLong()
val b2 = pop().toLong() val b2 = removeLast().toLong()
val b3 = pop().toLong() val b3 = removeLast().toLong()
val b4 = pop().toLong() val b4 = removeLast().toLong()
val b5 = pop().toLong() val b5 = removeLast().toLong()
val b6 = pop().toLong() val b6 = removeLast().toLong()
val b7 = pop().toLong() val b7 = removeLast().toLong()
val bits = b7 + val bits = b7 +
(1L shl 8)*b6 + (1L shl 8)*b6 +
(1L shl 16)*b5 + (1L shl 16)*b5 +