fix a ptr indexing error

This commit is contained in:
Irmen de Jong
2025-05-17 18:46:25 +02:00
parent eabdd3a8f3
commit 96f690e749
5 changed files with 49 additions and 5 deletions
@@ -424,6 +424,9 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
}
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
if(parent is PtrIndexedDereference)
return noModifications
if(arrayIndexedExpression.indexer.constIndex()==0) {
val dt = arrayIndexedExpression.arrayvar.inferType(program).getOrUndef()
if(dt.isPointer) {
@@ -220,8 +220,13 @@ _after:
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl()
if(arrayVar!=null && (arrayVar.datatype.isUnsignedWord || (arrayVar.datatype.isPointer && arrayVar.datatype.sub==BaseDataType.UBYTE))) {
val wordIndex = TypecastExpression(indexExpr, DataType.UWORD, true, indexExpr.position)
val address = BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", wordIndex, arrayIndexedExpression.position)
return if(parent is AssignTarget) {
val address = BinaryExpression(
arrayIndexedExpression.arrayvar.copy(),
"+",
wordIndex,
arrayIndexedExpression.position
)
return if (parent is AssignTarget) {
// assignment to array
val memwrite = DirectMemoryWrite(address, arrayIndexedExpression.position)
val newtarget = AssignTarget(
@@ -238,6 +243,8 @@ _after:
val memread = DirectMemoryRead(address, arrayIndexedExpression.position)
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
}
} else if(arrayVar!=null && (arrayVar.datatype.isPointer || arrayVar.datatype.isArray)) {
return noModifications
} else {
// it could be a pointer dereference instead of a simple array variable
val dt = arrayIndexedExpression.arrayvar.traverseDerefChainForDt(null)
@@ -108,7 +108,8 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
val type = idxderef.inferType(program).getOrElse {
throw FatalAstException("unknown dt")
}
val deref = PtPointerIndexedDeref(type, idxderef.position)
require(type.isPointer && type.sub!=null)
val deref = PtPointerIndexedDeref(DataType.forDt(type.sub!!), idxderef.position)
deref.add(transform(idxderef.indexed))
return deref
}
@@ -697,7 +698,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
}
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
val dt = srcArr.arrayvar.targetVarDecl()!!.datatype
val dt = srcArr.arrayvar.inferType(program)
if(!dt.isArray && !dt.isString && !dt.isPointer)
throw FatalAstException("array indexing can only be used on array, string or pointer variables ${srcArr.position}")
val eltType = srcArr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
+22
View File
@@ -7,6 +7,7 @@ import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.types.instanceOf
import prog8.code.ast.PtAssignment
import prog8.code.ast.PtReturn
import prog8.code.ast.PtSubSignature
import prog8.code.core.BaseDataType
@@ -292,4 +293,25 @@ main {
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
}
test("uword as pointer versus pointer to uword difference") {
val src="""
main {
sub start() {
uword @shared ptr1
^^uword @shared ptr2
ptr1[2] = 1
ptr2[2] = 1
}
}"""
val result = compileText(VMTarget(), false, src, outputDir)!!
val st = result.codegenAst!!.entrypoint()!!.children
st.size shouldBe 8
val a1 = st[5] as PtAssignment
val a2 = st[6] as PtAssignment
a1.target.memory shouldNotBe null
a2.target.array shouldNotBe null
}
})
@@ -428,6 +428,12 @@ class ArrayIndexedExpression(var arrayvar: IdentifierReference,
}
else -> InferredTypes.knownFor(target.datatype)
}
} else {
val dt = arrayvar.inferType(program).getOrUndef()
if(dt.isPointer) {
if(dt.sub!=null)
return InferredTypes.knownFor(dt.sub!!)
}
}
return InferredTypes.unknown()
}
@@ -1340,6 +1346,9 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
InferredTypes.knownFor(targetStmt.datatype)
}
null -> {
val param = definingSubroutine?.parameters?.find { it.name==nameInSource.singleOrNull() }
if(param!=null)
return InferredTypes.knownFor(param.type)
val fieldType = traverseDerefChainForDt(null)
if(fieldType.isUndefined)
InferredTypes.unknown()
@@ -1363,6 +1372,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
val vardecl = definingScope.lookup(nameInSource.take(1)) as? VarDecl
if (vardecl?.datatype?.isPointer != true)
return DataType.UNDEFINED
require(vardecl.datatype.subType!=null) { "pointer type should point to a struct ${vardecl.position}" }
struct = vardecl.datatype.subType as StructDecl
fieldDt = vardecl.datatype
}
@@ -1625,7 +1635,8 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
return InferredTypes.unknown()
}
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun replaceChildNode(node: Node, replacement: Node) =
throw FatalAstException("can't replace here")
override fun referencesIdentifier(nameInSource: List<String>) = indexed.referencesIdentifier(nameInSource)
}