From 86da9d3c7e1e76c7a68f11f2322b2c880817ca8d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 28 May 2025 18:08:53 +0200 Subject: [PATCH] assigning to plain pointer with array indexing --- .../codegen/intermediate/AssignmentGen.kt | 29 +++- compiler/test/TestPointers.kt | 2 +- .../prog8/ast/expressions/AstExpressions.kt | 1 - docs/source/todo.rst | 4 +- examples/test.p8 | 134 +++++++++--------- 5 files changed, 98 insertions(+), 72 deletions(-) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 50e8da966..0ce6dddaf 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -570,8 +570,33 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express valueRegister: Int, valueFpRegister: Int ) { - // TODO should be replaced by pointerderef in Ast itself maybe!?? - TODO("Not yet implemented: plain pointer indexed assignment ${targetIdent.position}") // TODO huh, this was working in earlier code wasn't it? where is the routine gone? + val pointerTr = expressionEval.translateExpression(targetIdent) + result += pointerTr.chunks + val pointerReg = pointerTr.resultReg + + val constIndex = targetArray.index.asConstInteger() + if(zeroValue) { + if(constIndex!=null) { + val offset = eltSize * constIndex + addInstr(result, IRInstruction(Opcode.ADD, IRDataType.WORD, reg1=pointerReg, immediate = offset), null) + } else { + val (code, indexReg) = loadIndexReg(targetArray, eltSize, true) + result += code + addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1=pointerReg, reg2=indexReg), null) + } + codeGen.storeValueAtPointersLocation(result, pointerReg, targetIdent.type.dereference(), true, -1) + } else { + if(constIndex!=null) { + val offset = eltSize * constIndex + addInstr(result, IRInstruction(Opcode.ADD, IRDataType.WORD, reg1=pointerReg, immediate = offset), null) + } else { + val (code, indexReg) = loadIndexReg(targetArray, eltSize, true) + result += code + addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1=pointerReg, reg2=indexReg), null) + } + val realValueReg = if(targetDt == IRDataType.FLOAT) valueFpRegister else valueRegister + codeGen.storeValueAtPointersLocation(result, pointerReg, targetIdent.type.dereference(), false, realValueReg) + } } private fun translateRegularAssignArrayIndexed( diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 05830f4df..d5eaec807 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -602,7 +602,7 @@ main { compileText(VMTarget(), false, src, outputDir) shouldNotBe null } - xtest("uword as pointer versus pointer to uword difference") { + test("uword as pointer versus pointer to uword difference") { val src=""" main { sub start() { diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 8d3b556ed..a84756cae 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -233,7 +233,6 @@ class BinaryExpression( val leftIdentfier = left as? IdentifierReference val leftIndexer = left as? ArrayIndexedExpression val rightIdentifier = right as? IdentifierReference - val rightIndexer = right as? ArrayIndexedExpression if(rightIdentifier!=null) { val struct: StructDecl? = if (leftIdentfier != null) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index c6cdf72da..fa3ea073c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -57,15 +57,13 @@ STRUCTS and TYPED POINTERS - 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. - add unit tests for expected AST elements for all syntaxes dealing with pointers, dereference(chain), derefs, and indexing (both as value and assigntargets) -- clean up pointerdereference in the grammar, regarding dealing with final ^^ or not (is there still any left?) -- fix TODO("address-of pointer dereference") - fix TODO("replace ptr^^ by @(ptr)") - add unit tests for all changes (pointers and structs) - try to fix parse error l1^^.s[0] = 4242 (equivalent to l1.s[0]=4242 , which does parse correctly) - 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 asm symbol name prefixing should work for dereferences too. -- fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator" +- really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator" - (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field) - update syntax highlighting files diff --git a/examples/test.p8 b/examples/test.p8 index 8a6e497da..9ec6ffb1a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,79 +5,83 @@ main { sub start() { simpleptrindexing() -;; struct List { -;; float f -;; ^^uword s -;; ^^float fp -;; uword n -;; } -;; ^^List l = List() -;; l.s = 2000 -;; l.fp = 3000 -;; -;; pokew(2000, 1) -;; pokew(2002, 2) -;; pokew(2004, 3) -;; pokew(2006, 4) -;; pokew(2008, 5) -;; pokef(3000, 1.111) -;; pokef(3008, 2.222) -;; pokef(3016, 3.333) -;; pokef(3024, 4.444) -;; pokef(3032, 5.555) -;; -;; cx16.r9L = 2 -;; -;; lvref1() -;; lvref2() -;; lvref1f() -;; lvref2f() -;; -;; ref1() -;; ref2() -;; ref1f() -;; ref2f() -; -; sub lvref1() { -; l.s[2] = 3333 -; } -; sub lvref2() { -; l.s[cx16.r9L+1] = 4444 -; } -; sub lvref1f() { -; l.fp[2] = 3333.3 -; } -; sub lvref2f() { -; l.fp[cx16.r9L+1] = 4444.4 -; } -; -; sub ref1() { -; cx16.r0 = l.s[2] -; txt.print_uw(l.s[2]) -; txt.nl() -; } -; sub ref2() { -; cx16.r1 = l.s[cx16.r9L+1] -; txt.print_uw(l.s[cx16.r9L+1]) -; txt.nl() -; } -; sub ref1f() { -; txt.print_f(l.fp[2]) -; txt.nl() -; } -; sub ref2f() { -; txt.print_f(l.fp[cx16.r9L+1]) -; txt.nl() -; } + struct List { + float f + ^^uword s + ^^float fp + uword n + } + ^^List l = List() + l.s = 2000 + l.fp = 3000 + + pokew(2000, 1) + pokew(2002, 2) + pokew(2004, 3) + pokew(2006, 4) + pokew(2008, 5) + pokef(3000, 1.111) + pokef(3008, 2.222) + pokef(3016, 3.333) + pokef(3024, 4.444) + pokef(3032, 5.555) + + cx16.r9L = 2 + + lvref1() + lvref2() + lvref1f() + lvref2f() + + ref1() + ref2() + ref1f() + ref2f() + + sub lvref1() { + l.s[2] = 3333 + } + sub lvref2() { + l.s[cx16.r9L+1] = 4444 + } + sub lvref1f() { + l.fp[2] = 3333.3 + } + sub lvref2f() { + l.fp[cx16.r9L+1] = 4444.4 + } + + sub ref1() { + cx16.r0 = l.s[2] + txt.print_uw(l.s[2]) + txt.nl() + } + sub ref2() { + cx16.r1 = l.s[cx16.r9L+1] + txt.print_uw(l.s[cx16.r9L+1]) + txt.nl() + } + sub ref1f() { + txt.print_f(l.fp[2]) + txt.nl() + } + sub ref2f() { + txt.print_f(l.fp[cx16.r9L+1]) + txt.nl() + } } sub simpleptrindexing() { ^^float flptr = 2000 + ^^bool bptr = 3000 + ; flptr[0] = 0.0 ; flptr[1] = 1.1 - flptr[2] = 2.2 ;; TODO Fix wrong memory write + cx16.r9L = 2 + flptr[cx16.r9L] = 2.2 + bptr[cx16.r9L] = true ; txt.print_f(flptr[0]) ; txt.nl()