support &, &< and &> on array elements from split word arrays, not just on the array as a whole

This commit is contained in:
Irmen de Jong 2024-12-29 02:33:29 +01:00
parent c8996418da
commit 37c2c1bf0b
18 changed files with 123 additions and 154 deletions

View File

@ -231,7 +231,7 @@ internal class AssignmentAsmGen(
targetDt.isSignedWord -> assignVariableWord(assign.target, variable, assign.source.datatype)
targetDt.isUnsignedWord -> {
if(assign.source.datatype.isPassByRef)
assignAddressOf(assign.target, variable, null, null)
assignAddressOf(assign.target, variable, false, null, null)
else
assignVariableWord(assign.target, variable, assign.source.datatype)
}
@ -447,7 +447,7 @@ internal class AssignmentAsmGen(
asmgen.asmSymbolName(value.identifier) + "_lsb" // the _lsb split array comes first in memory
else
asmgen.asmSymbolName(value.identifier)
assignAddressOf(assign.target, sourceName, arrayDt, value.arrayIndexExpr)
assignAddressOf(assign.target, sourceName, value.isMsbForSplitArray, arrayDt, value.arrayIndexExpr)
}
is PtBool -> throw AssemblyError("source kind should have been literalboolean")
is PtNumber -> throw AssemblyError("source kind should have been literalnumber")
@ -1929,21 +1929,21 @@ $endLabel""")
dt.isString -> {
assignExpressionToRegister(containment.needle, RegisterOrPair.A, elementDt.isSigned)
asmgen.out(" pha") // need to keep the scratch var safe so we have to do it in this order
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position,"P8ZP_SCRATCH_W1"), symbolName, null, null)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position,"P8ZP_SCRATCH_W1"), symbolName, false, null, null)
asmgen.out(" pla")
asmgen.out(" ldy #${numElements-1}")
asmgen.out(" jsr prog8_lib.containment_bytearray")
}
dt.isFloatArray -> {
assignExpressionToRegister(containment.needle, RegisterOrPair.FAC1, true)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, false, null, null)
asmgen.out(" ldy #$numElements")
asmgen.out(" jsr floats.containment_floatarray")
}
dt.isByteArray -> {
assignExpressionToRegister(containment.needle, RegisterOrPair.A, elementDt.isSigned)
asmgen.out(" pha") // need to keep the scratch var safe so we have to do it in this order
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, false, null, null)
asmgen.out(" pla")
asmgen.out(" ldy #$numElements")
asmgen.out(" jsr prog8_lib.containment_bytearray")
@ -1951,11 +1951,11 @@ $endLabel""")
dt.isWordArray -> {
assignExpressionToVariable(containment.needle, "P8ZP_SCRATCH_W1", elementDt)
if(dt.isSplitWordArray) {
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName+"_lsb", null, null)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName+"_lsb", false, null, null)
asmgen.out(" ldy #$numElements")
asmgen.out(" jsr prog8_lib.containment_splitwordarray")
} else {
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, false, null, null)
asmgen.out(" ldy #$numElements")
asmgen.out(" jsr prog8_lib.containment_linearwordarray")
}
@ -2576,13 +2576,12 @@ $endLabel""")
}
}
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, msb: Boolean, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
if(arrayIndexExpr!=null) {
if(arrayDt?.isSplitWordArray==true)
TODO("address of element of a split word array")
val constIndex = arrayIndexExpr.asConstInteger()
if(constIndex!=null) {
if (arrayDt?.isUnsignedWord==true) {
require(!msb)
assignVariableToRegister(sourceName, RegisterOrPair.AY, false, arrayIndexExpr.definingISub(), arrayIndexExpr.position)
if(constIndex>0)
asmgen.out("""
@ -2594,7 +2593,7 @@ $endLabel""")
}
else {
if(constIndex>0) {
val offset = program.memsizer.memorySize(arrayDt!!, constIndex) // add arrayIndexExpr * elementsize to the address of the array variable.
val offset = if(arrayDt!!.isSplitWordArray) constIndex else program.memsizer.memorySize(arrayDt, constIndex) // add arrayIndexExpr * elementsize to the address of the array variable.
asmgen.out(" lda #<($sourceName + $offset) | ldy #>($sourceName + $offset)")
} else {
asmgen.out(" lda #<$sourceName | ldy #>$sourceName")
@ -2604,6 +2603,7 @@ $endLabel""")
return
} else {
if (arrayDt?.isUnsignedWord==true) {
require(!msb)
assignVariableToRegister(sourceName, RegisterOrPair.AY, false, arrayIndexExpr.definingISub(), arrayIndexExpr.position)
asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false)

View File

@ -668,7 +668,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
sbc cx16.r0H
sta ${arrayVar}_msb+$index""")
}
else -> TODO("in-place modify split-words array value for operator $operator")
else -> TODO("inplace split word array value $operator")
}
}

View File

@ -879,7 +879,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
}
private fun operatorMultiplyInplaceSplitArray(array: PtArrayIndexer, operand: PtExpression): IRCodeChunks? {
return null // TODO("inplace split word array *")
return null // fallback to slow method // TODO("inplace split word array *")
}
private fun operatorMinusInplaceSplitArray(array: PtArrayIndexer, operand: PtExpression): IRCodeChunks? {
@ -900,10 +900,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
}
return result
} else {
return null // TODO("inplace split word array -")
return null // fallback to slow method // TODO("inplace split word array -")
}
}
return null // TODO("inplace split word array -")
return null // fallback to slow method // TODO("inplace split word array -")
}
private fun operatorPlusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
@ -986,10 +986,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
result += IRCodeChunk(skip, null)
return result
} else {
return null // TODO("inplace split word array +")
return null // fallback to slow method // TODO("inplace split word array +")
}
}
return null // TODO("inplace split word array +")
return null // fallback to slow method // TODO("inplace split word array +")
}
private fun operatorShiftRightInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {

View File

@ -548,7 +548,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val arr = (arg as? PtArrayIndexer)
val index = arr?.index?.asConstInteger()
if(arr!=null && index!=null) {
if(arr.splitWords) TODO("IR rol/ror on split words array")
if(arr.splitWords)
TODO("IR rol/ror on split words array")
val variable = arr.variable.name
val offset = codeGen.program.memsizer.memorySize(arr.type, index)
addInstr(result, IRInstruction(opcodeMemAndReg.first, vmDt, labelSymbol = variable, symbolOffset = offset), null)

View File

@ -163,15 +163,24 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
// note: LOAD <symbol> gets you the address of the symbol, whereas LOADM <symbol> would get you the value stored at that location
val result = mutableListOf<IRCodeChunkBase>()
val resultRegister = codeGen.registers.next()
fun loadAddressOfArrayLabel(reg: Int) {
if (expr.isMsbForSplitArray) {
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = reg, labelSymbol = symbol + "_msb"), null)
} else if (expr.identifier.type.isSplitWordArray) {
// the _lsb split array comes first in memory
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = reg, labelSymbol = symbol + "_lsb"), null)
} else
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = reg, labelSymbol = symbol), null)
}
if(expr.isFromArrayElement) {
if(expr.identifier.type.isSplitWordArray)
TODO("address of element of a split word array")
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol), null)
val indexTr2 = translateExpression(expr.arrayIndexExpr!!)
addToResult(result, indexTr2, indexTr2.resultReg, -1)
val indexTr = translateExpression(expr.arrayIndexExpr!!)
addToResult(result, indexTr, indexTr.resultReg, -1)
val indexWordReg = codeGen.registers.next()
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=indexWordReg, reg2=indexTr2.resultReg), null)
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=indexWordReg, reg2=indexTr.resultReg), null)
if(expr.identifier.type.isUnsignedWord) {
require(!expr.isMsbForSplitArray)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
it += IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1=resultRegister, reg2=indexWordReg)
@ -179,22 +188,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} else {
val eltSize = codeGen.program.memsizer.memorySize(expr.identifier.type, 1)
result += IRCodeChunk(null, null).also {
// multiply indexTr resultreg by the eltSize and add this to the resultRegister.
it += IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol)
if(eltSize>1) {
loadAddressOfArrayLabel(resultRegister)
if(eltSize>1 && !expr.identifier.type.isSplitWordArray) {
it += IRInstruction(Opcode.MUL, IRDataType.WORD, reg1=indexWordReg, immediate = eltSize)
}
it += IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1=resultRegister, reg2=indexWordReg)
}
}
} else {
if(expr.isMsbForSplitArray) {
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol+"_msb"), null)
} else if(expr.identifier.type.isSplitWordArray) {
// the _lsb split array comes first in memory
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol+"_lsb"), null)
} else
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol), null)
loadAddressOfArrayLabel(resultRegister)
}
return ExpressionCodeResult(result, vmDt, resultRegister, -1)
}

View File

@ -702,23 +702,17 @@ internal class AstChecker(private val program: Program,
val variable=addressOf.identifier.targetVarDecl(program)
if (variable!=null) {
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
errors.err("invalid pointer-of operand type",addressOf.position)
errors.err("invalid pointer-of operand type", addressOf.position)
}
if(addressOf.arrayIndex!=null && variable.datatype.isSplitWordArray) {
errors.err("cannot take the adress of a word element that is in a split-word array", addressOf.position)
}
if(addressOf.msb) {
if(variable!=null && !variable.datatype.isSplitWordArray)
errors.err("$> can only be used on split word arrays", addressOf.position)
}
super.visit(addressOf)
}
override fun visit(addressOfMsb: AddressOfMsb) {
val target = addressOfMsb.identifier.targetVarDecl(program)
if(target==null || !target.datatype.isSplitWordArray) {
errors.err("&> can only be used on split word arrays", addressOfMsb.position)
}
}
override fun visit(ifExpr: IfExpression) {
if(!ifExpr.condition.inferType(program).isBool)
errors.err("condition should be a boolean", ifExpr.condition.position)

View File

@ -48,7 +48,7 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
listOf(
IAstModification.ReplaceNode(
typecast,
AddressOf(identifier, null, typecast.position),
AddressOf(identifier, null, false, typecast.position),
parent
)
)

View File

@ -82,7 +82,6 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
private fun transformExpression(expr: Expression): PtExpression {
return when(expr) {
is AddressOf -> transform(expr)
is AddressOfMsb -> transform(expr)
is ArrayIndexedExpression -> transform(expr)
is ArrayLiteral -> transform(expr)
is BinaryExpression -> transform(expr)
@ -603,19 +602,13 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
}
private fun transform(src: AddressOf): PtAddressOf {
val addr = PtAddressOf(src.position)
val addr = PtAddressOf(src.position, src.msb)
addr.add(transform(src.identifier))
if(src.arrayIndex!=null)
addr.add(transformExpression(src.arrayIndex!!.indexExpr))
return addr
}
private fun transform(src: AddressOfMsb): PtAddressOf {
val addr = PtAddressOf(src.position, true)
addr.add(transform(src.identifier))
return addr
}
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
val dt = srcArr.arrayvar.targetVarDecl(program)!!.datatype
if(!dt.isArray && !dt.isString)

View File

@ -257,7 +257,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
if(!argDt.isString) {
modifications += IAstModification.ReplaceNode(
identifier,
AddressOf(identifier, null, it.second.position),
AddressOf(identifier, null, false, it.second.position),
call as Node
)
}
@ -275,7 +275,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
// take the address of the identifier
modifications += IAstModification.ReplaceNode(
identifier,
AddressOf(identifier, null, it.second.position),
AddressOf(identifier, null, false, it.second.position),
call as Node
)
}
@ -397,7 +397,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
val eltType = elt.inferType(program)
val tgt = elt.targetStatement(program)
if(eltType.isIterable || tgt is Subroutine || tgt is Label || tgt is Block) {
val addressof = AddressOf(elt, null, elt.position)
val addressof = AddressOf(elt, null, false, elt.position)
addressof.linkParents(array)
array.value[index] = addressof
}

View File

@ -55,13 +55,13 @@ class TestAsmGenSymbols: StringSpec({
val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, null, false, Position.DUMMY)
val assign1 = Assignment(tgt, IdentifierReference(listOf("localvar"), Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign2 = Assignment(tgt, AddressOf(IdentifierReference(listOf("locallabel"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign3 = Assignment(tgt, AddressOf(IdentifierReference(listOf("var_outside"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign4 = Assignment(tgt, AddressOf(IdentifierReference(listOf("label_outside"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign5 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","localvar"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign6 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","locallabel"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign7 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","var_outside"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign8 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","label_outside"), Position.DUMMY), null, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign2 = Assignment(tgt, AddressOf(IdentifierReference(listOf("locallabel"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign3 = Assignment(tgt, AddressOf(IdentifierReference(listOf("var_outside"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign4 = Assignment(tgt, AddressOf(IdentifierReference(listOf("label_outside"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign5 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","localvar"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign6 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","locallabel"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign7 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","var_outside"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val assign8 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","label_outside"), Position.DUMMY), null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY)

View File

@ -464,6 +464,8 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
override fun visit(addressOf: AddressOf) {
output("&")
if(addressOf.msb)
output(">")
addressOf.identifier.accept(this)
if(addressOf.arrayIndex!=null) {
output("[")
@ -472,11 +474,6 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
}
}
override fun visit(addressOfMsb: AddressOfMsb) {
output("&>")
addressOfMsb.identifier.accept(this)
}
override fun visit(inlineAssembly: InlineAssembly) {
outputlni("%asm {{")
outputln(inlineAssembly.assembly)

View File

@ -588,20 +588,12 @@ private fun ExpressionContext.toAst(insideParentheses: Boolean=false) : Expressi
if(addressof()!=null) {
val addressOf = addressof()
val identifier = addressOf.scoped_identifier()
if(addressOf.ADDRESS_OF_LSB()!=null && identifier==null)
throw SyntaxError("&< is only valid on array variables", toPosition())
return if(addressOf.ADDRESS_OF_MSB()!=null) {
if (identifier != null)
AddressOfMsb(addressof().scoped_identifier().toAst(), toPosition())
else
throw SyntaxError("&> is only valid on array variables", toPosition())
} else {
if (identifier != null)
AddressOf(addressof().scoped_identifier().toAst(), null, toPosition())
else {
val array = addressOf.arrayindexed()
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), toPosition())
}
val msb = addressOf.ADDRESS_OF_MSB()!=null
return if (identifier != null)
AddressOf(addressof().scoped_identifier().toAst(), null, msb, toPosition())
else {
val array = addressOf.arrayindexed()
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), msb, toPosition())
}
}

View File

@ -416,7 +416,7 @@ class TypecastExpression(var expression: Expression, var type: BaseDataType, val
}
}
data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayIndex?, override val position: Position) : Expression() {
data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayIndex?, val msb: Boolean, override val position: Position) : Expression() {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
@ -441,8 +441,10 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
}
}
override fun copy() = AddressOf(identifier.copy(), arrayIndex?.copy(), position)
override fun copy() = AddressOf(identifier.copy(), arrayIndex?.copy(), msb, position)
override fun constValue(program: Program): NumericLiteral? {
if(msb)
return null
val target = this.identifier.targetStatement(program)
val targetVar = target as? VarDecl
if(targetVar!=null) {
@ -464,10 +466,11 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
}
}
}
val targetAsmAddress = (target as? Subroutine)?.asmAddress
if(targetAsmAddress!=null) {
if (targetAsmAddress != null) {
val constAddress = targetAsmAddress.address.constValue(program)
if(constAddress==null)
if (constAddress == null)
return null
return NumericLiteral(BaseDataType.UWORD, constAddress.number, position)
}
@ -479,47 +482,6 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
}
data class AddressOfMsb(var identifier: IdentifierReference, override val position: Position) : Expression() {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
identifier.linkParents(this)
}
override val isSimple = true
override fun replaceChildNode(node: Node, replacement: Node) {
if(node===identifier) {
require(replacement is IdentifierReference)
identifier = replacement
replacement.parent = this
} else {
throw FatalAstException("invalid replace, no child node $node")
}
}
override fun copy() = AddressOfMsb(identifier.copy(), position)
override fun constValue(program: Program): NumericLiteral? {
val target = this.identifier.targetStatement(program)
val targetVar = target as? VarDecl
if(targetVar!=null) {
if (targetVar.type == VarDeclType.MEMORY || targetVar.type == VarDeclType.CONST) {
var address = targetVar.value?.constValue(program)?.number
if (address != null) {
TODO("RETURN CONSTVALUE ADDROF_MSB ")
// return NumericLiteral(BaseDataType.UWORD, address, position)
}
}
}
return null
}
override fun referencesIdentifier(nameInSource: List<String>) = identifier.nameInSource==nameInSource
override fun inferType(program: Program) = InferredTypes.knownFor(BaseDataType.UWORD)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
}
class DirectMemoryRead(var addressExpression: Expression, override val position: Position) : Expression() {
override lateinit var parent: Node

View File

@ -267,7 +267,7 @@ class VarDecl(val type: VarDeclType,
// parameter variable memory mapped to a R0-R15 virtual register
val regname = param.registerOrPair.asScopedNameVirtualReg(param.type)
decltype = VarDeclType.MEMORY
value = AddressOf(IdentifierReference(regname, param.position), null, param.position)
value = AddressOf(IdentifierReference(regname, param.position), null, false, param.position)
}
val dt = if(param.type.isArray) DataType.forDt(BaseDataType.UWORD) else param.type
return VarDecl(decltype, VarDeclOrigin.SUBROUTINEPARAM, dt, param.zp, SplitWish.DONTCARE, null, param.name, emptyList(), value,

View File

@ -94,7 +94,6 @@ abstract class AstWalker {
protected val noModifications = emptyList<IAstModification>()
open fun before(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications
open fun before(addressOfMsb: AddressOfMsb, parent: Node): Iterable<IAstModification> = noModifications
open fun before(array: ArrayLiteral, parent: Node): Iterable<IAstModification> = noModifications
open fun before(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun before(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
@ -140,7 +139,6 @@ abstract class AstWalker {
open fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications
open fun after(addressOfMsb: AddressOfMsb, parent: Node): Iterable<IAstModification> = noModifications
open fun after(array: ArrayLiteral, parent: Node): Iterable<IAstModification> = noModifications
open fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun after(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
@ -471,12 +469,6 @@ abstract class AstWalker {
track(after(addressOf, parent), addressOf, parent)
}
fun visit(addressOfMsb: AddressOfMsb, parent: Node) {
track(before(addressOfMsb, parent), addressOfMsb, parent)
addressOfMsb.identifier.accept(this, addressOfMsb)
track(after(addressOfMsb, parent), addressOfMsb, parent)
}
fun visit(ifExpr: IfExpression, parent: Node) {
track(before(ifExpr, parent), ifExpr, parent)
ifExpr.condition.accept(this, ifExpr)

View File

@ -182,10 +182,6 @@ interface IAstVisitor {
addressOf.arrayIndex?.accept(this)
}
fun visit(addressOfMsb: AddressOfMsb) {
addressOfMsb.identifier.accept(this)
}
fun visit(inlineAssembly: InlineAssembly) {
}

View File

@ -10,15 +10,6 @@ TODO
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- why is this code so much larger with charpos variable, than with just using cx16.r0L ?
ubyte charpos
for charpos in DIALOG_TOPX+1 to DIALOG_TOPX+30 {
txt.setchr(charpos, cx16.r1L, txt.getchr(charpos, cx16.r1L) ^ 128)
}
- support &, &< and &> on array elements from split word arrays too not just the array as a whole (to get rid of the error "&< is only valid on array variables"
and "cannot take the adress of a word element that is in a split-word array" and the TODOS "address of element of a split word array")
- after that: fix leftover asmgen split word array todo's
- Kotlin: can we use inline value classes in certain spots?
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
@ -59,6 +50,7 @@ IR/VM
- add BZ and BNZ instructions? To replace CMPI #0 + Branch?
- fix TODO("IR rol/ror on split words array")
- fix "<< in array" / ">> in array"
- implement fast code paths for TODO("inplace split....
- sometimes source lines get missing in the output p8ir, for example the first assignment is gone in:
sub start() {
cx16.r0L = cx16.r1 as ubyte

View File

@ -1,8 +1,56 @@
%import textio
%zeropage basicsafe
%option no_sysinit
main {
sub start() {
str localstr = "hello"
uword[] words = [1111,2222,"three"]
bool r1 = 'z' in localstr
bool result = 2222 in words
uword[8] @nosplit warr
uword[8] @split swarr
uword @shared ptr = $1000
const uword cptr = $2000
txt.print_uwhex(&ptr[2], true)
txt.spc()
txt.print_uwhex(&cptr[2], true)
txt.nl()
txt.print_uwhex(&warr, true)
txt.spc()
txt.print_uwhex(&warr[2], true)
txt.nl()
txt.print("addresses of split word array:\n")
txt.print_uwhex(&swarr, true)
txt.spc()
txt.print_uwhex(&<swarr, true)
txt.spc()
txt.print_uwhex(&>swarr, true)
txt.nl()
txt.print("addresses of normal word array:\n")
txt.print_uwhex(&warr, true)
txt.spc()
txt.print_uwhex(&<warr, true)
txt.nl()
txt.print("addresses of split word array element 4:\n")
txt.print_uwhex(&swarr[4], true)
txt.spc()
txt.print_uwhex(&<swarr[4], true)
txt.spc()
txt.print_uwhex(&>swarr[4], true)
txt.nl()
txt.print("addresses of split word array element 4 via var:\n")
cx16.r0L=4
txt.print_uwhex(&swarr[cx16.r0L], true)
txt.spc()
txt.print_uwhex(&<swarr[cx16.r0L], true)
txt.spc()
txt.print_uwhex(&>swarr[cx16.r0L], true)
txt.nl()
txt.print("addresses of normal word array element 4:\n")
txt.print_uwhex(&warr[4], true)
txt.spc()
txt.print_uwhex(&<warr[4], true)
txt.nl()
}
}