had to turn ^type syntax into ^^type to avoid confusion with the eor operator once again

This commit is contained in:
Irmen de Jong 2025-04-26 18:23:13 +02:00
parent b920d553a0
commit 88269628a2
5 changed files with 50 additions and 26 deletions

View File

@ -168,10 +168,10 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
}
}
BaseDataType.POINTER -> {
if(sub!=null) "^${sub.name.lowercase()}" else "^${subIdentifier!!.joinToString(".")}"
if(sub!=null) "^^${sub.name.lowercase()}" else "^^${subIdentifier!!.joinToString(".")}"
}
BaseDataType.ARRAY_POINTER -> {
if(sub!=null) "^${sub.name.lowercase()}[] (split)" else "^${subIdentifier!!.joinToString(".")}[] (split)"
if(sub!=null) "^^${sub.name.lowercase()}[] (split)" else "^^${subIdentifier!!.joinToString(".")}[] (split)"
}
else -> base.name.lowercase()
}
@ -186,10 +186,10 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
BaseDataType.FLOAT -> "float"
BaseDataType.STR -> "str"
BaseDataType.POINTER -> {
if(sub!=null) "^${sub.name.lowercase()}" else "^${subIdentifier!!.joinToString(".")}"
if(sub!=null) "^^${sub.name.lowercase()}" else "^^${subIdentifier!!.joinToString(".")}"
}
BaseDataType.ARRAY_POINTER -> {
if(sub!=null) "^${sub.name.lowercase()}[" else "^${subIdentifier!!.joinToString(".")}["
if(sub!=null) "^^${sub.name.lowercase()}[" else "^^${subIdentifier!!.joinToString(".")}["
}
BaseDataType.ARRAY -> {
when(sub) {

View File

@ -41,8 +41,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
errors.err("value '$constValue' out of range for ${decl.datatype}", constValue.position)
else
errors.err("value out of range for ${decl.datatype}", decl.value!!.position)
} else {
throw FatalAstException("value dt differs from decl dt ${decl.position}")
}
}
}

View File

