improved array literal datatype handling, fixed some datatype compiler errors related to this

This commit is contained in:
Irmen de Jong 2020-03-12 01:10:19 +01:00
parent fbecedaf41
commit 5f1ec80ae0
15 changed files with 114 additions and 229 deletions

View File

@ -476,7 +476,7 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
val array = litval.arrayliteral().toAst() val array = litval.arrayliteral().toAst()
// the actual type of the arraysize can not yet be determined here (missing namespace & heap) // the actual type of the arraysize can not yet be determined here (missing namespace & heap)
// the ConstantFold takes care of that and converts the type if needed. // the ConstantFold takes care of that and converts the type if needed.
ArrayLiteralValue(DataType.ARRAY_UB, array, position = litval.toPosition()) ArrayLiteralValue(InferredTypes.InferredType.unknown(), array, position = litval.toPosition())
} }
litval.structliteral()!=null -> { litval.structliteral()!=null -> {
val values = litval.structliteral().expression().map { it.toAst() } val values = litval.structliteral().expression().map { it.toAst() }

View File

@ -126,6 +126,13 @@ val ArrayElementTypes = mapOf(
DataType.ARRAY_W to DataType.WORD, DataType.ARRAY_W to DataType.WORD,
DataType.ARRAY_UW to DataType.UWORD, DataType.ARRAY_UW to DataType.UWORD,
DataType.ARRAY_F to DataType.FLOAT) DataType.ARRAY_F to DataType.FLOAT)
val ElementArrayTypes = mapOf(
DataType.BYTE to DataType.ARRAY_B,
DataType.UBYTE to DataType.ARRAY_UB,
DataType.WORD to DataType.ARRAY_W,
DataType.UWORD to DataType.ARRAY_UW,
DataType.FLOAT to DataType.ARRAY_F
)
// find the parent node of a specific type or interface // find the parent node of a specific type or interface
// (useful to figure out in what namespace/block something is defined, etc) // (useful to figure out in what namespace/block something is defined, etc)

View File

@ -5,10 +5,7 @@ import prog8.ast.antlr.escape
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.processing.IAstModifyingVisitor import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor import prog8.ast.processing.IAstVisitor
import prog8.ast.statements.ArrayIndex import prog8.ast.statements.*
import prog8.ast.statements.BuiltinFunctionStatementPlaceholder
import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl
import prog8.compiler.target.CompilationTarget import prog8.compiler.target.CompilationTarget
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
import prog8.functions.NotConstArgumentException import prog8.functions.NotConstArgumentException
@ -454,7 +451,7 @@ class StringLiteralValue(val value: String,
} }
} }
class ArrayLiteralValue(val type: DataType, // only array types class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred because not all array literals hava a known type yet
val value: Array<Expression>, val value: Array<Expression>,
override val position: Position) : Expression() { override val position: Position) : Expression() {
override lateinit var parent: Node override lateinit var parent: Node
@ -470,7 +467,8 @@ class ArrayLiteralValue(val type: DataType, // only array types
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this) override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun toString(): String = "$value" override fun toString(): String = "$value"
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(type) override fun inferType(program: Program): InferredTypes.InferredType = if(type.isUnknown) type else guessDatatype(program)
operator fun compareTo(other: ArrayLiteralValue): Int = throw ExpressionError("cannot order compare arrays", position) operator fun compareTo(other: ArrayLiteralValue): Int = throw ExpressionError("cannot order compare arrays", position)
override fun hashCode(): Int = Objects.hash(value, type) override fun hashCode(): Int = Objects.hash(value, type)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@ -479,8 +477,36 @@ class ArrayLiteralValue(val type: DataType, // only array types
return type==other.type && value.contentEquals(other.value) return type==other.type && value.contentEquals(other.value)
} }
fun guessDatatype(program: Program): InferredTypes.InferredType {
// Educated guess of the desired array literal's datatype.
// If it's inside a for loop, assume the data type of the loop variable is what we want.
val forloop = parent as? ForLoop
if(forloop != null) {
val loopvarDt = forloop.loopVarDt(program)
if(loopvarDt.isKnown) {
return if(loopvarDt.typeOrElse(DataType.STRUCT) !in ElementArrayTypes)
InferredTypes.InferredType.unknown()
else
InferredTypes.InferredType.known(ElementArrayTypes.getValue(loopvarDt.typeOrElse(DataType.STRUCT)))
}
}
// otherwise, select the "biggegst" datatype based on the elements in the array.
val datatypesInArray = value.map { it.inferType(program) }
require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) }
return when {
DataType.FLOAT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_F)
DataType.WORD in dts -> InferredTypes.InferredType.known(DataType.ARRAY_W)
DataType.UWORD in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
DataType.BYTE in dts -> InferredTypes.InferredType.known(DataType.ARRAY_B)
DataType.UBYTE in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UB)
else -> InferredTypes.InferredType.unknown()
}
}
fun cast(targettype: DataType): ArrayLiteralValue? { fun cast(targettype: DataType): ArrayLiteralValue? {
if(type==targettype) if(type.istype(targettype))
return this return this
if(targettype in ArrayDatatypes) { if(targettype in ArrayDatatypes) {
val elementType = ArrayElementTypes.getValue(targettype) val elementType = ArrayElementTypes.getValue(targettype)
@ -499,7 +525,7 @@ class ArrayLiteralValue(val type: DataType, // only array types
} }
} }
}.toTypedArray() }.toTypedArray()
return ArrayLiteralValue(targettype, castArray, position = position) return ArrayLiteralValue(InferredTypes.InferredType.known(targettype), castArray, position = position)
} }
return null // invalid type conversion from $this to $targettype return null // invalid type conversion from $this to $targettype
} }

