From 4372de1e7ea84201ebb6cae94ea98be193700201 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 29 Sep 2020 00:03:47 +0200 Subject: [PATCH] allow creating arrays of pointers to other arrays. Usefullness is very limited though... --- compiler/src/prog8/ast/expressions/AstExpressions.kt | 6 ++++++ compiler/src/prog8/ast/processing/AstChecker.kt | 10 ++++------ .../target/c64/codegen/assignment/AsmAssignment.kt | 2 +- docs/source/programming.rst | 6 ++++-- docs/source/syntaxreference.rst | 2 +- examples/test.p8 | 12 ++++++++++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/compiler/src/prog8/ast/expressions/AstExpressions.kt b/compiler/src/prog8/ast/expressions/AstExpressions.kt index 2ddfd5e39..bf11840d0 100644 --- a/compiler/src/prog8/ast/expressions/AstExpressions.kt +++ b/compiler/src/prog8/ast/expressions/AstExpressions.kt @@ -574,6 +574,12 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be DataType.UWORD in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW) DataType.BYTE in dts -> InferredTypes.InferredType.known(DataType.ARRAY_B) DataType.UBYTE in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UB) + DataType.ARRAY_UW in dts || + DataType.ARRAY_W in dts || + DataType.ARRAY_UB in dts || + DataType.ARRAY_B in dts || + DataType.ARRAY_F in dts || + DataType.STRUCT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW) else -> InferredTypes.InferredType.unknown() } } diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 38bcf9f19..80ea67a66 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -742,18 +742,16 @@ internal class AstChecker(private val program: Program, checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), null, arrayspec, array) } - fun isStringElement(e: Expression): Boolean { + fun isPassByReferenceElement(e: Expression): Boolean { if(e is IdentifierReference) { val decl = e.targetVarDecl(program.namespace)!! - return decl.datatype==DataType.STR + return decl.datatype in PassByReferenceDatatypes } return e is StringLiteralValue } - if(!array.value.all { it is NumericLiteralValue || it is AddressOf || isStringElement(it) }) { - // TODO for now, array literals have to consist of all compile time constant values... - errors.err("array literal doesn't consist of only compile time constant values", array.position) - } + if(!array.value.all { it is NumericLiteralValue || it is AddressOf || isPassByReferenceElement(it) }) + errors.err("array literal contains invalid types", array.position) super.visit(array) } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt index ab517b5f4..859813d6e 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt @@ -41,7 +41,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind, { val constMemoryAddress by lazy { memory?.addressExpression?.constValue(program)?.number?.toInt() ?: 0} val constArrayIndexValue by lazy { array?.arrayspec?.constIndex() } - val vardecl by lazy { variable?.targetVarDecl(program.namespace)!! } + val vardecl by lazy { variable!!.targetVarDecl(program.namespace)!! } val asmVarname by lazy { if(variable!=null) asmgen.asmVariableName(variable) diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 842a7da98..0870cecb3 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -236,13 +236,15 @@ The largest 5-byte MFLPT float that can be stored is: **1.7014118345e+38** (ne Arrays ^^^^^^ -Array types are also supported. They can be made of bytes, words or floats, and strings:: +Array types are also supported. They can be made of bytes, words or floats, strings, and other arrays +(although the usefulness of the latter is very limited for now):: byte[10] array ; array of 10 bytes, initially set to 0 byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value byte[99] array = 255 ; initialize array with 99 times 255 [255, 255, 255, 255, ...] byte[] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199] str[] names = ["ally", "pete"] ; array of string pointers/addresses (equivalent to uword) + uword[] others = [names, array] ; array of pointers/addresses to other arrays value = array[3] ; the fourth value in the array (index is 0-based) char = string[4] ; the fifth character (=byte) in the string @@ -334,7 +336,7 @@ and then create a variable with it:: ubyte blue } - Color rgb = {255,122,0} ; note the curly braces here instead of brackets + Color rgb = [255,122,0] ; note that struct initializer value is same as an array Color another ; the init value is optional, like arrays another = rgb ; assign all of the values of rgb to another diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 2c1a87ed3..dda688e4f 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -399,7 +399,7 @@ After defining a struct you can use the name of the struct as a data type to dec Struct variables can be assigned a struct literal value (also in their declaration as initial value):: - Color rgb = {255, 100, 0} ; curly braces instead of brackets + Color rgb = [255, 100, 0] ; note that the value is an array Operators diff --git a/examples/test.p8 b/examples/test.p8 index 939d6921d..107ed2aa0 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,6 +8,18 @@ main { str[] names = ["aap", "noot", "mies", "vuur"] uword[] names3 = ["aap", "noot", "mies", "vuur"] ubyte[] values = [11,22,33,44] + uword[] arrays = [names, names3, values] + + struct Color { + ubyte red + ubyte green + ubyte blue + } + + Color c1 = [11,22,33] ; TODO fix crash + Color c2 = [11,22,33] ; TODO fix crash + Color c3 = [11,22,33] ; TODO fix crash + ; uword[] colors = [ c1, c2, c3] sub start() { uword s