mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
fix array initialization
This commit is contained in:
parent
1fe5c943fd
commit
cc54e3ec99
@ -8,32 +8,32 @@
|
||||
|
||||
sub start() {
|
||||
|
||||
byte[3] barr1 = [-2,-1,2]
|
||||
byte[3] barr2 = [-22,-1, 3]
|
||||
ubyte[3] barr3 = [-2,-1,2] ; @ todo error
|
||||
ubyte[3] barr4 = [1,2,33]
|
||||
ubyte[3] barr5 = [1,2,-33] ; @todo error
|
||||
word[3] warr1 = [-2,-1,2]
|
||||
;word[3] warr2 = [-2,-1,2, 3453] ; @todo ok
|
||||
uword[3] warr3 = [-2,-1,2]
|
||||
uword[3] warr4 = [1,2,33.w]
|
||||
uword[3] warr5 = [1,2,-33] ; @todo error
|
||||
byte[4] barr1 = -2
|
||||
byte[4] barr2 = 33
|
||||
ubyte[4] barr4 = 2
|
||||
ubyte[4] barr5 = 44
|
||||
word[4] warr1 = 4444
|
||||
word[4] warr2 = -5555
|
||||
word[4] warr2b = -5522
|
||||
float[4] farr1
|
||||
float[4] farr2 = 23
|
||||
float[4] farr3 = 55.636346
|
||||
|
||||
byte b1 = 50 * 2
|
||||
byte b2 = -50 * 2
|
||||
ubyte ub1 = 50 * 2
|
||||
word w1 = 999 * 2
|
||||
word w2 = -999 * 2
|
||||
uword uw1 = 999 * 2
|
||||
float f1 = 999*2
|
||||
float f2 = -999*2
|
||||
; byte b1 = 50 * 2
|
||||
; byte b2 = -50 * 2
|
||||
; ubyte ub1 = 50 * 2
|
||||
; word w1 = 999 * 2
|
||||
; word w2 = -999 * 2
|
||||
; uword uw1 = 999 * 2
|
||||
; float f1 = 999*2
|
||||
; float f2 = -999*2
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
sub toscreenx(x: float, z: float) -> word {
|
||||
return floor(x/(4.2+z) * flt(height)) + width // 2
|
||||
}
|
||||
; sub toscreenx(x: float, z: float) -> word {
|
||||
; 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)
|
||||
}
|
||||
|
||||
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) {
|
||||
x = x.process(processor)
|
||||
y = y?.process(processor)
|
||||
@ -1042,7 +1049,12 @@ class LiteralValue(val type: DataType,
|
||||
val fh = floatvalue?.hashCode() ?: 0x00103456
|
||||
val sh = strvalue?.hashCode() ?: 0x00014567
|
||||
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 {
|
||||
@ -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.arrayliteral()!=null -> {
|
||||
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.
|
||||
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
|
||||
}
|
||||
|
@ -415,9 +415,15 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
when {
|
||||
decl.value is RangeExpr -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as RangeExpr)
|
||||
decl.value is LiteralValue -> checkValueTypeAndRange(decl.datatype,
|
||||
decl.arrayspec ?: ArraySpec(LiteralValue.optimalInteger(-2, decl.position), null, decl.position),
|
||||
decl.value as LiteralValue, heap)
|
||||
decl.value is LiteralValue -> {
|
||||
val arraySpec = decl.arrayspec ?: (
|
||||
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 -> {
|
||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!::class.simpleName}")
|
||||
return super.process(decl)
|
||||
@ -515,9 +521,12 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(!compilerOptions.floats && literalValue.type==DataType.FLOAT) {
|
||||
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
|
||||
}
|
||||
checkValueTypeAndRange(literalValue.type,
|
||||
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), null, literalValue.position),
|
||||
literalValue, heap)
|
||||
val arrayspec =
|
||||
if(literalValue.isArray)
|
||||
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)
|
||||
when(lv.type) {
|
||||
@ -798,7 +807,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
// 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 arraySpecSize = arrayspec.size()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
@ -808,66 +817,34 @@ class AstChecker(private val namespace: INameScope,
|
||||
val expectedSize = constX.asIntegerValue
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
}
|
||||
} 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 true
|
||||
}
|
||||
}
|
||||
return err("invalid array initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
// 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 arraySpecSize = arrayspec.size()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
// arrayspec is not always known when checking
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
if(constX?.asIntegerValue==null)
|
||||
return err("array size specifier must be constant integer value")
|
||||
val expectedSize = constX.asIntegerValue
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
}
|
||||
} 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 true
|
||||
}
|
||||
}
|
||||
return err("invalid array initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
// 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) {
|
||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
|
||||
if(value.type==targetDt) {
|
||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).doubleArray!!.size
|
||||
val arraySpecSize = arrayspec.size()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
// arrayspec is not always known when checking
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
if(constX?.asIntegerValue==null)
|
||||
return err("array size specifier must be constant integer value")
|
||||
@ -875,17 +852,20 @@ class AstChecker(private val namespace: INameScope,
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
}
|
||||
} else {
|
||||
val number = value.asNumericValue?.toDouble()
|
||||
if(number==null)
|
||||
return err("expected numerical value")
|
||||
else if (number < FLOAT_MAX_NEGATIVE || number > FLOAT_MAX_POSITIVE)
|
||||
return err("value '$number' out of range for mfplt5 floating point")
|
||||
// check if the floating point values are all within range
|
||||
val doubles = if(value.arrayvalue!=null)
|
||||
value.arrayvalue.map {it.constValue(namespace, heap)?.asNumericValue!!.toDouble()}.toDoubleArray()
|
||||
else
|
||||
heap.get(value.heapId!!).doubleArray!!
|
||||
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 -> {
|
||||
// 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()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
@ -897,19 +877,8 @@ class AstChecker(private val namespace: INameScope,
|
||||
if (matrix.size != expectedSize)
|
||||
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
|
||||
|
@ -1,6 +1,7 @@
|
||||
package prog8.optimizing
|
||||
|
||||
import prog8.ast.*
|
||||
import prog8.compiler.CompilerException
|
||||
import prog8.compiler.HeapValues
|
||||
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
|
||||
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 -> {
|
||||
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()
|
||||
if(litval!=null && litval.isArray) {
|
||||
// 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))
|
||||
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) {
|
||||
// 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
|
||||
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 heapId = heap.add(decl.datatype, fillArray)
|
||||
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) {
|
||||
// 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 fillArray = DoubleArray(size) { _ -> fillvalue }
|
||||
val heapId = heap.add(decl.datatype, fillArray)
|
||||
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
||||
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
|
||||
errors.add(ExpressionError("float value overflow", 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
|
||||
@ -437,100 +469,63 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
return super.process(newValue)
|
||||
}
|
||||
} else if(literalValue.arrayvalue!=null) {
|
||||
val newArray = literalValue.arrayvalue.map { it.process(this) }.toTypedArray()
|
||||
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 moveArrayToHeap(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 {
|
||||
if(arrayIndexedExpression.array.y!=null) {
|
||||
if(arrayIndexedExpression.array.size()!=null) {
|
||||
|
Loading…
Reference in New Issue
Block a user