identified problems with pointer array as parameter

This commit is contained in:
Irmen de Jong
2025-07-06 20:33:20 +02:00
parent 8ede098154
commit b6c0bac96f
4 changed files with 236 additions and 42 deletions

View File

@@ -1320,4 +1320,115 @@ main {
compileText(VMTarget(), false, src, outputDir) shouldNotBe null compileText(VMTarget(), false, src, outputDir) shouldNotBe null
} }
xtest("array of pointers as subroutine param - not the primitive type pointers") {
val src="""
%option enable_floats
main {
sub start() {
^^ubyte[4] array1
^^byte[4] array2
^^bool[4] array3
^^word[4] array4
^^uword[4] array5
^^float[4] array6
^^long[4] array7
^^str[4] array8
error1(array1)
error2(array2)
error3(array3)
error4(array4)
error5(array5)
error6(array6)
error7(array7)
error8(array8)
}
sub error1(^^ubyte ptr) {
cx16.r0++
}
sub error2(^^byte ptr) {
cx16.r0++
}
sub error3(^^bool ptr) {
cx16.r0++
}
sub error4(^^word ptr) {
cx16.r0++
}
sub error5(^^uword ptr) {
cx16.r0++
}
sub error6(^^float ptr) {
cx16.r0++
}
sub error7(^^long ptr) {
cx16.r0++
}
sub error8(^^str ptr) {
cx16.r0++
}
}"""
val errors = ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors = errors) shouldBe null
errors.errors.size shouldBe 999
// TODO
}
xtest("array of pointers as subroutine param") {
val src="""
%option enable_floats
main {
sub start() {
^^ubyte[4] array1
^^byte[4] array2
^^bool[4] array3
^^word[4] array4
^^uword[4] array5
^^float[4] array6
^^long[4] array7
^^str[4] array8
ok1(array1)
ok2(array2)
ok3(array3)
ok4(array4)
ok5(array5)
ok6(array6)
ok7(array7)
ok8(array8)
}
sub ok1(^^ubyte[] ptr) {
cx16.r0 = ptr
}
sub ok2(^^byte[] ptr) {
cx16.r0 = ptr
}
sub ok3(^^bool[] ptr) {
cx16.r0 = ptr
}
sub ok4(^^word[] ptr) {
cx16.r0 = ptr
}
sub ok5(^^uword[] ptr) {
cx16.r0 = ptr
}
sub ok6(^^float[] ptr) {
cx16.r0 = ptr
}
sub ok7(^^long[] ptr) {
cx16.r0 = ptr
}
sub ok8(^^str[] ptr) {
cx16.r0 = ptr
}
}"""
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
}
}) })

View File

