mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
fixed constantfolding of array values
This commit is contained in:
parent
2c08d2f9c6
commit
3a1fa9e069
@ -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 {
|
||||
|
@ -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<IExpression> = 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<DataType> = 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(',')
|
||||
|
Loading…
Reference in New Issue
Block a user