From 3a1fa9e06986180f9ffe85e10144bcd20ddc2e92 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 1 Jul 2019 13:43:14 +0200 Subject: [PATCH] fixed constantfolding of array values --- compiler/src/prog8/ast/AST.kt | 17 ++- .../src/prog8/optimizing/ConstantFolding.kt | 113 ++++++++++-------- examples/test.p8 | 21 ++-- 3 files changed, 88 insertions(+), 63 deletions(-) diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 192100218..26f9aa1ef 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -228,7 +228,12 @@ interface IAstProcessor { } fun process(literalValue: LiteralValue): LiteralValue { - literalValue.arrayvalue?.forEach { it.process(this) } + if(literalValue.arrayvalue!=null && literalValue.heapId==null) { + for(av in literalValue.arrayvalue.withIndex()) { + val newvalue = av.value.process(this) + literalValue.arrayvalue[av.index] = newvalue + } + } return literalValue } @@ -1386,7 +1391,15 @@ open class LiteralValue(val type: DataType, arrayvalue?.forEach {it.linkParents(this)} } - override fun constValue(program: Program): LiteralValue? = this + override fun constValue(program: Program): LiteralValue? { + if(arrayvalue!=null) { + for(v in arrayvalue) { + if(v.constValue(program)==null) return null + } + } + return this + } + override fun process(processor: IAstProcessor) = processor.process(this) override fun toString(): String { diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 34a9d48da..80277d5f5 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -592,30 +592,67 @@ class ConstantFolding(private val program: Program) : IAstProcessor { } override fun process(literalValue: LiteralValue): LiteralValue { - if(literalValue.isString) { + val litval = super.process(literalValue) + if(litval.isString) { // intern the string; move it into the heap - if(literalValue.strvalue(program.heap).length !in 1..255) - addError(ExpressionError("string literal length must be between 1 and 255", literalValue.position)) + if(litval.strvalue(program.heap).length !in 1..255) + addError(ExpressionError("string literal length must be between 1 and 255", litval.position)) else { - val heapId = program.heap.addString(literalValue.type, literalValue.strvalue(program.heap)) // TODO: we don't know the actual string type yet, STR != STR_S etc... - val newValue = LiteralValue(literalValue.type, heapId = heapId, position = literalValue.position) + val heapId = program.heap.addString(litval.type, litval.strvalue(program.heap)) // TODO: we don't know the actual string type yet, STR != STR_S etc... + val newValue = LiteralValue(litval.type, heapId = heapId, position = litval.position) return super.process(newValue) } - } else if(literalValue.arrayvalue!=null) { - return moveArrayToHeap(literalValue) + } else if(litval.arrayvalue!=null) { + // first, adjust the array datatype + val litval2 = adjustArrayValDatatype(litval) + return moveArrayToHeap(litval2) } + return litval + } - return super.process(literalValue) + private fun adjustArrayValDatatype(litval: LiteralValue): LiteralValue { + val array = litval.arrayvalue!! + val typesInArray = array.mapNotNull { it.inferType(program) }.toSet() + val arrayDt = + when { + array.any { it is AddressOf} -> DataType.ARRAY_UW + DataType.FLOAT in typesInArray -> DataType.ARRAY_F + DataType.WORD in typesInArray -> DataType.ARRAY_W + else -> { + val allElementsAreConstantOrAddressOf = array.fold(true) { c, expr-> c and (expr is LiteralValue || expr is AddressOf)} + if(!allElementsAreConstantOrAddressOf) { + addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", litval.position)) + return litval + } else { + val integerArray = array.map { it.constValue(program)!!.asIntegerValue!! } + val maxValue = integerArray.max()!! + val minValue = integerArray.min()!! + if (minValue >= 0) { + // unsigned + if (maxValue <= 255) + DataType.ARRAY_UB + else + DataType.ARRAY_UW + } else { + // signed + if (maxValue <= 127) + DataType.ARRAY_B + else + DataType.ARRAY_W + } + } + } + } + + if(arrayDt!=litval.type) { + return LiteralValue(arrayDt, arrayvalue = litval.arrayvalue, position = litval.position) + } + return litval } private fun moveArrayToHeap(arraylit: LiteralValue): LiteralValue { val array: Array = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray() - val allElementsAreConstantOrAddressOf = array.fold(true) { c, expr-> c and (expr is LiteralValue || expr is AddressOf)} - if(!allElementsAreConstantOrAddressOf) { - addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", arraylit.position)) - return arraylit - } else if(array.any {it is AddressOf}) { - val arrayDt = DataType.ARRAY_UW + if(array.any {it is AddressOf}) { val intArrayWithAddressOfs = array.map { when (it) { is AddressOf -> IntegerOrAddressOf(null, it) @@ -623,50 +660,26 @@ class ConstantFolding(private val program: Program) : IAstProcessor { else -> throw CompilerException("invalid datatype in array") } } - val heapId = program.heap.addIntegerArray(arrayDt, intArrayWithAddressOfs.toTypedArray()) - return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position) + val heapId = program.heap.addIntegerArray(arraylit.type, intArrayWithAddressOfs.toTypedArray()) + return LiteralValue(arraylit.type, heapId = heapId, position = arraylit.position) } else { // array is only constant numerical values val valuesInArray = array.map { it.constValue(program)!!.asNumericValue!! } - val integerArray = valuesInArray.map{ it.toInt() } - val doubleArray = valuesInArray.map{it.toDouble()}.toDoubleArray() - val typesInArray: Set = array.mapNotNull { it.inferType(program) }.toSet() - - // Take an educated guess about the array type. - // This may be altered (if needed & if possible) to suit an array declaration type later! - // Also, the check if all values are valid for the given datatype is done later, in the AstChecker. - val arrayDt = - if(DataType.FLOAT in typesInArray) - DataType.ARRAY_F - else if(DataType.WORD in typesInArray) { - DataType.ARRAY_W - } else { - val maxValue = integerArray.max()!! - val minValue = integerArray.min()!! - if (minValue >= 0) { - // unsigned - if (maxValue <= 255) - DataType.ARRAY_UB - else - DataType.ARRAY_UW - } else { - // signed - if (maxValue <= 127) - DataType.ARRAY_B - else - DataType.ARRAY_W - } - } - - val heapId = when(arrayDt) { + val heapId = when(arraylit.type) { DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, - DataType.ARRAY_W -> program.heap.addIntegerArray(arrayDt, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray()) - DataType.ARRAY_F -> program.heap.addDoublesArray(doubleArray) + DataType.ARRAY_W -> { + val integerArray = valuesInArray.map{ it.toInt() } + program.heap.addIntegerArray(arraylit.type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray()) + } + DataType.ARRAY_F -> { + val doubleArray = valuesInArray.map{it.toDouble()}.toDoubleArray() + program.heap.addDoublesArray(doubleArray) + } else -> throw CompilerException("invalid arraysize type") } - return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position) + return LiteralValue(arraylit.type, heapId = heapId, position = arraylit.position) } } diff --git a/examples/test.p8 b/examples/test.p8 index 1e6415de1..9fa3b9d53 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,21 +1,20 @@ -%import c64utils -%zeropage basicsafe -%import c64flt +;%import c64utils +;%zeropage basicsafe +;%import c64flt ~ main { sub start() { + float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ] - float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ] - - ; storage for rotated coordinates - ubyte[len(xcoor)] xx = 2 - float[len(xcoor)] rotatedx=0.0 - - ubyte[4] x = 23 - float[4] yy = 4.4 + ; storage for rotated coordinates +; ubyte[len(xcoor)] xx = 2 +; float[len(xcoor)] rotatedx=0.0 +; +; ubyte[4] x = 23 +; float[4] yy = 4.4 ; c64flt.print_f(xcoor[1]) ; c64.CHROUT(',')