@@ -30,17 +30,45 @@ Typed pointer to simple datatype
The syntax for declaring typed pointers is as follows: The syntax for declaring typed pointers is as follows:
``^^type``: pointer to that type ``^^type``: pointer to a type
You can declare a pointer to any numeric datatype (bytes, words, longs, floats), booleans, You can declare a pointer to any numeric datatype (bytes, words, longs, floats), booleans, and also strings.
and also strings. (the latter, ``^^str`` - a pointer to a string - is equivalient to ``^^ubyte`` though because a string is just an array of ubytes.) (The latter: ``^^str`` - a pointer to a string - is equivalient to ``^^ubyte`` though because a string is just an array of ubytes.)
``^^float fptr`` declares fptr as a pointer to a float value.
Finally, the type can be a struct type, which then declares a pointer to that struct type. This is explained in the next section. Finally, the type can be a struct type, which then declares a pointer to that struct type. This is explained in the next section.
So, for example; ``^^float fptr`` declares fptr as a pointer to a float value.
``^^type[size]``: array with size size containing pointers to type. ``^^type[size]``: array with size size containing pointers to a type.
So ``^^word[100] values`` declares values to be an array of 100 pointers to words. So for example; ``^^word[100] values`` declares values to be an array of 100 pointers to words.
Note that an array of pointers (regardless of the type they point to) is always a @split word array by default. Note that an array of pointers (regardless of the type they point to) is always a @split word array.
It is not possible to define "pointers to arrays"; ``^^(type[])`` is invalid syntax. It is not possible to define pointers to *arrays*; ``^^(type[])`` is invalid syntax.
Pointers of different types cannot be assigned to one another, unless you use an explicit cast.
Typed pointers and an 'untyped' uword pointer/value can be assigned to each other without an explicit cast.
Because it is pretty common to check if a pointer value is zero or not (because zero usually means that the pointer doesn't exist/has no value),
pointers can be implicitly cast to a boolean. This allows you to easily write conditionals such as ``while ptr { ... }``
Dereferencing a pointer, pointer arithmetic
-------------------------------------------
To get the value the pointer points at, you *dereference* the pointer. The syntax for that is: ``pointer^^``.
Say the pointer variable is of type ``^^float``, then ``pointer^^`` will return the float value it points at.
You can also use array indexing syntax to get the n-th value. For example: ``floatpointer[3]`` will return the
fourth floating point value in the sequence that the floatpointer points at. Because the pointer is a typed pointer,
the compiler knows what the size of the value is that it points at and correctly skips forward the required number of bytes in memory.
In this case, say a float takes 5 bytes, then ``floatpointer[3]`` will return the float value stored at memory address floatpointer+15.
Notice that ``floatpointer[0]`` is equivalent to ``floatpointer^^``.
You can add and subtract values from a pointer, this is called **pointer arithmetic**.
For example, to advance a pointer to the next value, you can use ``pointer++``.
To make it point to the preceding value, you can use ``pointer--``.
Adding or subtracting X to a pointer will change the pointer by X times the size of the value it points at (the same as the C language does it).
This is true even for pointers to struct types: the compiler knows the storage size of the whole struct type and advances or rewinds
the pointer value (memory address) by the appropriate number of bytes (X times the size of the struct). More info below.
Structs Structs
@@ -53,9 +81,3 @@ Typed pointer to Struct type
---------------------------- ----------------------------
Work in progress. Work in progress.
Pointer arithmetic and array indexing
-------------------------------------
Work in progress.

View File

@@ -61,7 +61,11 @@ STRUCTS and TYPED POINTERS
- DONE: added peekbool() and pokebool() and pokebowl() boolean peek and poke, the latter is equivalent to pokebool() - DONE: added peekbool() and pokebool() and pokebowl() boolean peek and poke, the latter is equivalent to pokebool()
- DONE: fixed support for (expression) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with peek() - DONE: fixed support for (expression) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with peek()
- DONE: fixed support for (assigntarget) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with poke() - DONE: fixed support for (assigntarget) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with poke()
- fix ^^bool[] ptr in sub params
- ^^bool[3] ptr in sub param should give proper error for the array size that is not allowed there? or can we actually use it?
- write docs in structpointers.rst - write docs in structpointers.rst
- scan through virtual examples to change untyped uword pointers to typed pointers
- scan through virtual library modules to change untyped uword pointers to typed pointers
- add support for array index dereferencing as assign target "array[2]^^.value = 99" where array is struct pointers (currently a 'no support' error) - add support for array index dereferencing as assign target "array[2]^^.value = 99" where array is struct pointers (currently a 'no support' error)
- add support for array index dereferencing as assign target "array[2].value = 99" where array is struct pointers (currently a parser error) - add support for array index dereferencing as assign target "array[2].value = 99" where array is struct pointers (currently a parser error)
- try to fix parse error l1^^.s[0] = 4242 (equivalent to l1.s[0]=4242 , which does parse correctly) - try to fix parse error l1^^.s[0] = 4242 (equivalent to l1.s[0]=4242 , which does parse correctly)
@@ -70,6 +74,9 @@ STRUCTS and TYPED POINTERS
- 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"
- 6502 asm symbol name prefixing should work for dereferences too. - 6502 asm symbol name prefixing should work for dereferences too.
- update structpointers.rst docs with 6502 things?
- scan through 6502 library modules to change untyped uword pointers to typed pointers
- scan through 6502 examples to change untyped uword pointers to typed pointers
- 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" - 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) - (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)

View File

@@ -1,38 +1,92 @@
%import textio
%option enable_floats %option enable_floats
main { main {
sub start() { sub start() {
^^ubyte[4] array1 = [1000, 1100, 1200, 1300] ^^ubyte[4] array1
^^byte[4] array2 = [1000, 1100, 1200, 1300] ^^byte[4] array2
^^bool[4] array3 = [1000, 1100, 1200, 1300] ^^bool[4] array3
^^word[4] array4 = [1000, 1100, 1200, 1300] ^^word[4] array4
^^uword[4] array5 = [1000, 1100, 1200, 1300] ^^uword[4] array5
^^float[4] array6 = [1000, 1100, 1200, 1300] ^^float[4] array6
^^long[4] array7 = [1000, 1100, 1200, 1300] ^^long[4] array7
^^str[4] array8 = [1000, 1100, 1200, 1300] ^^str[4] array8
cx16.r0 = array1[2] error1(array1)
cx16.r1 = array2[2] error2(array2)
cx16.r2 = array3[2] error3(array3)
cx16.r3 = array4[2] error4(array4)
cx16.r4 = array5[2] error5(array5)
cx16.r5 = array6[2] error6(array6)
cx16.r6 = array7[2] error7(array7)
cx16.r7 = array8[2] error8(array8)
; txt.print_uw(array[1]) ok1(array1)
; txt.print_uw(array[2]) ok2(array2)
; txt.print_uw(array[3]) ok3(array3)
; txt.print_uw(array[4]) ok4(array4)
; txt.print_uw(array[5]) ok5(array5)
; txt.print_uw(array[6]) ok6(array6)
; txt.print_uw(array[7]) ok7(array7)
; ok8(array8)
; func(farray)
} }
; sub func(^^float zzz) { sub error1(^^ubyte ptr) {
; cx16.r0++ cx16.r0++
; } }
sub error2(^^byte ptr) {
cx16.r0++
}
sub error3(^^bool ptr) {
cx16.r0++
}
sub error4(^^word ptr) {
cx16.r0++
}
sub error5(^^uword ptr) {
cx16.r0++
}
sub error6(^^float ptr) {
cx16.r0++
}
sub error7(^^long ptr) {
cx16.r0++
}
sub error8(^^str ptr) {
cx16.r0++
}
sub ok1(^^ubyte[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok2(^^byte[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok3(^^bool[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok4(^^word[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok5(^^uword[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok6(^^float[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok7(^^long[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
sub ok8(^^str[] ptr) {
txt.print_uw(ptr)
txt.nl()
}
} }