diff --git a/.gitignore b/.gitignore index 125d5d635..b1345ba6f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,13 @@ build/ dist/ output/ out/ +out-new/ +out-old/ .*cache/ *.directory *.prg *.bin +*.p8ir *.labels.txt *.vm.txt *.vice-mon-list diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index ef10e8fca..57e482624 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -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) { BaseDataType.ARRAY -> { when(sub) { diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index f730db5e3..27c9932a4 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -166,10 +166,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, } 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) { // check chain and field val dt = deref.identifier.inferType(program).getOrUndef() @@ -191,10 +187,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, if(fieldDt==null) { 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) - } } } diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 9c0eb079c..aeb425b6b 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -507,6 +507,18 @@ _after: 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 } diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 2c5414579..dbbae3f7b 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -393,9 +393,9 @@ main { val dr1 = (st[3] as Assignment).target.pointerDereference!! val dr2 = (st[4] as Assignment).value as PtrDereference - val dr3 = (st[6] as Assignment).value as PtrDereference - val dr4 = (st[7] as Assignment).value as PtrDereference - val dr5 = (st[8] as Assignment).target.pointerDereference!! + val dr3 = (st[7] as Assignment).value as PtrDereference + val dr4 = (st[8] as Assignment).value as PtrDereference + val dr5 = (st[9] as Assignment).target.pointerDereference!! dr0.identifier.nameInSource shouldBe listOf("l1", "s") dr0.chain.size shouldBe 0 diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 36abd1d44..b456201c4 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -1631,7 +1631,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po val vardecl = indexed.arrayvar.targetVarDecl() if(vardecl!=null &&vardecl.datatype.isPointer) { 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") } @@ -1641,7 +1641,7 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po dt.isUndefined -> InferredTypes.unknown() dt.isUnsignedWord -> InferredTypes.knownFor(BaseDataType.UBYTE) 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() @@ -1657,6 +1657,8 @@ class PtrIndexedDereference(val indexed: ArrayIndexedExpression, override val po } class PtrDereference(val identifier: IdentifierReference, val chain: List, val field: String?, override val position: Position) : Expression() { + // TODO why both identifier and chain? + override lateinit var parent: Node override fun linkParents(parent: Node) { @@ -1674,7 +1676,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List 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. -- 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? +- 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) - 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" diff --git a/examples/test.p8 b/examples/test.p8 index 538cb8d4e..a5450caa9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,7 +5,7 @@ main { } sub start() { ^^List l1 = List() - cx16.r1 = l1.s^^ ; TODO fix "undefined symbol" error (and fix the unit test too) + cx16.r1 = l1.s^^ } } diff --git a/simpleAst/src/prog8/code/ast/AstExpressions.kt b/simpleAst/src/prog8/code/ast/AstExpressions.kt index 041b25464..3ade82098 100644 --- a/simpleAst/src/prog8/code/ast/AstExpressions.kt +++ b/simpleAst/src/prog8/code/ast/AstExpressions.kt @@ -414,7 +414,7 @@ class PtPointerDeref(type: DataType, val chain: List, val field: String? get() = children.single() as PtExpression init { - require(!type.isUndefined) + require(!type.isUndefined && !type.isPointer) { "no support for pointer to pointer" } } }