View File

@ -686,11 +686,13 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(array: ArrayLiteralValue) { override fun visit(array: ArrayLiteralValue) {
if(!compilerOptions.floats && array.type in setOf(DataType.FLOAT, DataType.ARRAY_F)) { if(array.type.isKnown) {
checkResult.add(SyntaxError("floating point used, but that is not enabled via options", array.position)) if (!compilerOptions.floats && array.type.typeOrElse(DataType.STRUCT) in setOf(DataType.FLOAT, DataType.ARRAY_F)) {
checkResult.add(SyntaxError("floating point used, but that is not enabled via options", array.position))
}
val arrayspec = ArrayIndex.forArray(array)
checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), null, arrayspec, array)
} }
val arrayspec = ArrayIndex.forArray(array)
checkValueTypeAndRangeArray(array.type, null, arrayspec, array)
super.visit(array) super.visit(array)
} }
@ -1064,11 +1066,15 @@ internal class AstChecker(private val program: Program,
checkResult.add(ExpressionError(msg, value.position)) checkResult.add(ExpressionError(msg, value.position))
return false return false
} }
if(value.type.isUnknown)
return err("attempt to check values of array with as yet unknown datatype")
when (targetDt) { when (targetDt) {
DataType.STR -> return err("string value expected") DataType.STR -> return err("string value expected")
DataType.ARRAY_UB, DataType.ARRAY_B -> { DataType.ARRAY_UB, DataType.ARRAY_B -> {
// value may be either a single byte, or a byte arraysize (of all constant values), or a range // value may be either a single byte, or a byte arraysize (of all constant values), or a range
if(value.type==targetDt) { if(value.type.istype(targetDt)) {
if(!checkArrayValues(value, targetDt)) if(!checkArrayValues(value, targetDt))
return false return false
val arraySpecSize = arrayspec.size() val arraySpecSize = arrayspec.size()
@ -1090,7 +1096,7 @@ internal class AstChecker(private val program: Program,
} }
DataType.ARRAY_UW, DataType.ARRAY_W -> { DataType.ARRAY_UW, DataType.ARRAY_W -> {
// value may be either a single word, or a word arraysize, or a range // value may be either a single word, or a word arraysize, or a range
if(value.type==targetDt) { if(value.type.istype(targetDt)) {
if(!checkArrayValues(value, targetDt)) if(!checkArrayValues(value, targetDt))
return false return false
val arraySpecSize = arrayspec.size() val arraySpecSize = arrayspec.size()
@ -1112,7 +1118,7 @@ internal class AstChecker(private val program: Program,
} }
DataType.ARRAY_F -> { DataType.ARRAY_F -> {
// value may be either a single float, or a float arraysize // value may be either a single float, or a float arraysize
if(value.type==targetDt) { if(value.type.istype(targetDt)) {
if(!checkArrayValues(value, targetDt)) if(!checkArrayValues(value, targetDt))
return false return false
val arraySize = value.value.size val arraySize = value.value.size
@ -1138,7 +1144,7 @@ internal class AstChecker(private val program: Program,
return err("invalid float array initialization value ${value.type}, expected $targetDt") return err("invalid float array initialization value ${value.type}, expected $targetDt")
} }
DataType.STRUCT -> { DataType.STRUCT -> {
if(value.type in ArrayDatatypes) { if(value.type.typeOrElse(DataType.STRUCT) in ArrayDatatypes) {
if(value.value.size != struct!!.numberOfElements) if(value.value.size != struct!!.numberOfElements)
return err("number of values is not the same as the number of members in the struct") return err("number of values is not the same as the number of members in the struct")
for(elt in value.value.zip(struct.statements)) { for(elt in value.value.zip(struct.statements)) {

View File

@ -225,22 +225,34 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
return super.visit(returnStmt) return super.visit(returnStmt)
} }
override fun visit(arrayLiteral: ArrayLiteralValue): Expression { override fun visit(arrayLiteral: ArrayLiteralValue): Expression {
val array = super.visit(arrayLiteral) val array = super.visit(arrayLiteral)
if(array is ArrayLiteralValue) { if(array is ArrayLiteralValue) {
val vardecl = array.parent as? VarDecl val vardecl = array.parent as? VarDecl
return if(vardecl!=null) // adjust the datatype of the array (to an educated guess)
fixupArrayEltDatatypesFromVardecl(array, vardecl) if(vardecl!=null) {
val arrayDt = array.type
if(!arrayDt.istype(vardecl.datatype)) {
val cast = array.cast(vardecl.datatype)
if (cast != null) {
vardecl.value = cast
cast.linkParents(vardecl)
return cast
}
}
return array
}
else { else {
// fix the datatype of the array (also on the heap) to the 'biggest' datatype in the array val arrayDt = array.guessDatatype(program)
// (we don't know the desired datatype here exactly so we guess) if(arrayDt.isKnown) {
val datatype = determineArrayDt(array.value) // this array literal is part of an expression, turn it into an identifier reference
val litval2 = array.cast(datatype) val litval2 = array.cast(arrayDt.typeOrElse(DataType.STRUCT))
if(litval2!=null) { return if (litval2 != null) {
litval2.parent = array.parent litval2.parent = array.parent
// finally, replace the literal array by a identifier reference. makeIdentifierFromRefLv(litval2)
makeIdentifierFromRefLv(litval2) } else array
} else array }
} }
} }
return array return array
@ -261,20 +273,6 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
return string return string
} }
private fun determineArrayDt(array: Array<Expression>): DataType {
val datatypesInArray = array.map { it.inferType(program) }
require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) }
return when {
DataType.FLOAT in dts -> DataType.ARRAY_F
DataType.WORD in dts -> DataType.ARRAY_W
DataType.UWORD in dts -> DataType.ARRAY_UW
DataType.BYTE in dts -> DataType.ARRAY_B
DataType.UBYTE in dts -> DataType.ARRAY_UB
else -> throw IllegalArgumentException("can't determine type of array")
}
}
private fun makeIdentifierFromRefLv(array: ArrayLiteralValue): IdentifierReference { private fun makeIdentifierFromRefLv(array: ArrayLiteralValue): IdentifierReference {
// a referencetype literal value that's not declared as a variable // a referencetype literal value that's not declared as a variable
// we need to introduce an auto-generated variable for this to be able to refer to the value // we need to introduce an auto-generated variable for this to be able to refer to the value
@ -350,46 +348,3 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
} }
} }
internal fun fixupArrayEltDatatypes(array: ArrayLiteralValue, program: Program): ArrayLiteralValue {
val dts = array.value.map {it.inferType(program).typeOrElse(DataType.STRUCT)}.toSet()
if(dts.any { it !in NumericDatatypes }) {
return array
}
val dt = when {
DataType.FLOAT in dts -> DataType.ARRAY_F
DataType.WORD in dts -> DataType.ARRAY_W
DataType.UWORD in dts -> DataType.ARRAY_UW
DataType.BYTE in dts -> DataType.ARRAY_B
else -> DataType.ARRAY_UB
}
if(dt==array.type)
return array
// convert values and array type
val elementType = ArrayElementTypes.getValue(dt)
val allNumerics = array.value.all { it is NumericLiteralValue }
if(allNumerics) {
val values = array.value.map { (it as NumericLiteralValue).cast(elementType) as Expression }.toTypedArray()
val array2 = ArrayLiteralValue(dt, values, array.position)
array2.linkParents(array.parent)
return array2
}
return array
}
internal fun fixupArrayEltDatatypesFromVardecl(array: ArrayLiteralValue, vardecl: VarDecl): ArrayLiteralValue {
val arrayDt = array.type
if(arrayDt!=vardecl.datatype) {
// fix the datatype of the array (also on the heap) to match the vardecl
val cast = array.cast(vardecl.datatype)
if (cast != null) {
vardecl.value = cast
cast.linkParents(vardecl)
return cast
}
// can't be casted yet, attempt again later
}
return array
}

View File

@ -42,7 +42,7 @@ internal class VarInitValueAndAddressOfCreator(private val program: Program): IA
if(decl.isArray && decl.value==null) { if(decl.isArray && decl.value==null) {
// array datatype without initialization value, add list of zeros // array datatype without initialization value, add list of zeros
val arraysize = decl.arraysize!!.size()!! val arraysize = decl.arraysize!!.size()!!
val array = ArrayLiteralValue(decl.datatype, val array = ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype),
Array(arraysize) { NumericLiteralValue.optimalInteger(0, decl.position) }, Array(arraysize) { NumericLiteralValue.optimalInteger(0, decl.position) },
decl.position) decl.position)
decl.value = array decl.value = array

View File

@ -199,7 +199,7 @@ class VarDecl(val type: VarDeclType,
fun createAuto(array: ArrayLiteralValue): VarDecl { fun createAuto(array: ArrayLiteralValue): VarDecl {
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
val declaredType = ArrayElementTypes.getValue(array.type) val declaredType = ArrayElementTypes.getValue(array.type.typeOrElse(DataType.STRUCT))
val arraysize = ArrayIndex.forArray(array) val arraysize = ArrayIndex.forArray(array)
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, null, array, return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, null, array,
isArray = true, autogeneratedDontRemove = true, position = array.position) isArray = true, autogeneratedDontRemove = true, position = array.position)
@ -663,6 +663,12 @@ class ForLoop(val loopRegister: Register?,
override fun toString(): String { override fun toString(): String {
return "ForLoop(loopVar: $loopVar, loopReg: $loopRegister, iterable: $iterable, pos=$position)" return "ForLoop(loopVar: $loopVar, loopReg: $loopRegister, iterable: $iterable, pos=$position)"
} }
fun loopVarDt(program: Program): InferredTypes.InferredType {
val lv = loopVar
return if(loopRegister!=null) InferredTypes.InferredType.known(DataType.UBYTE)
else lv?.inferType(program) ?: InferredTypes.InferredType.unknown()
}
} }
class WhileLoop(var condition: Expression, class WhileLoop(var condition: Expression,

View File

@ -5,8 +5,6 @@ import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.processing.IAstModifyingVisitor import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.fixupArrayEltDatatypesFromVardecl
import prog8.ast.processing.fixupArrayEltDatatypes
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.target.CompilationTarget import prog8.compiler.target.CompilationTarget
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
@ -76,11 +74,11 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
if(constRange!=null) { if(constRange!=null) {
val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE) val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE)
if(eltType in ByteDatatypes) { if(eltType in ByteDatatypes) {
decl.value = ArrayLiteralValue(decl.datatype, decl.value = ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype),
constRange.map { NumericLiteralValue(eltType, it.toShort(), decl.value!!.position) }.toTypedArray(), constRange.map { NumericLiteralValue(eltType, it.toShort(), decl.value!!.position) }.toTypedArray(),
position = decl.value!!.position) position = decl.value!!.position)
} else { } else {
decl.value = ArrayLiteralValue(decl.datatype, decl.value = ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype),
constRange.map { NumericLiteralValue(eltType, it, decl.value!!.position) }.toTypedArray(), constRange.map { NumericLiteralValue(eltType, it, decl.value!!.position) }.toTypedArray(),
position = decl.value!!.position) position = decl.value!!.position)
} }
@ -116,7 +114,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
} }
// create the array itself, filled with the fillvalue. // create the array itself, filled with the fillvalue.
val array = Array(size) {fillvalue}.map { NumericLiteralValue.optimalInteger(it, numericLv.position) as Expression}.toTypedArray() val array = Array(size) {fillvalue}.map { NumericLiteralValue.optimalInteger(it, numericLv.position) as Expression}.toTypedArray()
val refValue = ArrayLiteralValue(decl.datatype, array, position = numericLv.position) val refValue = ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype), array, position = numericLv.position)
decl.value = refValue decl.value = refValue
refValue.parent=decl refValue.parent=decl
optimizationsDone++ optimizationsDone++
@ -137,7 +135,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
else { else {
// create the array itself, filled with the fillvalue. // create the array itself, filled with the fillvalue.
val array = Array(size) {fillvalue}.map { NumericLiteralValue(DataType.FLOAT, it, litval.position) as Expression}.toTypedArray() val array = Array(size) {fillvalue}.map { NumericLiteralValue(DataType.FLOAT, it, litval.position) as Expression}.toTypedArray()
val refValue = ArrayLiteralValue(DataType.ARRAY_F, array, position = litval.position) val refValue = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_F), array, position = litval.position)
decl.value = refValue decl.value = refValue
refValue.parent=decl refValue.parent=decl
optimizationsDone++ optimizationsDone++
@ -629,14 +627,18 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
} }
override fun visit(arrayLiteral: ArrayLiteralValue): Expression { override fun visit(arrayLiteral: ArrayLiteralValue): Expression {
// because constant folding can result in arrays that are now suddenly capable
// of telling the type of all their elements (for instance, when they contained -2 which
// was a prefix expression earlier), we recalculate the array's datatype.
val array = super.visit(arrayLiteral) val array = super.visit(arrayLiteral)
if(array is ArrayLiteralValue) { if(array is ArrayLiteralValue) {
val vardecl = array.parent as? VarDecl if(array.type.isKnown)
return if (vardecl!=null) { return array
fixupArrayEltDatatypesFromVardecl(array, vardecl) val arrayDt = array.guessDatatype(program)
} else { if(arrayDt.isKnown) {
// it's not an array associated with a vardecl, attempt to guess the data type from the array values val newArray = arrayLiteral.cast(arrayDt.typeOrElse(DataType.STRUCT))
fixupArrayEltDatatypes(array, program) if(newArray!=null)
return newArray
} }
} }
return array return array

View File

@ -22,7 +22,7 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
override fun visit(assignment: Assignment): Statement { override fun visit(assignment: Assignment): Statement {
if (assignment.aug_op != null) if (assignment.aug_op != null)
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer") throw AstException("augmented assignments should have been converted to normal assignments before this optimizer: $assignment")
return super.visit(assignment) return super.visit(assignment)
} }

View File

@ -424,7 +424,7 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
override fun visit(assignment: Assignment): Statement { override fun visit(assignment: Assignment): Statement {
if(assignment.aug_op!=null) if(assignment.aug_op!=null)
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer") throw AstException("augmented assignments should have been converted to normal assignments before this optimizer: $assignment")
if(assignment.target isSameAs assignment.value) { if(assignment.target isSameAs assignment.value) {
if(assignment.target.isNotMemory(program.namespace)) { if(assignment.target.isNotMemory(program.namespace)) {

View File

@ -603,9 +603,9 @@ open class RuntimeValueArray(type: DataType, val array: Array<Number>, val heapI
companion object { companion object {
fun fromLv(array: ArrayLiteralValue): RuntimeValueArray { fun fromLv(array: ArrayLiteralValue): RuntimeValueArray {
return if (array.type == DataType.ARRAY_F) { return if (array.type.istype(DataType.ARRAY_F)) {
val doubleArray = array.value.map { (it as NumericLiteralValue).number }.toTypedArray() val doubleArray = array.value.map { (it as NumericLiteralValue).number }.toTypedArray()
RuntimeValueArray(array.type, doubleArray, array.heapId) RuntimeValueArray(DataType.ARRAY_F, doubleArray, array.heapId)
} else { } else {
val resultArray = mutableListOf<Number>() val resultArray = mutableListOf<Number>()
for (elt in array.value.withIndex()) { for (elt in array.value.withIndex()) {
@ -615,7 +615,7 @@ open class RuntimeValueArray(type: DataType, val array: Array<Number>, val heapI
resultArray.add((elt.hashCode())) // ...poor man's implementation of ADDRESSOF(array), it probably won't work very well resultArray.add((elt.hashCode())) // ...poor man's implementation of ADDRESSOF(array), it probably won't work very well
} }
} }
RuntimeValueArray(array.type, resultArray.toTypedArray(), array.heapId) RuntimeValueArray(array.type.typeOrElse(DataType.STRUCT), resultArray.toTypedArray(), array.heapId)
} }
} }
} }

View File

@ -5,6 +5,7 @@ import org.junit.jupiter.api.TestInstance
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.expressions.ArrayLiteralValue import prog8.ast.expressions.ArrayLiteralValue
import prog8.ast.expressions.InferredTypes
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.StringLiteralValue import prog8.ast.expressions.StringLiteralValue
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -96,9 +97,9 @@ class TestParserNumericLiteralValue {
val lvTwoR = NumericLiteralValue(DataType.UBYTE, 2, dummyPos) val lvTwoR = NumericLiteralValue(DataType.UBYTE, 2, dummyPos)
val lvThreeR = NumericLiteralValue(DataType.UBYTE, 3, dummyPos) val lvThreeR = NumericLiteralValue(DataType.UBYTE, 3, dummyPos)
val lvFour= NumericLiteralValue(DataType.UBYTE, 4, dummyPos) val lvFour= NumericLiteralValue(DataType.UBYTE, 4, dummyPos)
val lv1 = ArrayLiteralValue(DataType.ARRAY_UB, arrayOf(lvOne, lvTwo, lvThree), dummyPos) val lv1 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOne, lvTwo, lvThree), dummyPos)
val lv2 = ArrayLiteralValue(DataType.ARRAY_UB, arrayOf(lvOneR, lvTwoR, lvThreeR), dummyPos) val lv2 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvThreeR), dummyPos)
val lv3 = ArrayLiteralValue(DataType.ARRAY_UB, arrayOf(lvOneR, lvTwoR, lvFour), dummyPos) val lv3 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvFour), dummyPos)
assertEquals(lv1, lv2) assertEquals(lv1, lv2)
assertNotEquals(lv1, lv3) assertNotEquals(lv1, lv3)
} }

View File

@ -5,125 +5,7 @@ main {
sub start() { sub start() {
ubyte[] uba = [1,2,3] byte[] barr = [22,-33,-44,55,66]
byte[] bba = [1,2,3]
uword[] uwa = [1111,2222,3333]
word[] wwa = [1111,2222,3333]
ubyte ub
byte bb
uword uw
word ww
for ub in uba {
c64scr.print_ub(ub)
c64scr.print(",")
}
c64scr.print("\n")
for bb in bba {
c64scr.print_b(bb)
c64scr.print(",")
}
c64scr.print("\n")
for uw in uwa {
c64scr.print_uw(uw)
c64scr.print(",")
}
c64scr.print("\n")
for ww in wwa {
c64scr.print_w(ww)
c64scr.print(",")
}
c64scr.print("\n")
for ub in [1,2,3] {
c64scr.print_ub(ub)
c64scr.print(",")
}
; c64scr.print("\n")
; for bb in [1,2,3] { ; TODO fix array literal conversion error
; c64scr.print_b(bb)
; c64scr.print(",")
; }
c64scr.print("\n")
for uw in [1111,2222,3333] {
c64scr.print_uw(uw)
c64scr.print(",")
}
; c64scr.print("\n")
; for ww in [1111,2222,3333] { ; TODO fix array literal conversion error
; c64scr.print_w(ww)
; c64scr.print(",")
; }
c64scr.print("\n")
ubyte[] ubb1 = [ 1 ]
ubyte[] ubb2 = [ 1, 2]
ubyte[] ubb3 = [ 1,2,3 ]
ubyte[] ubb4 = [ 1,2,3,4 ]
uword[] uww1 = [111]
uword[] uww2 = [111,222]
uword[] uww3 = [111,222,333]
uword[] uww4 = [111,222,333,444]
reverse(ubb1)
reverse(ubb2)
reverse(ubb3)
reverse(ubb4)
reverse(uww1)
reverse(uww2)
reverse(uww3)
reverse(uww4)
for ub in ubb1 {
c64scr.print_ub(ub)
c64scr.print(",")
}
c64scr.print("\n")
for ub in ubb2 {
c64scr.print_ub(ub)
c64scr.print(",")
}
c64scr.print("\n")
for ub in ubb3 {
c64scr.print_ub(ub)
c64scr.print(",")
}
c64scr.print("\n")
for ub in ubb4 {
c64scr.print_ub(ub)
c64scr.print(",")
}
c64scr.print("\n")
for uw in uww1 {
c64scr.print_uw(uw)
c64scr.print(",")
}
c64scr.print("\n")
for uw in uww2 {
c64scr.print_uw(uw)
c64scr.print(",")
}
c64scr.print("\n")
for uw in uww3 {
c64scr.print_uw(uw)
c64scr.print(",")
}
c64scr.print("\n")
for uw in uww4 {
c64scr.print_uw(uw)
c64scr.print(",")
}
c64scr.print("\n")
float[] fa = [1.1, 2.2, 3.3, 4.4, 5.5]
reverse(fa)
sort(uww3)
sort(fa)
for ub in 0 to len(fa)-1 {
c64flt.print_f(fa[ub])
c64scr.print(",")
}
c64scr.print("\n")
} }
} }

View File

@ -12,7 +12,7 @@ main {
return return
str s1 = "hello" str s1 = "hello"
str s2 = "screencodes" ; TODO as c64sc str s2 = @"screencodes"
&str ms1 = $c000 &str ms1 = $c000

View File

@ -414,7 +414,7 @@ main {
count = 0 count = 0
total = 0 total = 0
c64scr.print("byte var in arrayliteral: ") c64scr.print("byte var in arrayliteral: ")
for bb in [1,3,5,99] { ; TODO now gives compiler error, fix byte var array literal conversion for bb in [1,3,5,99] {
count++ count++
total += bb total += bb
} }
@ -790,7 +790,7 @@ main {
count = 0 count = 0
total = 0 total = 0
c64scr.print("word var in arrayliteral: ") c64scr.print("word var in arrayliteral: ")
for ww in [1111,3333,555,999] { ; TODO now compiler error, fix word var array literal conversion for ww in [1111,3333,555,999] {
count++ count++
total += ww total += ww
} }