mirror of
https://github.com/irmen/prog8.git
synced 2026-04-25 12:33:55 +00:00
fix pointer array initialization
This commit is contained in:
@@ -351,22 +351,22 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
val isPointer = base.isPointer
|
||||
val isStructInstance = base.isStructInstance
|
||||
val isPointerArray = base.isPointerArray
|
||||
val isBoolArray = base.isArray && sub == BaseDataType.BOOL
|
||||
val isByteArray = base.isArray && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE)
|
||||
val isUnsignedByteArray = base.isArray && sub == BaseDataType.UBYTE
|
||||
val isSignedByteArray = base.isArray && sub == BaseDataType.BYTE
|
||||
val isWordArray = base.isArray && (sub == BaseDataType.UWORD || sub == BaseDataType.WORD)
|
||||
val isUnsignedWordArray = base.isArray && sub == BaseDataType.UWORD
|
||||
val isSignedWordArray = base.isArray && sub == BaseDataType.WORD
|
||||
val isFloatArray = base.isArray && sub == BaseDataType.FLOAT
|
||||
val isBoolArray = base.isArray && !base.isPointerArray && sub == BaseDataType.BOOL
|
||||
val isByteArray = base.isArray && !base.isPointerArray && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE)
|
||||
val isUnsignedByteArray = base.isArray && !base.isPointerArray && sub == BaseDataType.UBYTE
|
||||
val isSignedByteArray = base.isArray && !base.isPointerArray && sub == BaseDataType.BYTE
|
||||
val isWordArray = base.isArray && !base.isPointerArray && (sub == BaseDataType.UWORD || sub == BaseDataType.WORD)
|
||||
val isUnsignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.UWORD
|
||||
val isSignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.WORD
|
||||
val isFloatArray = base.isArray && !base.isPointerArray && sub == BaseDataType.FLOAT
|
||||
val isString = base == BaseDataType.STR
|
||||
val isBool = base == BaseDataType.BOOL
|
||||
val isFloat = base == BaseDataType.FLOAT
|
||||
val isLong = base == BaseDataType.LONG
|
||||
val isStringly = base == BaseDataType.STR || base == BaseDataType.UWORD || (base == BaseDataType.ARRAY && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE))
|
||||
val isSplitWordArray = base.isSplitWordArray
|
||||
val isSplitUnsignedWordArray = base.isSplitWordArray && sub == BaseDataType.UWORD
|
||||
val isSplitSignedWordArray = base.isSplitWordArray && sub == BaseDataType.WORD
|
||||
val isSplitUnsignedWordArray = base.isSplitWordArray && !base.isPointerArray && sub == BaseDataType.UWORD
|
||||
val isSplitSignedWordArray = base.isSplitWordArray && !base.isPointerArray && sub == BaseDataType.WORD
|
||||
val isIterable = base.isIterable
|
||||
val isPassByRef = base.isPassByRef
|
||||
val isPassByValue = base.isPassByValue
|
||||
|
||||
@@ -30,7 +30,8 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR -> {
|
||||
if(decl.isArray) {
|
||||
if(decl.datatype.isSplitWordArray)
|
||||
// using a array of words as initializer to a pointer array is fine
|
||||
if (!valueDt.isSplitWordArray || !decl.datatype.isPointerArray)
|
||||
errors.err("value has incompatible type ($valueType) for the variable (${decl.datatype})", decl.value!!.position)
|
||||
} else if(!decl.datatype.isString) {
|
||||
if (valueDt.largerSizeThan(decl.datatype)) {
|
||||
|
||||
@@ -1290,4 +1290,34 @@ main {
|
||||
(st[4] as FunctionCallStatement).args.single() shouldBe instanceOf<AddressOf>()
|
||||
(st[5] as FunctionCallStatement).args.single() shouldBe instanceOf<AddressOf>()
|
||||
}
|
||||
|
||||
test("initializing arrays of pointers") {
|
||||
val src="""
|
||||
%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]
|
||||
|
||||
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]
|
||||
}
|
||||
}"""
|
||||
|
||||
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
|
||||
}
|
||||
})
|
||||
@@ -8,13 +8,39 @@ Structs and Pointers
|
||||
Legacy untyped pointers (uword)
|
||||
-------------------------------
|
||||
|
||||
Work in progress.
|
||||
Prior to version 12 of the language, the only pointer type available was a plain ``uword`` value (the memory address)
|
||||
which could be used as a pointer to an ``ubyte`` (the byte value at that memory address).
|
||||
Array indexing on an ``uword`` simply means to point to the ``ubyte`` at the location of the address + index value.
|
||||
|
||||
When the address of a value (explicitly) or a value of a reference type (string, array) was passed as an argument to a subroutine call,
|
||||
it became one of these plain ``uword`` 'pointers'. The subroutine receiving it always had to interpret the 'pointer'
|
||||
explicitly for what it actually pointed to, if that wasn't a simple byte.
|
||||
|
||||
Some implicit conversions were allowed too (such as putting ``str`` as the type of a subroutine parameter,
|
||||
which would be changed to ``uword`` by the compiler).
|
||||
|
||||
*For backward compatibility reasons, this untyped ``uword`` pointer still exists in the language.*
|
||||
|
||||
Since version 12 there now are *typed pointers* that better express the intent and tell the compiler how to use the pointer,
|
||||
these are explained below.
|
||||
|
||||
|
||||
Typed pointer to simple datatype
|
||||
--------------------------------
|
||||
|
||||
Work in progress.
|
||||
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.
|
||||
Finally, the type can be a struct type, which then declares a pointer to that struct type. This is explained in the next section.
|
||||
|
||||
``^^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.
|
||||
|
||||
It is not possible to define "pointers to arrays"; ``^^(type[])`` is invalid syntax.
|
||||
|
||||
|
||||
Structs
|
||||
|
||||
+31
-6
@@ -1,13 +1,38 @@
|
||||
%option enable_floats
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
struct Node {
|
||||
^^uword s
|
||||
}
|
||||
^^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]
|
||||
|
||||
^^Node l1
|
||||
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]
|
||||
|
||||
l1.s[0] = 4242
|
||||
l1^^.s[0] = 4242 ; TODO fix parse error
|
||||
; 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)
|
||||
}
|
||||
|
||||
; sub func(^^float zzz) {
|
||||
; cx16.r0++
|
||||
; }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</options>
|
||||
<keywords keywords="&;&<;&>;->;@;^^;alias;and;as;asmsub;break;clobbers;continue;do;downto;else;extsub;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;on;or;repeat;return;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%jmptable;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@bank;@dirty;@nosplit;@nozp;@requirezp;@shared;@split;@zp;atascii:;c64os:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords3 keywords="^^bool;^^byte;^^float;^^str;^^ubyte;^^uword;^^word;bool;byte;const;float;long;str;struct;ubyte;uword;void;word" />
|
||||
<keywords3 keywords="^^bool;^^byte;^^float;^^long;^^str;^^ubyte;^^uword;^^word;bool;byte;const;float;long;str;struct;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;bmx;call;callfar;callfar2;cbm;clamp;cmp;conv;cx16;defer;diskio;divmod;floats;len;lsb;lsw;math;max;memory;min;mkword;msb;msw;peek;peekf;peekw;poke;pokef;pokew;psg;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt;strings;sys;txt;verafx" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
|
||||
Reference in New Issue
Block a user