diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 25d977220..3a97696b3 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -492,7 +492,7 @@ private class AstChecker(private val namespace: INameScope, checkResult.add(SyntaxError("floating point used, but that is not enabled via options", decl.position)) } - // ARRAY without size specifier MUST have an initializer value + // ARRAY without size specifier MUST have an iterable initializer value if(decl.isUnsizedArray) { if(decl.type==VarDeclType.MEMORY) checkResult.add(SyntaxError("memory mapped array must have a size specification", decl.position)) @@ -500,6 +500,12 @@ private class AstChecker(private val namespace: INameScope, checkResult.add(SyntaxError("array variable is missing a size specification or an initialization value", decl.position)) return decl } + if(decl.value is LiteralValue && !(decl.value as LiteralValue).isArray) { + checkResult.add(SyntaxError("unsized array declaration cannot use a single literal initialization value", decl.position)) + return decl + } + if(decl.value is RangeExpr) + throw FatalAstException("range expressions in vardecls should have been converted into array values during constFolding $decl") } when(decl.type) { diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index db02631fd..5eeccd9eb 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -45,6 +45,24 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV } } DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> { + val rangeExpr = decl.value as? RangeExpr + if(rangeExpr!=null) { + // convert the initializer range expression to an actual array + val constRange = rangeExpr.toConstantIntegerRange(heap) + if(constRange!=null) { + val eltType = rangeExpr.resultingDatatype(namespace, heap)!! + if(eltType in ByteDatatypes) { + decl.value = LiteralValue(decl.datatype, + arrayvalue = constRange.map { LiteralValue(eltType, bytevalue=it.toShort(), position = decl.value!!.position ) } + .toTypedArray(), position=decl.value!!.position) + } else { + decl.value = LiteralValue(decl.datatype, + arrayvalue = constRange.map { LiteralValue(eltType, wordvalue= it, position = decl.value!!.position ) } + .toTypedArray(), position=decl.value!!.position) + } + decl.value!!.linkParents(decl) + } + } if(litval?.type==DataType.FLOAT) errors.add(ExpressionError("arraysize requires only integers here", litval.position)) if(decl.arraysize==null) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 80e3460f1..f89350245 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -60,7 +60,7 @@ of values together (and use it multiple times). Something like:: struct Point { ubyte color - word[3] vec = [0,0,0] + word[] vec = [0,0,0] } Point p1 diff --git a/examples/test.p8 b/examples/test.p8 index 45dbb7de6..c51ee910f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,16 +4,15 @@ sub start() { - ; @todo documentation on array without size - ubyte[5] array2 = 20 to 100 ; @todo fix this initializer value word[5] array3 = 3000 to 3100 ; @todo fix this initializer value - byte[] derp = 99 ; @todo better ast error c64scr.print_uw(len(array2)) c64.CHROUT('\n') c64scr.print_uw(len(array3)) c64.CHROUT('\n') + c64scr.print_uw(len(array4)) + c64.CHROUT('\n') c64.CHROUT('\n') c64scr.print_ub(array2[0]) c64.CHROUT(',')