mirror of
https://github.com/irmen/prog8.git
synced 2025-02-13 18:31:04 +00:00
support &, &< and &> on array elements from split word arrays, not just on the array as a whole
This commit is contained in:
parent
c8996418da
commit
37c2c1bf0b
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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? {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
)
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -182,10 +182,6 @@ interface IAstVisitor {
|
||||
addressOf.arrayIndex?.accept(this)
|
||||
}
|
||||
|
||||
fun visit(addressOfMsb: AddressOfMsb) {
|
||||
addressOfMsb.identifier.accept(this)
|
||||
}
|
||||
|
||||
fun visit(inlineAssembly: InlineAssembly) {
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user