mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 08:29:25 +00:00
fix array initialization
This commit is contained in:
parent
1fe5c943fd
commit
cc54e3ec99
@ -8,32 +8,32 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
byte[3] barr1 = [-2,-1,2]
|
byte[4] barr1 = -2
|
||||||
byte[3] barr2 = [-22,-1, 3]
|
byte[4] barr2 = 33
|
||||||
ubyte[3] barr3 = [-2,-1,2] ; @ todo error
|
ubyte[4] barr4 = 2
|
||||||
ubyte[3] barr4 = [1,2,33]
|
ubyte[4] barr5 = 44
|
||||||
ubyte[3] barr5 = [1,2,-33] ; @todo error
|
word[4] warr1 = 4444
|
||||||
word[3] warr1 = [-2,-1,2]
|
word[4] warr2 = -5555
|
||||||
;word[3] warr2 = [-2,-1,2, 3453] ; @todo ok
|
word[4] warr2b = -5522
|
||||||
uword[3] warr3 = [-2,-1,2]
|
float[4] farr1
|
||||||
uword[3] warr4 = [1,2,33.w]
|
float[4] farr2 = 23
|
||||||
uword[3] warr5 = [1,2,-33] ; @todo error
|
float[4] farr3 = 55.636346
|
||||||
|
|
||||||
byte b1 = 50 * 2
|
; byte b1 = 50 * 2
|
||||||
byte b2 = -50 * 2
|
; byte b2 = -50 * 2
|
||||||
ubyte ub1 = 50 * 2
|
; ubyte ub1 = 50 * 2
|
||||||
word w1 = 999 * 2
|
; word w1 = 999 * 2
|
||||||
word w2 = -999 * 2
|
; word w2 = -999 * 2
|
||||||
uword uw1 = 999 * 2
|
; uword uw1 = 999 * 2
|
||||||
float f1 = 999*2
|
; float f1 = 999*2
|
||||||
float f2 = -999*2
|
; float f2 = -999*2
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub toscreenx(x: float, z: float) -> word {
|
; sub toscreenx(x: float, z: float) -> word {
|
||||||
return floor(x/(4.2+z) * flt(height)) + width // 2
|
; return floor(x/(4.2+z) * flt(height)) + width // 2
|
||||||
}
|
; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -560,6 +560,13 @@ class ArraySpec(var x: IExpression, var y: IExpression?, override val position:
|
|||||||
y?.linkParents(this)
|
y?.linkParents(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun forArray(v: LiteralValue, heap: HeapValues): ArraySpec {
|
||||||
|
val arraySize = v.arrayvalue?.size ?: heap.get(v.heapId!!).arraysize
|
||||||
|
return ArraySpec(LiteralValue.optimalInteger(arraySize, v.position), null, v.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun process(processor: IAstProcessor) {
|
fun process(processor: IAstProcessor) {
|
||||||
x = x.process(processor)
|
x = x.process(processor)
|
||||||
y = y?.process(processor)
|
y = y?.process(processor)
|
||||||
@ -1042,7 +1049,12 @@ class LiteralValue(val type: DataType,
|
|||||||
val fh = floatvalue?.hashCode() ?: 0x00103456
|
val fh = floatvalue?.hashCode() ?: 0x00103456
|
||||||
val sh = strvalue?.hashCode() ?: 0x00014567
|
val sh = strvalue?.hashCode() ?: 0x00014567
|
||||||
val ah = arrayvalue?.hashCode() ?: 0x11119876
|
val ah = arrayvalue?.hashCode() ?: 0x11119876
|
||||||
return bh xor wh xor fh xor sh xor ah xor type.hashCode()
|
var hash = bh * 31 xor wh
|
||||||
|
hash = hash*31 xor fh
|
||||||
|
hash = hash*31 xor sh
|
||||||
|
hash = hash*31 xor ah
|
||||||
|
hash = hash*31 xor type.hashCode()
|
||||||
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@ -1906,7 +1918,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
|
|||||||
litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition())
|
litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition())
|
||||||
litval.arrayliteral()!=null -> {
|
litval.arrayliteral()!=null -> {
|
||||||
val array = litval.arrayliteral()?.toAst()
|
val array = litval.arrayliteral()?.toAst()
|
||||||
// byte/word array type difference is not determined here.
|
// the actual type of the array can not yet be determined here (missing namespace & heap)
|
||||||
// the ConstantFolder takes care of that and converts the type if needed.
|
// the ConstantFolder takes care of that and converts the type if needed.
|
||||||
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
|
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
|
||||||
}
|
}
|
||||||
|
@ -415,9 +415,15 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
decl.value is RangeExpr -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as RangeExpr)
|
decl.value is RangeExpr -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as RangeExpr)
|
||||||
decl.value is LiteralValue -> checkValueTypeAndRange(decl.datatype,
|
decl.value is LiteralValue -> {
|
||||||
decl.arrayspec ?: ArraySpec(LiteralValue.optimalInteger(-2, decl.position), null, decl.position),
|
val arraySpec = decl.arrayspec ?: (
|
||||||
decl.value as LiteralValue, heap)
|
if((decl.value as LiteralValue).isArray)
|
||||||
|
ArraySpec.forArray(decl.value as LiteralValue, heap)
|
||||||
|
else
|
||||||
|
ArraySpec(LiteralValue.optimalInteger(-2, decl.position), null, decl.position)
|
||||||
|
)
|
||||||
|
checkValueTypeAndRange(decl.datatype, arraySpec, decl.value as LiteralValue, heap)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!::class.simpleName}")
|
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!::class.simpleName}")
|
||||||
return super.process(decl)
|
return super.process(decl)
|
||||||
@ -515,9 +521,12 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
if(!compilerOptions.floats && literalValue.type==DataType.FLOAT) {
|
if(!compilerOptions.floats && literalValue.type==DataType.FLOAT) {
|
||||||
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
|
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
|
||||||
}
|
}
|
||||||
checkValueTypeAndRange(literalValue.type,
|
val arrayspec =
|
||||||
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), null, literalValue.position),
|
if(literalValue.isArray)
|
||||||
literalValue, heap)
|
ArraySpec.forArray(literalValue, heap)
|
||||||
|
else
|
||||||
|
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), null, literalValue.position)
|
||||||
|
checkValueTypeAndRange(literalValue.type, arrayspec, literalValue, heap)
|
||||||
|
|
||||||
val lv = super.process(literalValue)
|
val lv = super.process(literalValue)
|
||||||
when(lv.type) {
|
when(lv.type) {
|
||||||
@ -798,7 +807,7 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
}
|
}
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||||
// value may be either a single byte, or a byte array (of all constant values)
|
// value may be either a single byte, or a byte array (of all constant values)
|
||||||
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_B) {
|
if(value.type==targetDt) {
|
||||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
|
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
|
||||||
val arraySpecSize = arrayspec.size()
|
val arraySpecSize = arrayspec.size()
|
||||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||||
@ -808,66 +817,34 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
val expectedSize = constX.asIntegerValue
|
val expectedSize = constX.asIntegerValue
|
||||||
if (arraySize != expectedSize)
|
if (arraySize != expectedSize)
|
||||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||||
}
|
return true
|
||||||
} else if(value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_W) {
|
|
||||||
return err("initialization value must be an array of bytes")
|
|
||||||
} else {
|
|
||||||
if(targetDt==DataType.ARRAY_UB) {
|
|
||||||
val number = value.bytevalue ?: return if (value.floatvalue != null)
|
|
||||||
err("unsigned byte value expected instead of float; possible loss of precision")
|
|
||||||
else
|
|
||||||
err("unsigned byte value expected")
|
|
||||||
if (number < 0 || number > 255)
|
|
||||||
return err("value '$number' out of range for unsigned byte")
|
|
||||||
} else {
|
|
||||||
val number = value.bytevalue ?: return if (value.floatvalue != null)
|
|
||||||
err("byte value expected instead of float; possible loss of precision")
|
|
||||||
else
|
|
||||||
err("byte value expected")
|
|
||||||
if (number < -128 || number > 127)
|
|
||||||
return err("value '$number' out of range for byte")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return err("invalid array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||||
// value may be either a single word, or a word array
|
// value may be either a single word, or a word array
|
||||||
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_B || value.type==DataType.ARRAY_W) {
|
if(value.type==targetDt) {
|
||||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
|
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).array!!.size
|
||||||
val arraySpecSize = arrayspec.size()
|
val arraySpecSize = arrayspec.size()
|
||||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||||
// arrayspec is not always known when checking
|
|
||||||
val constX = arrayspec.x.constValue(namespace, heap)
|
val constX = arrayspec.x.constValue(namespace, heap)
|
||||||
if(constX?.asIntegerValue==null)
|
if(constX?.asIntegerValue==null)
|
||||||
return err("array size specifier must be constant integer value")
|
return err("array size specifier must be constant integer value")
|
||||||
val expectedSize = constX.asIntegerValue
|
val expectedSize = constX.asIntegerValue
|
||||||
if (arraySize != expectedSize)
|
if (arraySize != expectedSize)
|
||||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||||
}
|
return true
|
||||||
} else {
|
|
||||||
if(targetDt==DataType.ARRAY_UW) {
|
|
||||||
val number = value.asIntegerValue ?: return if (value.floatvalue != null)
|
|
||||||
err("unsigned byte or word value expected instead of float; possible loss of precision")
|
|
||||||
else
|
|
||||||
err("unsigned byte or word value expected")
|
|
||||||
if (number < 0 || number > 65535)
|
|
||||||
return err("value '$number' out of range for unsigned word")
|
|
||||||
} else {
|
|
||||||
val number = value.asIntegerValue ?: return if (value.floatvalue != null)
|
|
||||||
err("byte or word value expected instead of float; possible loss of precision")
|
|
||||||
else
|
|
||||||
err("byte or word value expected")
|
|
||||||
if (number < -32768 || number > 32767)
|
|
||||||
return err("value '$number' out of range for word")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return err("invalid array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
// value may be either a single float, or a float array
|
// value may be either a single float, or a float array
|
||||||
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_UW || value.type==DataType.ARRAY_F) {
|
if(value.type==targetDt) {
|
||||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
|
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).doubleArray!!.size
|
||||||
val arraySpecSize = arrayspec.size()
|
val arraySpecSize = arrayspec.size()
|
||||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||||
// arrayspec is not always known when checking
|
|
||||||
val constX = arrayspec.x.constValue(namespace, heap)
|
val constX = arrayspec.x.constValue(namespace, heap)
|
||||||
if(constX?.asIntegerValue==null)
|
if(constX?.asIntegerValue==null)
|
||||||
return err("array size specifier must be constant integer value")
|
return err("array size specifier must be constant integer value")
|
||||||
@ -875,17 +852,20 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
if (arraySize != expectedSize)
|
if (arraySize != expectedSize)
|
||||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||||
}
|
}
|
||||||
} else {
|
// check if the floating point values are all within range
|
||||||
val number = value.asNumericValue?.toDouble()
|
val doubles = if(value.arrayvalue!=null)
|
||||||
if(number==null)
|
value.arrayvalue.map {it.constValue(namespace, heap)?.asNumericValue!!.toDouble()}.toDoubleArray()
|
||||||
return err("expected numerical value")
|
else
|
||||||
else if (number < FLOAT_MAX_NEGATIVE || number > FLOAT_MAX_POSITIVE)
|
heap.get(value.heapId!!).doubleArray!!
|
||||||
return err("value '$number' out of range for mfplt5 floating point")
|
if(doubles.any { it < FLOAT_MAX_NEGATIVE || it> FLOAT_MAX_POSITIVE})
|
||||||
|
return err("floating point value overflow")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
return err("invalid array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||||
// value can only be a single byte, or a byte array (which represents the matrix)
|
// value can only be a single byte, or a byte array (which represents the matrix)
|
||||||
if(value.type==DataType.ARRAY_UB || value.type==DataType.ARRAY_B || value.type==DataType.MATRIX_UB || value.type==DataType.MATRIX_B) {
|
if(value.type==targetDt) {
|
||||||
val arraySpecSize = arrayspec.size()
|
val arraySpecSize = arrayspec.size()
|
||||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||||
val constX = arrayspec.x.constValue(namespace, heap)
|
val constX = arrayspec.x.constValue(namespace, heap)
|
||||||
@ -897,19 +877,8 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
if (matrix.size != expectedSize)
|
if (matrix.size != expectedSize)
|
||||||
return err("initializer matrix size mismatch (expecting $expectedSize, got ${matrix.size} elements)")
|
return err("initializer matrix size mismatch (expecting $expectedSize, got ${matrix.size} elements)")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if(targetDt==DataType.MATRIX_UB) {
|
|
||||||
val number = value.bytevalue
|
|
||||||
?: return err("unsigned byte value expected")
|
|
||||||
if (number < 0 || number > 255)
|
|
||||||
return err("value '$number' out of range for unsigned byte")
|
|
||||||
} else {
|
|
||||||
val number = value.bytevalue
|
|
||||||
?: return err("byte value expected")
|
|
||||||
if (number < -128 || number > 127)
|
|
||||||
return err("value '$number' out of range for byte")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return err("invalid matrix initialization value $value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package prog8.optimizing
|
package prog8.optimizing
|
||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
|
import prog8.compiler.CompilerException
|
||||||
import prog8.compiler.HeapValues
|
import prog8.compiler.HeapValues
|
||||||
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
|
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
|
||||||
import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
|
import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
|
||||||
@ -54,6 +55,8 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
|||||||
}
|
}
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||||
val litval = decl.value as? LiteralValue
|
val litval = decl.value as? LiteralValue
|
||||||
|
if(litval?.type==DataType.FLOAT)
|
||||||
|
errors.add(ExpressionError("array requires only integers here", litval.position))
|
||||||
val size = decl.arrayspec!!.size()
|
val size = decl.arrayspec!!.size()
|
||||||
if(litval!=null && litval.isArray) {
|
if(litval!=null && litval.isArray) {
|
||||||
// array initializer value is an array already, keep as-is (or convert to WORDs if needed)
|
// array initializer value is an array already, keep as-is (or convert to WORDs if needed)
|
||||||
@ -67,11 +70,36 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
|||||||
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_UW, null, array.array, null))
|
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_UW, null, array.array, null))
|
||||||
decl.value = LiteralValue(decl.datatype, heapId = litval.heapId, position = litval.position)
|
decl.value = LiteralValue(decl.datatype, heapId = litval.heapId, position = litval.position)
|
||||||
}
|
}
|
||||||
|
} else if(decl.datatype==DataType.ARRAY_W && litval.type == DataType.ARRAY_B) {
|
||||||
|
val array = heap.get(litval.heapId)
|
||||||
|
if(array.array!=null) {
|
||||||
|
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_W, null, array.array, null))
|
||||||
|
decl.value = LiteralValue(decl.datatype, heapId = litval.heapId, position = litval.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (size != null) {
|
} else if (size != null) {
|
||||||
// array initializer is empty or a single int, and we know the size; create the array.
|
// array initializer is empty or a single int, and we know the size; create the array.
|
||||||
val fillvalue = if (litval == null) 0 else litval.asIntegerValue ?: 0
|
val fillvalue = if (litval == null) 0 else litval.asIntegerValue ?: 0
|
||||||
|
when(decl.datatype){
|
||||||
|
DataType.ARRAY_UB, DataType.MATRIX_UB -> {
|
||||||
|
if(fillvalue !in 0..255)
|
||||||
|
errors.add(ExpressionError("ubyte value overflow", litval?.position ?: decl.position))
|
||||||
|
}
|
||||||
|
DataType.ARRAY_B, DataType.MATRIX_B -> {
|
||||||
|
if(fillvalue !in -128..127)
|
||||||
|
errors.add(ExpressionError("byte value overflow", litval?.position ?: decl.position))
|
||||||
|
}
|
||||||
|
DataType.ARRAY_UW -> {
|
||||||
|
if(fillvalue !in 0..65535)
|
||||||
|
errors.add(ExpressionError("uword value overflow", litval?.position ?: decl.position))
|
||||||
|
}
|
||||||
|
DataType.ARRAY_W -> {
|
||||||
|
if(fillvalue !in -32768..32767)
|
||||||
|
errors.add(ExpressionError("word value overflow", litval?.position ?: decl.position))
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
val fillArray = IntArray(size) { _ -> fillvalue }
|
val fillArray = IntArray(size) { _ -> fillvalue }
|
||||||
val heapId = heap.add(decl.datatype, fillArray)
|
val heapId = heap.add(decl.datatype, fillArray)
|
||||||
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
||||||
@ -93,9 +121,13 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
|||||||
} else if (size != null) {
|
} else if (size != null) {
|
||||||
// array initializer is empty or a single int, and we know the size; create the array.
|
// array initializer is empty or a single int, and we know the size; create the array.
|
||||||
val fillvalue = if (litval == null) 0.0 else litval.asNumericValue?.toDouble() ?: 0.0
|
val fillvalue = if (litval == null) 0.0 else litval.asNumericValue?.toDouble() ?: 0.0
|
||||||
val fillArray = DoubleArray(size) { _ -> fillvalue }
|
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
|
||||||
val heapId = heap.add(decl.datatype, fillArray)
|
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
|
||||||
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
else {
|
||||||
|
val fillArray = DoubleArray(size) { _ -> fillvalue }
|
||||||
|
val heapId = heap.add(decl.datatype, fillArray)
|
||||||
|
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> return result
|
else -> return result
|
||||||
@ -437,100 +469,63 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
|||||||
return super.process(newValue)
|
return super.process(newValue)
|
||||||
}
|
}
|
||||||
} else if(literalValue.arrayvalue!=null) {
|
} else if(literalValue.arrayvalue!=null) {
|
||||||
val newArray = literalValue.arrayvalue.map { it.process(this) }.toTypedArray()
|
return moveArrayToHeap(literalValue)
|
||||||
val arrayDt =
|
|
||||||
if(newArray.any { it.resultingDatatype(namespace, heap) == DataType.FLOAT })
|
|
||||||
DataType.ARRAY_F
|
|
||||||
else {
|
|
||||||
if (newArray.any { it.resultingDatatype(namespace, heap) in setOf(DataType.BYTE, DataType.WORD) }) {
|
|
||||||
// we have signed values
|
|
||||||
if (newArray.any { it.resultingDatatype(namespace, heap) == DataType.WORD })
|
|
||||||
DataType.ARRAY_W
|
|
||||||
else
|
|
||||||
DataType.ARRAY_B
|
|
||||||
} else {
|
|
||||||
// only unsigned values
|
|
||||||
if (newArray.any { it.resultingDatatype(namespace, heap) == DataType.UWORD })
|
|
||||||
DataType.ARRAY_UW
|
|
||||||
else DataType.ARRAY_UB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the values are all constants, the array is moved to the heap
|
|
||||||
val allElementsAreConstant = newArray.fold(true) { c, expr-> c and (expr is LiteralValue)}
|
|
||||||
if(allElementsAreConstant) {
|
|
||||||
val litArray = newArray.map{ it as? LiteralValue }
|
|
||||||
if(null in litArray) {
|
|
||||||
addError(ExpressionError("array/matrix literal can contain only constant values", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
if(arrayDt==DataType.ARRAY_UB || arrayDt==DataType.MATRIX_UB) {
|
|
||||||
// all values should be ubytes
|
|
||||||
val integerArray = litArray.map { (it as LiteralValue).bytevalue }
|
|
||||||
if (integerArray.any { it == null || it.toInt() !in 0..255 }) {
|
|
||||||
addError(ExpressionError("byte array elements must all be integers 0..255", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
val array = integerArray.mapNotNull { it?.toInt() }.toIntArray()
|
|
||||||
val heapId = heap.add(arrayDt, array)
|
|
||||||
val newValue = LiteralValue(arrayDt, heapId = heapId, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
} else if(arrayDt==DataType.ARRAY_B || arrayDt==DataType.MATRIX_B) {
|
|
||||||
// all values should be bytes
|
|
||||||
val integerArray = litArray.map { (it as LiteralValue).bytevalue }
|
|
||||||
if(integerArray.any { it==null || it.toInt() !in -128..127 }) {
|
|
||||||
addError(ExpressionError("byte array elements must all be integers -128..127", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
val array = integerArray.mapNotNull { it?.toInt() }.toIntArray()
|
|
||||||
val heapId = heap.add(arrayDt, array)
|
|
||||||
val newValue = LiteralValue(arrayDt, heapId=heapId, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
} else if(arrayDt==DataType.ARRAY_UW) {
|
|
||||||
// all values should be bytes or words
|
|
||||||
val integerArray = litArray.map { (it as LiteralValue).asIntegerValue }
|
|
||||||
if(integerArray.any {it==null || it !in 0..65535 }) {
|
|
||||||
addError(ExpressionError("word array elements must all be integers 0..65535", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
val array = integerArray.filterNotNull().toIntArray()
|
|
||||||
val heapId = heap.add(arrayDt, array)
|
|
||||||
val newValue = LiteralValue(DataType.ARRAY_UW, heapId=heapId, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
} else if(arrayDt==DataType.ARRAY_W) {
|
|
||||||
// all values should be bytes or words
|
|
||||||
val integerArray = litArray.map { (it as LiteralValue).asIntegerValue }
|
|
||||||
if(integerArray.any {it==null || it !in -32768..32767 }) {
|
|
||||||
addError(ExpressionError("word array elements must all be integers -32768..32767", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
val array = integerArray.filterNotNull().toIntArray()
|
|
||||||
val heapId = heap.add(arrayDt, array)
|
|
||||||
val newValue = LiteralValue(DataType.ARRAY_W, heapId=heapId, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
} else if(arrayDt==DataType.ARRAY_F) {
|
|
||||||
// all values should be bytes, words or floats
|
|
||||||
val doubleArray = litArray.map { (it as LiteralValue).asNumericValue?.toDouble() }
|
|
||||||
if(doubleArray.any { it==null || it !in FLOAT_MAX_NEGATIVE..FLOAT_MAX_POSITIVE }) {
|
|
||||||
addError(ExpressionError("float array elements must all be floats in the acceptable range", literalValue.position))
|
|
||||||
return super.process(literalValue)
|
|
||||||
}
|
|
||||||
val array = doubleArray.filterNotNull().toDoubleArray()
|
|
||||||
val heapId = heap.add(arrayDt, array)
|
|
||||||
val newValue = LiteralValue(DataType.ARRAY_F, heapId=heapId, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addError(ExpressionError("array/matrix literal can contain only constant values", literalValue.position))
|
|
||||||
}
|
|
||||||
|
|
||||||
val newValue = LiteralValue(arrayDt, arrayvalue = newArray, position = literalValue.position)
|
|
||||||
return super.process(newValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.process(literalValue)
|
return super.process(literalValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun moveArrayToHeap(arraylit: LiteralValue): LiteralValue {
|
||||||
|
val array: Array<IExpression> = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray()
|
||||||
|
val allElementsAreConstant = array.fold(true) { c, expr-> c and (expr is LiteralValue)}
|
||||||
|
if(!allElementsAreConstant) {
|
||||||
|
addError(ExpressionError("array/matrix literal can contain only constant values", arraylit.position))
|
||||||
|
return arraylit
|
||||||
|
} else {
|
||||||
|
val valuesInArray = array.map { it.constValue(namespace, heap)!!.asNumericValue!! }
|
||||||
|
val integerArray = valuesInArray.map{it.toInt()}.toIntArray()
|
||||||
|
val doubleArray = valuesInArray.map{it.toDouble()}.toDoubleArray()
|
||||||
|
val typesInArray: Set<DataType> = array.mapNotNull { it.resultingDatatype(namespace, heap) }.toSet()
|
||||||
|
val arrayDt =
|
||||||
|
if(DataType.FLOAT in typesInArray)
|
||||||
|
DataType.ARRAY_F
|
||||||
|
else if(DataType.WORD in typesInArray) {
|
||||||
|
if(DataType.UWORD in typesInArray)
|
||||||
|
DataType.ARRAY_F
|
||||||
|
else
|
||||||
|
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) {
|
||||||
|
DataType.ARRAY_UB,
|
||||||
|
DataType.ARRAY_B,
|
||||||
|
DataType.ARRAY_UW,
|
||||||
|
DataType.ARRAY_W,
|
||||||
|
DataType.MATRIX_UB,
|
||||||
|
DataType.MATRIX_B -> heap.add(arrayDt, integerArray)
|
||||||
|
DataType.ARRAY_F -> heap.add(arrayDt, doubleArray)
|
||||||
|
else -> throw CompilerException("invalid array type")
|
||||||
|
}
|
||||||
|
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
|
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
|
||||||
if(arrayIndexedExpression.array.y!=null) {
|
if(arrayIndexedExpression.array.y!=null) {
|
||||||
if(arrayIndexedExpression.array.size()!=null) {
|
if(arrayIndexedExpression.array.size()!=null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user