diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 7bd3bb98f..f82675a9e 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -5,6 +5,7 @@ import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.tree.TerminalNode import prog8.compiler.RuntimeValue import prog8.compiler.HeapValues +import prog8.compiler.IntegerOrAddressOf import prog8.compiler.target.c64.Petscii import prog8.functions.BuiltinFunctions import prog8.functions.NotConstArgumentException @@ -1298,7 +1299,7 @@ open class LiteralValue(val type: DataType, val floatvalue: Double? = null, val strvalue: String? = null, val arrayvalue: Array? = null, - var heapId: Int? =null, + initHeapId: Int? =null, override val position: Position) : IExpression { override lateinit var parent: Node @@ -1307,6 +1308,8 @@ open class LiteralValue(val type: DataType, val isString = type in StringDatatypes val isNumeric = type in NumericDatatypes val isArray = type in ArrayDatatypes + var heapId = initHeapId + private set companion object { fun fromBoolean(bool: Boolean, position: Position) = @@ -1522,6 +1525,35 @@ open class LiteralValue(val type: DataType, } return null // invalid type conversion from $this to $targettype } + + fun addToHeap(heap: HeapValues) { + if(heapId==null) { + if (strvalue != null) { + heapId = heap.addString(type, strvalue) + } + else if (arrayvalue!=null) { + if(arrayvalue.any {it is AddressOf}) { + val intArrayWithAddressOfs = arrayvalue.map { + when (it) { + is AddressOf -> IntegerOrAddressOf(null, it) + is LiteralValue -> IntegerOrAddressOf(it.asIntegerValue, null) + else -> throw FatalAstException("invalid datatype in array") + } + } + heapId = heap.addIntegerArray(type, intArrayWithAddressOfs.toTypedArray()) + } else { + val valuesInArray = arrayvalue.map { (it as LiteralValue).asNumericValue!! } + if(type==DataType.ARRAY_F) { + val doubleArray = valuesInArray.map { it.toDouble() }.toDoubleArray() + heapId = heap.addDoublesArray(doubleArray) + } else { + val integerArray = valuesInArray.map { it.toInt() } + heapId = heap.addIntegerArray(type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray()) + } + } + } + } + } } diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 271fb2f56..77d0d6eef 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -535,7 +535,7 @@ private class AstChecker(private val program: Program, decl.value = litVal } decl.type==VarDeclType.VAR -> { - val litVal = LiteralValue(decl.datatype, heapId = heapStringSentinel, position=decl.position) // point to the sentinel heap value instead + val litVal = LiteralValue(decl.datatype, initHeapId = heapStringSentinel, position=decl.position) // point to the sentinel heap value instead litVal.parent=decl decl.value = litVal } diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 3b9ef88b0..e19192319 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -113,7 +113,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor { else -> {} } val heapId = program.heap.addIntegerArray(decl.datatype, Array(size) { IntegerOrAddressOf(fillvalue, null) }) - decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position) + decl.value = LiteralValue(decl.datatype, initHeapId = heapId, position = litval?.position ?: decl.position) optimizationsDone++ return decl } @@ -127,7 +127,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor { errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position)) else { val heapId = program.heap.addDoublesArray(DoubleArray(size) { fillvalue }) - decl.value = LiteralValue(DataType.ARRAY_F, heapId = heapId, position = litval?.position ?: decl.position) + decl.value = LiteralValue(DataType.ARRAY_F, initHeapId = heapId, position = litval?.position ?: decl.position) optimizationsDone++ return decl } @@ -154,7 +154,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor { DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> { if(array.array!=null) { program.heap.update(heapId, HeapValues.HeapValue(decl.datatype, null, array.array, null)) - decl.value = LiteralValue(decl.datatype, heapId=heapId, position = litval.position) + decl.value = LiteralValue(decl.datatype, initHeapId=heapId, position = litval.position) } } DataType.ARRAY_F -> { @@ -162,7 +162,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor { // convert a non-float array to floats val doubleArray = array.array.map { it.integer!!.toDouble() }.toDoubleArray() program.heap.update(heapId, HeapValues.HeapValue(DataType.ARRAY_F, null, null, doubleArray)) - decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval.position) + decl.value = LiteralValue(decl.datatype, initHeapId = heapId, position = litval.position) } } else -> throw FatalAstException("invalid array vardecl type ${decl.datatype}") @@ -598,12 +598,12 @@ class ConstantFolding(private val program: Program) : IAstProcessor { if(litval.strvalue!!.length !in 1..255) addError(ExpressionError("string literal length must be between 1 and 255", litval.position)) else { - litval.heapId = program.heap.addString(litval.type, litval.strvalue) // TODO: we don't know the actual string type yet, STR != STR_S etc... + litval.addToHeap(program.heap) // TODO: we don't know the actual string type yet, STR != STR_S etc... } } else if(litval.arrayvalue!=null) { // first, adjust the array datatype val litval2 = adjustArrayValDatatype(litval) - moveArrayToHeap(litval2) + litval2.addToHeap(program.heap) return litval2 } return litval @@ -649,37 +649,6 @@ class ConstantFolding(private val program: Program) : IAstProcessor { return litval } - private fun moveArrayToHeap(arraylit: LiteralValue) { - val array: Array = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray() - if(array.any {it is AddressOf}) { - val intArrayWithAddressOfs = array.map { - when (it) { - is AddressOf -> IntegerOrAddressOf(null, it) - is LiteralValue -> IntegerOrAddressOf(it.asIntegerValue, null) - else -> throw CompilerException("invalid datatype in array") - } - } - arraylit.heapId = program.heap.addIntegerArray(arraylit.type, intArrayWithAddressOfs.toTypedArray()) - } else { - // array is only constant numerical values - val valuesInArray = array.map { it.constValue(program)!!.asNumericValue!! } - arraylit.heapId = when(arraylit.type) { - DataType.ARRAY_UB, - DataType.ARRAY_B, - DataType.ARRAY_UW, - 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") - } - } - } - override fun process(assignment: Assignment): IStatement { super.process(assignment) val lv = assignment.value as? LiteralValue