mirror of
https://github.com/irmen/prog8.git
synced 2025-11-24 06:17:39 +00:00
identified problems with pointer array as parameter
This commit is contained in:
@@ -1320,4 +1320,115 @@ main {
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
@@ -30,17 +30,45 @@ Typed pointer to simple datatype
|
||||
|
||||
The syntax for declaring typed pointers is as follows:
|
||||
|
||||
``^^type``: pointer to that type
|
||||
You can declare a pointer to any numeric datatype (bytes, words, longs, floats), booleans,
|
||||
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.)
|
||||
``^^float fptr`` declares fptr as a pointer to a float value.
|
||||
``^^type``: pointer to a type
|
||||
You can declare a pointer to any numeric datatype (bytes, words, longs, floats), booleans, 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.)
|
||||
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.
|
||||
So ``^^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.
|
||||
``^^type[size]``: array with size size containing pointers to a type.
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -53,9 +81,3 @@ Typed pointer to Struct type
|
||||
----------------------------
|
||||
|
||||
Work in progress.
|
||||
|
||||
|
||||
Pointer arithmetic and array indexing
|
||||
-------------------------------------
|
||||
|
||||
Work in progress.
|
||||
|
||||
@@ -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: 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()
|
||||
- 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
|
||||
- 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 parser error)
|
||||
- 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 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.
|
||||
- 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"
|
||||
- (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)
|
||||
|
||||
|
||||
110
examples/test.p8
110
examples/test.p8
@@ -1,38 +1,92 @@
|
||||
%import textio
|
||||
%option enable_floats
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
^^ubyte[4] array1 = [1000, 1100, 1200, 1300]
|
||||
^^byte[4] array2 = [1000, 1100, 1200, 1300]
|
||||
^^bool[4] array3 = [1000, 1100, 1200, 1300]
|
||||
^^word[4] array4 = [1000, 1100, 1200, 1300]
|
||||
^^uword[4] array5 = [1000, 1100, 1200, 1300]
|
||||
^^float[4] array6 = [1000, 1100, 1200, 1300]
|
||||
^^long[4] array7 = [1000, 1100, 1200, 1300]
|
||||
^^str[4] array8 = [1000, 1100, 1200, 1300]
|
||||
^^ubyte[4] array1
|
||||
^^byte[4] array2
|
||||
^^bool[4] array3
|
||||
^^word[4] array4
|
||||
^^uword[4] array5
|
||||
^^float[4] array6
|
||||
^^long[4] array7
|
||||
^^str[4] array8
|
||||
|
||||
cx16.r0 = array1[2]
|
||||
cx16.r1 = array2[2]
|
||||
cx16.r2 = array3[2]
|
||||
cx16.r3 = array4[2]
|
||||
cx16.r4 = array5[2]
|
||||
cx16.r5 = array6[2]
|
||||
cx16.r6 = array7[2]
|
||||
cx16.r7 = array8[2]
|
||||
error1(array1)
|
||||
error2(array2)
|
||||
error3(array3)
|
||||
error4(array4)
|
||||
error5(array5)
|
||||
error6(array6)
|
||||
error7(array7)
|
||||
error8(array8)
|
||||
|
||||
; txt.print_uw(array[1])
|
||||
; txt.print_uw(array[2])
|
||||
; txt.print_uw(array[3])
|
||||
; txt.print_uw(array[4])
|
||||
; txt.print_uw(array[5])
|
||||
; txt.print_uw(array[6])
|
||||
; txt.print_uw(array[7])
|
||||
;
|
||||
; func(farray)
|
||||
ok1(array1)
|
||||
ok2(array2)
|
||||
ok3(array3)
|
||||
ok4(array4)
|
||||
ok5(array5)
|
||||
ok6(array6)
|
||||
ok7(array7)
|
||||
ok8(array8)
|
||||
}
|
||||
|
||||
; sub func(^^float zzz) {
|
||||
; cx16.r0++
|
||||
; }
|
||||
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++
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user