mirror of
https://github.com/irmen/prog8.git
synced 2025-07-09 10:24:10 +00:00
move some utility methods into Pt Ast nodes itself
This commit is contained in:
@ -66,12 +66,6 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
|||||||
StSub(node.name, params, node.returntype, node)
|
StSub(node.name, params, node.returntype, node)
|
||||||
}
|
}
|
||||||
is PtVariable -> {
|
is PtVariable -> {
|
||||||
val bss = when (node.type) {
|
|
||||||
// TODO should bss be a computed property on PtVariable?
|
|
||||||
DataType.STR -> false
|
|
||||||
in ArrayDatatypes -> node.value==null || node.arraySize==0u
|
|
||||||
else -> node.value==null
|
|
||||||
}
|
|
||||||
val initialNumeric: Double?
|
val initialNumeric: Double?
|
||||||
val initialString: StString?
|
val initialString: StString?
|
||||||
val initialArray: StArray?
|
val initialArray: StArray?
|
||||||
@ -103,7 +97,7 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
|||||||
initialString = null
|
initialString = null
|
||||||
numElements = node.arraySize?.toInt()
|
numElements = node.arraySize?.toInt()
|
||||||
}
|
}
|
||||||
StStaticVariable(node.name, node.type, bss, initialNumeric, initialString, initialArray, numElements, node.zeropage, node)
|
StStaticVariable(node.name, node.type, node.bss, initialNumeric, initialString, initialArray, numElements, node.zeropage, node)
|
||||||
}
|
}
|
||||||
is PtBuiltinFunctionCall -> {
|
is PtBuiltinFunctionCall -> {
|
||||||
if(node.name=="memory") {
|
if(node.name=="memory") {
|
||||||
|
@ -2,6 +2,7 @@ package prog8.code.ast
|
|||||||
|
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.round
|
import kotlin.math.round
|
||||||
|
|
||||||
|
|
||||||
@ -52,6 +53,54 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun asConstInteger(): Int? = (this as? PtNumber)?.number?.toInt()
|
||||||
|
|
||||||
|
fun isSimple(): Boolean {
|
||||||
|
return when(this) {
|
||||||
|
is PtAddressOf -> true
|
||||||
|
is PtArray -> true
|
||||||
|
is PtArrayIndexer -> index is PtNumber || index is PtIdentifier
|
||||||
|
is PtBinaryExpression -> false
|
||||||
|
is PtBuiltinFunctionCall -> name in arrayOf("msb", "lsb", "peek", "peekw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd")
|
||||||
|
is PtContainmentCheck -> false
|
||||||
|
is PtFunctionCall -> false
|
||||||
|
is PtIdentifier -> true
|
||||||
|
is PtMachineRegister -> true
|
||||||
|
is PtMemoryByte -> address is PtNumber || address is PtIdentifier
|
||||||
|
is PtNumber -> true
|
||||||
|
is PtPrefix -> value.isSimple()
|
||||||
|
is PtRange -> true
|
||||||
|
is PtString -> true
|
||||||
|
is PtTypeCast -> value.isSimple()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fun clone(): PtExpression {
|
||||||
|
fun withClonedChildrenFrom(orig: PtExpression, clone: PtExpression): PtExpression {
|
||||||
|
orig.children.forEach { clone.add((it as PtExpression).clone()) }
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
when(this) {
|
||||||
|
is PtAddressOf -> return withClonedChildrenFrom(this, PtAddressOf(position))
|
||||||
|
is PtArray -> return withClonedChildrenFrom(this, PtArray(type, position))
|
||||||
|
is PtArrayIndexer -> return withClonedChildrenFrom(this, PtArrayIndexer(type, position))
|
||||||
|
is PtBinaryExpression -> return withClonedChildrenFrom(this, PtBinaryExpression(operator, type, position))
|
||||||
|
is PtBuiltinFunctionCall -> return withClonedChildrenFrom(this, PtBuiltinFunctionCall(name, void, hasNoSideEffects, type, position))
|
||||||
|
is PtContainmentCheck -> return withClonedChildrenFrom(this, PtContainmentCheck(position))
|
||||||
|
is PtFunctionCall -> return withClonedChildrenFrom(this, PtFunctionCall(name, void, type, position))
|
||||||
|
is PtIdentifier -> return withClonedChildrenFrom(this, PtIdentifier(name, type, position))
|
||||||
|
is PtMachineRegister -> return withClonedChildrenFrom(this, PtMachineRegister(register, type, position))
|
||||||
|
is PtMemoryByte -> return withClonedChildrenFrom(this, PtMemoryByte(position))
|
||||||
|
is PtNumber -> return withClonedChildrenFrom(this, PtNumber(type, number, position))
|
||||||
|
is PtPrefix -> return withClonedChildrenFrom(this, PtPrefix(operator, type, position))
|
||||||
|
is PtRange -> return withClonedChildrenFrom(this, PtRange(type, position))
|
||||||
|
is PtString -> return withClonedChildrenFrom(this, PtString(value, encoding, position))
|
||||||
|
is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
class PtAddressOf(position: Position) : PtExpression(DataType.UWORD, position) {
|
class PtAddressOf(position: Position) : PtExpression(DataType.UWORD, position) {
|
||||||
@ -187,6 +236,33 @@ class PtRange(type: DataType, position: Position) : PtExpression(type, position)
|
|||||||
get() = children[1] as PtExpression
|
get() = children[1] as PtExpression
|
||||||
val step: PtNumber
|
val step: PtNumber
|
||||||
get() = children[2] as PtNumber
|
get() = children[2] as PtNumber
|
||||||
|
|
||||||
|
fun toConstantIntegerRange(): IntProgression? {
|
||||||
|
fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression {
|
||||||
|
return when {
|
||||||
|
fromVal <= toVal -> when {
|
||||||
|
stepVal <= 0 -> IntRange.EMPTY
|
||||||
|
stepVal == 1 -> fromVal..toVal
|
||||||
|
else -> fromVal..toVal step stepVal
|
||||||
|
}
|
||||||
|
else -> when {
|
||||||
|
stepVal >= 0 -> IntRange.EMPTY
|
||||||
|
stepVal == -1 -> fromVal downTo toVal
|
||||||
|
else -> fromVal downTo toVal step abs(stepVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fromLv = from as? PtNumber
|
||||||
|
val toLv = to as? PtNumber
|
||||||
|
val stepLv = step as? PtNumber
|
||||||
|
if(fromLv==null || toLv==null || stepLv==null)
|
||||||
|
return null
|
||||||
|
val fromVal = fromLv.number.toInt()
|
||||||
|
val toVal = toLv.number.toInt()
|
||||||
|
val stepVal = stepLv.number.toInt()
|
||||||
|
return makeRange(fromVal, toVal, stepVal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,6 +155,13 @@ class PtVariable(name: String, override val type: DataType, val zeropage: Zeropa
|
|||||||
init {
|
init {
|
||||||
value?.let {it.parent=this}
|
value?.let {it.parent=this}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val bss: Boolean =
|
||||||
|
when (type) {
|
||||||
|
DataType.STR -> false
|
||||||
|
in ArrayDatatypes -> value==null || arraySize==0u
|
||||||
|
else -> value==null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ class AsmGen6502Internal (
|
|||||||
DataType.BYTE -> "cx16.r9sL"
|
DataType.BYTE -> "cx16.r9sL"
|
||||||
DataType.UWORD -> "cx16.r9"
|
DataType.UWORD -> "cx16.r9"
|
||||||
DataType.WORD -> "cx16.r9s"
|
DataType.WORD -> "cx16.r9s"
|
||||||
DataType.FLOAT -> TODO("no temporary float var available")
|
DataType.FLOAT -> throw AssemblyError("a float tempvar should never be requested and it also doesn't exist")
|
||||||
else -> throw AssemblyError("invalid dt $dt")
|
else -> throw AssemblyError("invalid dt $dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,62 +1,10 @@
|
|||||||
package prog8.codegen.cpu6502
|
package prog8.codegen.cpu6502
|
||||||
|
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.IPtSubroutine
|
||||||
|
import prog8.code.ast.PtAsmSub
|
||||||
|
import prog8.code.ast.PtSub
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
// TODO include this in the node class directly?
|
|
||||||
|
|
||||||
internal fun PtExpression.asConstInteger(): Int? =
|
|
||||||
(this as? PtNumber)?.number?.toInt()
|
|
||||||
|
|
||||||
|
|
||||||
internal fun PtRange.toConstantIntegerRange(): IntProgression? {
|
|
||||||
fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression {
|
|
||||||
return when {
|
|
||||||
fromVal <= toVal -> when {
|
|
||||||
stepVal <= 0 -> IntRange.EMPTY
|
|
||||||
stepVal == 1 -> fromVal..toVal
|
|
||||||
else -> fromVal..toVal step stepVal
|
|
||||||
}
|
|
||||||
else -> when {
|
|
||||||
stepVal >= 0 -> IntRange.EMPTY
|
|
||||||
stepVal == -1 -> fromVal downTo toVal
|
|
||||||
else -> fromVal downTo toVal step abs(stepVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fromLv = from as? PtNumber
|
|
||||||
val toLv = to as? PtNumber
|
|
||||||
val stepLv = step as? PtNumber
|
|
||||||
if(fromLv==null || toLv==null || stepLv==null)
|
|
||||||
return null
|
|
||||||
val fromVal = fromLv.number.toInt()
|
|
||||||
val toVal = toLv.number.toInt()
|
|
||||||
val stepVal = stepLv.number.toInt()
|
|
||||||
return makeRange(fromVal, toVal, stepVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun PtExpression.isSimple(): Boolean {
|
|
||||||
return when(this) {
|
|
||||||
is PtAddressOf -> true
|
|
||||||
is PtArray -> true
|
|
||||||
is PtArrayIndexer -> index is PtNumber || index is PtIdentifier
|
|
||||||
is PtBinaryExpression -> false
|
|
||||||
is PtBuiltinFunctionCall -> name in arrayOf("msb", "lsb", "peek", "peekw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd")
|
|
||||||
is PtContainmentCheck -> false
|
|
||||||
is PtFunctionCall -> false
|
|
||||||
is PtIdentifier -> true
|
|
||||||
is PtMachineRegister -> true
|
|
||||||
is PtMemoryByte -> address is PtNumber || address is PtIdentifier
|
|
||||||
is PtNumber -> true
|
|
||||||
is PtPrefix -> value.isSimple()
|
|
||||||
is PtRange -> true
|
|
||||||
is PtString -> true
|
|
||||||
is PtTypeCast -> value.isSimple()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun IPtSubroutine.regXasResult(): Boolean =
|
internal fun IPtSubroutine.regXasResult(): Boolean =
|
||||||
(this is PtAsmSub) && this.returns.any { it.first.registerOrPair in arrayOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
(this is PtAsmSub) && this.returns.any { it.first.registerOrPair in arrayOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) }
|
||||||
@ -100,29 +48,6 @@ internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<RegisterOrStatusflag, D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun PtExpression.clone(): PtExpression {
|
|
||||||
fun withClonedChildrenFrom(orig: PtExpression, clone: PtExpression): PtExpression {
|
|
||||||
orig.children.forEach { clone.add((it as PtExpression).clone()) }
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
when(this) {
|
|
||||||
is PtAddressOf -> return withClonedChildrenFrom(this, PtAddressOf(position))
|
|
||||||
is PtArray -> return withClonedChildrenFrom(this, PtArray(type, position))
|
|
||||||
is PtArrayIndexer -> return withClonedChildrenFrom(this, PtArrayIndexer(type, position))
|
|
||||||
is PtBinaryExpression -> return withClonedChildrenFrom(this, PtBinaryExpression(operator, type, position))
|
|
||||||
is PtBuiltinFunctionCall -> return withClonedChildrenFrom(this, PtBuiltinFunctionCall(name, void, hasNoSideEffects, type, position))
|
|
||||||
is PtContainmentCheck -> return withClonedChildrenFrom(this, PtContainmentCheck(position))
|
|
||||||
is PtFunctionCall -> return withClonedChildrenFrom(this, PtFunctionCall(name, void, type, position))
|
|
||||||
is PtIdentifier -> return withClonedChildrenFrom(this, PtIdentifier(name, type, position))
|
|
||||||
is PtMachineRegister -> return withClonedChildrenFrom(this, PtMachineRegister(register, type, position))
|
|
||||||
is PtMemoryByte -> return withClonedChildrenFrom(this, PtMemoryByte(position))
|
|
||||||
is PtNumber -> return withClonedChildrenFrom(this, PtNumber(type, number, position))
|
|
||||||
is PtPrefix -> return withClonedChildrenFrom(this, PtPrefix(operator, type, position))
|
|
||||||
is PtRange -> return withClonedChildrenFrom(this, PtRange(type, position))
|
|
||||||
is PtString -> return withClonedChildrenFrom(this, PtString(value, encoding, position))
|
|
||||||
is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun PtSub.returnRegister(): RegisterOrStatusflag? {
|
internal fun PtSub.returnRegister(): RegisterOrStatusflag? {
|
||||||
return when(returntype) {
|
return when(returntype) {
|
||||||
|
@ -3,7 +3,6 @@ package prog8.codegen.cpu6502.assignment
|
|||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||||
import prog8.codegen.cpu6502.asConstInteger
|
|
||||||
import prog8.codegen.cpu6502.returnsWhatWhere
|
import prog8.codegen.cpu6502.returnsWhatWhere
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
"^=" -> inplaceModification(assign.target, "^", srcValue)
|
"^=" -> inplaceModification(assign.target, "^", srcValue)
|
||||||
"<<=" -> inplaceModification(assign.target, "<<", srcValue)
|
"<<=" -> inplaceModification(assign.target, "<<", srcValue)
|
||||||
">>=" -> inplaceModification(assign.target, ">>", srcValue)
|
">>=" -> inplaceModification(assign.target, ">>", srcValue)
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assign.operator}") // TODO fallback to non-augmented Assign?
|
else -> throw AssemblyError("invalid augmented assign operator ${assign.operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
"<<" -> expressionEval.operatorShiftLeftInplace(address, null, vmDt, value)
|
"<<" -> expressionEval.operatorShiftLeftInplace(address, null, vmDt, value)
|
||||||
">>" -> expressionEval.operatorShiftRightInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
">>" -> expressionEval.operatorShiftRightInplace(address, null, vmDt, value.type in SignedDatatypes, value)
|
||||||
in PrefixOperators -> inplacePrefix(assignment.operator, vmDt, address, null)
|
in PrefixOperators -> inplacePrefix(assignment.operator, vmDt, address, null)
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}") // TODO fallbackAssign?
|
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value)
|
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value)
|
||||||
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
||||||
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol)
|
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol)
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}") // TODO fallbackAssign?
|
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,6 @@ class IRBlock(
|
|||||||
val alignment: BlockAlignment,
|
val alignment: BlockAlignment,
|
||||||
val position: Position
|
val position: Position
|
||||||
) {
|
) {
|
||||||
// TODO not separate lists but just a single list of chunks, like IRSubroutine? (but these are not all chunks...)
|
|
||||||
val children = mutableListOf<IIRBlockElement>()
|
val children = mutableListOf<IIRBlockElement>()
|
||||||
|
|
||||||
enum class BlockAlignment {
|
enum class BlockAlignment {
|
||||||
|
Reference in New Issue
Block a user