From b6a837cbeae0441a29e29c31bea54478f5aa1022 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 4 Apr 2023 22:11:51 +0200 Subject: [PATCH] fix boolean array with initialization value --- .../optimizer/ConstantIdentifierReplacer.kt | 11 +++++++++++ .../prog8/compiler/astprocessing/AstChecker.kt | 9 ++++++--- .../compiler/astprocessing/TypecastsAdder.kt | 16 +++++++++++++--- compiler/test/codegeneration/TestVariables.kt | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index e3067a8f7..45cd1caaf 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -242,6 +242,17 @@ internal class ConstantIdentifierReplacer(private val program: Program, private } } } + DataType.ARRAY_BOOL -> { + val numericLv = decl.value as? NumericLiteral + val size = decl.arraysize?.constIndex() ?: return noModifications + if(numericLv!=null) { + // arraysize initializer is a single int, and we know the size. + val fillvalue = if(numericLv.number==0.0) 0.0 else 1.0 + val array = Array(size) {fillvalue}.map { NumericLiteral(DataType.UBYTE, fillvalue, numericLv.position) }.toTypedArray() + val refValue = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_BOOL), array, position = numericLv.position) + return listOf(IAstModification.ReplaceNode(decl.value!!, refValue, decl)) + } + } else -> { // nothing to do for this type } diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index c0ee4739c..9f3bacba8 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -656,10 +656,13 @@ internal class AstChecker(private val program: Program, if (iDt isnot decl.datatype) { if(decl.datatype in ArrayDatatypes) { val eltDt = ArrayToElementTypes.getValue(decl.datatype) - if(iDt isnot eltDt) - err("initialisation value has incompatible type (${declValue.inferType(program)}) for the variable (${decl.datatype})") + if(iDt isnot eltDt) { + if(!(iDt.isBool && eltDt==DataType.UBYTE || iDt.istype(DataType.UBYTE) && eltDt==DataType.BOOL)) + err("initialisation value has incompatible type (${declValue.inferType(program)}) for the variable (${decl.datatype})") + } } else { - err("initialisation value has incompatible type (${declValue.inferType(program)}) for the variable (${decl.datatype})") + if(!(iDt.isBool && decl.datatype==DataType.UBYTE || iDt.istype(DataType.UBYTE) && decl.datatype==DataType.BOOL)) + err("initialisation value has incompatible type (${declValue.inferType(program)}) for the variable (${decl.datatype})") } } } diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index b6e1c0c0b..af6f6c8e7 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -23,9 +23,19 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val val valueDt = declValue.inferType(program) if(valueDt isnot decl.datatype) { - // don't add a typecast on an array initializer value - if(valueDt.isInteger && decl.datatype in ArrayDatatypes) - return noModifications + // don't add a typecast on an array initializer value, unless booleans + if(valueDt.isInteger && decl.datatype in ArrayDatatypes) { + if(decl.datatype == DataType.ARRAY_BOOL) { + val integer = declValue.constValue(program)?.number + if(integer!=null) { + val num = NumericLiteral(DataType.UBYTE, if(integer==0.0) 0.0 else 1.0, declValue.position) + num.parent = decl + decl.value = num + } + } else { + return noModifications + } + } // don't add a typecast if the initializer value is inherently not assignable if(valueDt isNotAssignableTo decl.datatype) diff --git a/compiler/test/codegeneration/TestVariables.kt b/compiler/test/codegeneration/TestVariables.kt index 24c425ead..36ad68528 100644 --- a/compiler/test/codegeneration/TestVariables.kt +++ b/compiler/test/codegeneration/TestVariables.kt @@ -80,4 +80,19 @@ class TestVariables: FunSpec({ compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null } + test("initialization of boolean array with single value") { + val text = """ + main { + sub start() { + bool[10] sieve0 = false + bool[10] sieve1 = true + bool[10] sieve2 = 42 + sieve0[0] = true + sieve1[0] = true + sieve2[0] = true + } + } + """ + compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null + } })