@ -12,13 +12,13 @@ STRUCTS and TYPED POINTERS
- DONE: declare struct as a separate entity so you can then declare multiple variables (pointers) of the same struct type. Like usual.
- DONE: struct is a 'packed' struct, fields are placed in order of declaration. This guarantees exact size and place of the fields
- DONE: structs only supported as a reference type (uword pointer). This removes a lot of the problems related to introducing a variable length value type.
- DONE: need to introduce typed pointer datatype in prog8 to allow this to make any sense. + correct code gen
- DONE: need to introduce typed pointer datatype in prog8 to allow this to make any sense. Syntax to declare a pointer type: ^^datatype (double hat to avoid parsing confusion with the eor operator)
- DONE: initially only a pointer-to-struct should actually work, pointer-to-other-type is possible but that can come later.
- DONE: a struct can contain only numeric type fields (byte,word,float) - no nested structs, no reference types (strings, arrays) inside structs.
- DONE: struct might also contain typed pointer fields (because a pointer is just an address word)
- DONE: max 1 page of memory total size to allow regular register indexing
- DONE: assigning ptrs of different types is only allowed via a cast as usual. For simple address (uword) assignments, no cast is needed (but allowed)
- DONE: how to dereference a pointer? Pascal does it like this: ptr^ But this conflicts with the existing eor operator so we now use ptr^^ (double hat)
- DONE: how to dereference a pointer? Pascal does it like this: ptr^ But this conflicts with the existing eor operator so we now use ptr^^^ (double hat)
- DONE: dereferencing a pointer to struct could look like Pascal's ptr^.field as well, but the ^ is actually redundant here; compiler already knows it's a pointer type.
Note that actually dereferencing a pointer to a struct as an explicit operation, conflicts with the third axiom on this list (structs only as reference types) so it can only be done for basic types?
So... setting struct fields can simply be ``structvar.field = 42`` and reading them ``a = structvar.field``
@ -28,7 +28,7 @@ STRUCTS and TYPED POINTERS
- static initialization of structs may be allowed only at block scope and then behaves like arrays; it won't reset to the original value when program is restarted, so beware. Syntax = TBD
- allow memory-mapped structs? Something like &Sprite sprite0 = $9000 basically behaves identically to a typed pointer, but the address is immutable as usual
- existing STR and ARRAY remain unchanged (don't become typed pointers) so we can keep doing register-indexed addressing directly on them
- rather than str or uword parameter types for routines with a string argument, use ^str (or ^ubyte maybe? these are more or less identical..?)
- rather than str or uword parameter types for routines with a string argument, use ^^str (or ^^ubyte maybe? these are more or less identical..?)
- same for arrays? pointer-to-array syntax = TBD
- what about pointers to subroutines? should these be typed as well now?
- asm symbol name prefixing should work for dereferences too.

View File

@ -3,6 +3,32 @@
%zeropage basicsafe
%option no_sysinit
/*
main {
struct Node {
^^Node next
ubyte value
}
sub start() {
uword mem = memory("mem", 1000, 0)
^^Node n1 = mem
^^Node n2 = mem+10
^^Node n3 = mem+20
^^Node n4 = mem+30 as ^^Node
txt.print_uw(n1)
txt.spc()
txt.print_uw(n1.next)
txt.print_uw(n1.next as uword)
txt.spc()
txt.print_ub(n1.value)
txt.nl()
}
}
*/
main {
struct Enemy {
@ -13,8 +39,8 @@ main {
bool alive
; no strings or arrays allowed in struct type declarations.
; typed pointers are allowed though because these are just a uword:
^float floatptr
^str stringpointer
^^float floatptr
^^str stringpointer
}
sub start() {
@ -23,18 +49,18 @@ main {
struct Node {
ubyte type
uword value
^Node nextnode ; linked list?
^^Node nextnode ; linked list?
}
; declare pointer vars
^bool @shared bool_ptr
^ubyte @shared ubyte_ptr
^word @shared word_ptr
^Node @shared node_ptr
^Enemy @shared enemy_ptr
^bool[5] @shared boolptr_list ; array of pointers to bools (bit silly, should we even support this)
^Node[5] @shared node_list ; array of pointers to nodes
^Enemy[5] @shared enemy_list ; array of pointers to enemies
^^bool @shared bool_ptr
^^ubyte @shared ubyte_ptr
^^word @shared word_ptr
^^Node @shared node_ptr
^^Enemy @shared enemy_ptr
^^bool[5] @shared boolptr_list ; array of pointers to bools (bit silly, should we even support this)
^^Node[5] @shared node_list ; array of pointers to nodes
^^Enemy[5] @shared enemy_list ; array of pointers to enemies
txt.print("sizeofs: ")
txt.print_ub(sizeof(Enemy))
@ -46,16 +72,16 @@ main {
; point to a memory address.
bool_ptr = 2000
bool_ptr = 2002 as ^bool
bool_ptr = 2002 as ^^bool
ubyte_ptr = 2000
word_ptr = 2000
node_ptr = 2000
enemy_ptr = 2000
bool_ptr = enemy_ptr as ^bool ; cast makes no sense, but hey, programmer knows best right? (without cast would give error)
bool_ptr = enemy_ptr as ^^bool ; cast makes no sense, but hey, programmer knows best right? (without cast would give error)
; array elements, point to a memory address
node_list[0] = 1000
node_list[1] = 2000
node_list[1] = 2002 as ^Node
node_list[1] = 2002 as ^^Node
node_list[2] = 3000
; dereference
@ -92,3 +118,4 @@ main {
; TODO how to statically allocate/initialize a struct? Difficult.. see TODO in docs
}
}

View File

@ -33,8 +33,7 @@ ADDRESS_OF: '&' ;
ADDRESS_OF_MSB: '&>' ;
ADDRESS_OF_LSB: '&<' ;
INVALID_AND_COMPOSITE: '&&' ;
POINTER: '^';
POINTERDEREF: '^^';
POINTER: '^^';
fragment HEX_DIGIT: ('a'..'f') | ('A'..'F') | ('0'..'9') ;
fragment BIN_DIGIT: ('0' | '1') ;
@ -331,7 +330,7 @@ pointerdereference: (prefix = scoped_identifier '.')? derefchain ('.' field = i
derefchain : singlederef ('.' singlederef)* ;
singlederef : identifier POINTERDEREF ;
singlederef : identifier POINTER ;
branch_stmt : branchcondition EOL? (statement | statement_block) EOL? else_part? ;