mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 06:16:15 +00:00
fix ptr errors
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,10 +7,13 @@ build/
|
|||||||
dist/
|
dist/
|
||||||
output/
|
output/
|
||||||
out/
|
out/
|
||||||
|
out-new/
|
||||||
|
out-old/
|
||||||
.*cache/
|
.*cache/
|
||||||
*.directory
|
*.directory
|
||||||
*.prg
|
*.prg
|
||||||
*.bin
|
*.bin
|
||||||
|
*.p8ir
|
||||||
*.labels.txt
|
*.labels.txt
|
||||||
*.vm.txt
|
*.vm.txt
|
||||||
*.vice-mon-list
|
*.vice-mon-list
|
||||||
|
|||||||
@@ -202,6 +202,17 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dereference(): DataType {
|
||||||
|
require(isPointer || isUnsignedWord)
|
||||||
|
return when {
|
||||||
|
isUnsignedWord -> forDt(BaseDataType.UBYTE)
|
||||||
|
sub!=null -> forDt(sub)
|
||||||
|
subType!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, subType)
|
||||||
|
subTypeFromAntlr!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr)
|
||||||
|
else -> throw IllegalArgumentException("cannot dereference this pointer type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String = when(base) {
|
override fun toString(): String = when(base) {
|
||||||
BaseDataType.ARRAY -> {
|
BaseDataType.ARRAY -> {
|
||||||
when(sub) {
|
when(sub) {
|
||||||
|
|||||||
@@ -166,10 +166,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(deref: PtrDereference) {
|
override fun visit(deref: PtrDereference) {
|
||||||
val first = deref.identifier.targetStatement()
|
|
||||||
if(first==null)
|
|
||||||
errors.undefined(deref.identifier.nameInSource, deref.identifier.position)
|
|
||||||
|
|
||||||
if(deref.field!=null) {
|
if(deref.field!=null) {
|
||||||
// check chain and field
|
// check chain and field
|
||||||
val dt = deref.identifier.inferType(program).getOrUndef()
|
val dt = deref.identifier.inferType(program).getOrUndef()
|
||||||
@@ -191,10 +187,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
|||||||
if(fieldDt==null) {
|
if(fieldDt==null) {
|
||||||
errors.err("unknown field '${deref.field}' in struct '${struct.name}'", deref.position)
|
errors.err("unknown field '${deref.field}' in struct '${struct.name}'", deref.position)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (first !is VarDecl || !first.datatype.isStructInstance) {
|
|
||||||
errors.err("cannot find struct type", deref.identifier.position)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -507,6 +507,18 @@ _after:
|
|||||||
return listOf(IAstModification.ReplaceNode(deref, memread, parent))
|
return listOf(IAstModification.ReplaceNode(deref, memread, parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(deref.chain.isEmpty() && deref.field==null) {
|
||||||
|
val expr = deref.parent as? BinaryExpression
|
||||||
|
if (expr != null && expr.operator == ".") {
|
||||||
|
if (expr.left is IdentifierReference && expr.right === deref) {
|
||||||
|
// replace (a) . (b^^) by (a.b)^^
|
||||||
|
val identifier = IdentifierReference((expr.left as IdentifierReference).nameInSource + deref.identifier.nameInSource, expr.left.position)
|
||||||
|
val replacement = PtrDereference(identifier, emptyList(), null, deref.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(expr, replacement, expr.parent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -393,9 +393,9 @@ main {
|
|||||||
val dr1 = (st[3] as Assignment).target.pointerDereference!!
|
val dr1 = (st[3] as Assignment).target.pointerDereference!!
|
||||||
val dr2 = (st[4] as Assignment).value as PtrDereference
|
val dr2 = (st[4] as Assignment).value as PtrDereference
|
||||||
|
|
||||||
val dr3 = (st[6] as Assignment).value as PtrDereference
|
val dr3 = (st[7] as Assignment).value as PtrDereference
|
||||||
val dr4 = (st[7] as Assignment).value as PtrDereference
|
val dr4 = (st[8] as Assignment).value as PtrDereference
|
||||||
val dr5 = (st[8] as Assignment).target.pointerDereference!!
|
val dr5 = (st[9] as Assignment).target.pointerDereference!!
|
||||||
|
|
||||||
dr0.identifier.nameInSource shouldBe listOf("l1", "s")
|
dr0.identifier.nameInSource shouldBe listOf("l1", "s")
|
||||||
dr0.chain.size shouldBe 0
|
dr0.chain.size shouldBe 0
|
||||||
|
|||||||
@@ -1631,7 +1631,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
|
|||||||
val vardecl = indexed.arrayvar.targetVarDecl()
|
val vardecl = indexed.arrayvar.targetVarDecl()
|
||||||
if(vardecl!=null &&vardecl.datatype.isPointer) {
|
if(vardecl!=null &&vardecl.datatype.isPointer) {
|
||||||
if(vardecl.datatype.sub!=null)
|
if(vardecl.datatype.sub!=null)
|
||||||
return InferredTypes.knownFor(vardecl.datatype.sub!!)
|
return InferredTypes.knownFor(vardecl.datatype.dereference())
|
||||||
TODO("cannot determine type of dereferenced indexed pointer(?) that is not a pointer to a basic type")
|
TODO("cannot determine type of dereferenced indexed pointer(?) that is not a pointer to a basic type")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1641,7 +1641,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
|
|||||||
dt.isUndefined -> InferredTypes.unknown()
|
dt.isUndefined -> InferredTypes.unknown()
|
||||||
dt.isUnsignedWord -> InferredTypes.knownFor(BaseDataType.UBYTE)
|
dt.isUnsignedWord -> InferredTypes.knownFor(BaseDataType.UBYTE)
|
||||||
dt.isPointer -> {
|
dt.isPointer -> {
|
||||||
return if(dt.sub!=null) InferredTypes.knownFor(dt.sub!!)
|
return if(dt.sub!=null) InferredTypes.knownFor(dt.dereference())
|
||||||
else InferredTypes.unknown()
|
else InferredTypes.unknown()
|
||||||
}
|
}
|
||||||
else -> InferredTypes.unknown()
|
else -> InferredTypes.unknown()
|
||||||
@@ -1657,6 +1657,8 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PtrDereference(val identifier: IdentifierReference, val chain: List<String>, val field: String?, override val position: Position) : Expression() {
|
class PtrDereference(val identifier: IdentifierReference, val chain: List<String>, val field: String?, override val position: Position) : Expression() {
|
||||||
|
// TODO why both identifier and chain?
|
||||||
|
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
@@ -1674,7 +1676,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
|||||||
if(first==null)
|
if(first==null)
|
||||||
return InferredTypes.unknown()
|
return InferredTypes.unknown()
|
||||||
if(first is StructFieldRef) {
|
if(first is StructFieldRef) {
|
||||||
return InferredTypes.knownFor(first.type)
|
return InferredTypes.knownFor(first.type.dereference())
|
||||||
}
|
}
|
||||||
val vardecl = identifier.targetVarDecl()
|
val vardecl = identifier.targetVarDecl()
|
||||||
if(vardecl==null || vardecl.datatype.isUndefined || (!vardecl.datatype.isPointer && !vardecl.datatype.isStructInstance) )
|
if(vardecl==null || vardecl.datatype.isUndefined || (!vardecl.datatype.isPointer && !vardecl.datatype.isStructInstance) )
|
||||||
@@ -1683,7 +1685,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
|||||||
if(chain.isEmpty()) {
|
if(chain.isEmpty()) {
|
||||||
return if(field==null) {
|
return if(field==null) {
|
||||||
require(vardecl.datatype.sub!=null) { "can only dereference a pointer to a simple datatype " }
|
require(vardecl.datatype.sub!=null) { "can only dereference a pointer to a simple datatype " }
|
||||||
InferredTypes.knownFor(vardecl.datatype.sub!!)
|
InferredTypes.knownFor(vardecl.datatype.dereference())
|
||||||
} else {
|
} else {
|
||||||
// lookup struct field type
|
// lookup struct field type
|
||||||
val struct = vardecl.datatype.subType as StructDecl
|
val struct = vardecl.datatype.subType as StructDecl
|
||||||
@@ -1691,7 +1693,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
|||||||
if (fieldDt == null)
|
if (fieldDt == null)
|
||||||
InferredTypes.unknown()
|
InferredTypes.unknown()
|
||||||
else
|
else
|
||||||
InferredTypes.knownFor(fieldDt)
|
InferredTypes.knownFor(fieldDt.dereference())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// lookup type of field at the end of a dereference chain
|
// lookup type of field at the end of a dereference chain
|
||||||
@@ -1705,13 +1707,13 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
|||||||
struct = fieldDt.subType as StructDecl
|
struct = fieldDt.subType as StructDecl
|
||||||
}
|
}
|
||||||
if(field==null) {
|
if(field==null) {
|
||||||
return InferredTypes.knownFor(DataType.pointer(struct))
|
return InferredTypes.knownFor(DataType.structInstance(struct))
|
||||||
}
|
}
|
||||||
val fieldDt = struct.getFieldType(field)
|
val fieldDt = struct.getFieldType(field)
|
||||||
return if(fieldDt==null)
|
return if(fieldDt==null)
|
||||||
InferredTypes.unknown()
|
InferredTypes.unknown()
|
||||||
else
|
else
|
||||||
InferredTypes.knownFor(fieldDt)
|
InferredTypes.knownFor(fieldDt.dereference())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ STRUCTS and TYPED POINTERS
|
|||||||
- DONE: fix _msb/_lsb storage of the split-words pointer-arrays
|
- DONE: fix _msb/_lsb storage of the split-words pointer-arrays
|
||||||
- DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
|
- DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
|
||||||
- DONE: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
|
- DONE: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
|
||||||
- fix ptr indexed problems (see todo.p8)
|
- fix ptr problems in re.p8
|
||||||
- Can we now get rid of PtPointerIndexedDeref ? Both for expression (value) as assigntarget? All code for translate(idxderef: PtPointerIndexedDeref) in ExpressionGen?
|
- Can we now get rid of PtPointerIndexedDeref ? Both for expression (value) as assigntarget? All code for translate(idxderef: PtPointerIndexedDeref) in ExpressionGen?
|
||||||
|
- why does PtrDereference have both identifier and chain property? what goes where? is the distinction needed?
|
||||||
- add unit tests for all changes (pointers and structs)
|
- add unit tests for all changes (pointers and structs)
|
||||||
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
|
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
|
||||||
- 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code"
|
- 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ main {
|
|||||||
}
|
}
|
||||||
sub start() {
|
sub start() {
|
||||||
^^List l1 = List()
|
^^List l1 = List()
|
||||||
cx16.r1 = l1.s^^ ; TODO fix "undefined symbol" error (and fix the unit test too)
|
cx16.r1 = l1.s^^
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ class PtPointerDeref(type: DataType, val chain: List<String>, val field: String?
|
|||||||
get() = children.single() as PtExpression
|
get() = children.single() as PtExpression
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(!type.isUndefined)
|
require(!type.isUndefined && !type.isPointer) { "no support for pointer to pointer" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user