improved deduction of array datatypes

This commit is contained in:
Irmen de Jong 2019-07-30 23:35:25 +02:00
parent ae90a957c6
commit cc9965cc96
6 changed files with 134 additions and 62 deletions

View File

@ -600,13 +600,15 @@ class ReferenceLiteralValue(val type: DataType, // only reference types allo
}
heapId = heap.addIntegerArray(type, intArrayWithAddressOfs.toTypedArray())
} else {
val valuesInArray = array.map { (it as NumericLiteralValue).number }
heapId = if(type== DataType.ARRAY_F) {
val doubleArray = valuesInArray.map { it.toDouble() }.toDoubleArray()
heap.addDoublesArray(doubleArray)
} else {
val integerArray = valuesInArray.map { it.toInt() }
heap.addIntegerArray(type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
val valuesInArray = array.map { (it as? NumericLiteralValue)?.number }
if(null !in valuesInArray) {
heapId = if (type == DataType.ARRAY_F) {
val doubleArray = valuesInArray.map { it!!.toDouble() }.toDoubleArray()
heap.addDoublesArray(doubleArray)
} else {
val integerArray = valuesInArray.map { it!!.toInt() }
heap.addIntegerArray(type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
}
}
}
}

View File

@ -1061,7 +1061,6 @@ internal class AstChecker(private val program: Program,
}
return err("invalid word array size, must be 1-128")
}
TODO("${value.position}")
return err("invalid word array initialization value ${value.type}, expected $targetDt")
}
DataType.ARRAY_F -> {

View File

@ -7,6 +7,7 @@ import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.compiler.HeapValues
import prog8.compiler.target.c64.AssemblyProgram
import prog8.functions.BuiltinFunctions
@ -233,10 +234,49 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
}
override fun visit(refLiteral: ReferenceLiteralValue): Expression {
if(refLiteral.parent !is VarDecl) {
return makeIdentifierFromRefLv(refLiteral)
val litval = super.visit(refLiteral)
if(litval is ReferenceLiteralValue) {
if (litval.isString) {
// intern the string; move it into the heap
if (litval.str!!.length !in 1..255)
checkResult.add(ExpressionError("string literal length must be between 1 and 255", litval.position))
else {
litval.addToHeap(program.heap)
}
} else if (litval.isArray) {
val vardecl = litval.parent as? VarDecl
if (vardecl!=null) {
return fixupArrayDatatype(litval, vardecl, program.heap)
} else {
// fix the datatype of the array (also on the heap) to the 'biggest' datatype in the array
// (we don't know the desired datatype here exactly so we guess)
val datatype = determineArrayDt(litval.array!!) ?: return litval
val litval2 = litval.cast(datatype)!!
litval2.parent = litval.parent
// finally, replace the literal by a identifier reference.
return makeIdentifierFromRefLv(litval2)
}
}
}
return super.visit(refLiteral)
return litval
}
private fun determineArrayDt(array: Array<Expression>): DataType? {
val datatypesInArray = array.mapNotNull { it.inferType(program) }
if(datatypesInArray.isEmpty())
return null
if(DataType.FLOAT in datatypesInArray)
return DataType.ARRAY_F
if(DataType.WORD in datatypesInArray)
return DataType.ARRAY_W
if(DataType.UWORD in datatypesInArray)
return DataType.ARRAY_UW
if(DataType.BYTE in datatypesInArray)
return DataType.ARRAY_B
if(DataType.UBYTE in datatypesInArray)
return DataType.ARRAY_UB
return null
}
private fun makeIdentifierFromRefLv(refLiteral: ReferenceLiteralValue): IdentifierReference {
@ -315,3 +355,20 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
}
}
internal fun fixupArrayDatatype(array: ReferenceLiteralValue, vardecl: VarDecl, heap: HeapValues): ReferenceLiteralValue {
if(array.heapId!=null) {
val arrayDt = array.type
if(arrayDt!=vardecl.datatype) {
// fix the datatype of the array (also on the heap) to match the vardecl
val litval2 = array.cast(vardecl.datatype)!!
vardecl.value = litval2
litval2.linkParents(vardecl)
litval2.addToHeap(heap) // TODO is the previous array discarded from the resulting asm code?
return litval2
}
} else {
array.addToHeap(heap)
}
return array
}

View File

@ -952,7 +952,27 @@ internal class AsmGen2(val program: Program,
}
private fun translate(stmt: ForLoop) {
TODO("forloop $stmt")
when(stmt.iterable) {
is RangeExpr -> {
println("forloop over range $stmt")
}
is IdentifierReference -> {
val iterableDt = stmt.iterable.inferType(program)
when(iterableDt) {
DataType.STR, DataType.STR_S, DataType.ARRAY_UB, DataType.ARRAY_B -> {
println("forloop over byte array/string $stmt")
}
DataType.ARRAY_W, DataType.ARRAY_UW -> {
println("forloop over word array $stmt")
}
DataType.ARRAY_F -> {
println("forloop over float array $stmt")
}
else -> throw AssemblyError("can't iterate over $iterableDt")
}
}
else -> throw AssemblyError("can't iterate over ${stmt.iterable}")
}
}
private fun translate(stmt: PostIncrDecr) {

View File

@ -5,6 +5,7 @@ import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.fixupArrayDatatype
import prog8.ast.statements.*
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE
@ -580,33 +581,11 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
override fun visit(refLiteral: ReferenceLiteralValue): Expression {
val litval = super.visit(refLiteral)
if(litval is ReferenceLiteralValue) {
if (litval.isString) {
// intern the string; move it into the heap
if (litval.str!!.length !in 1..255)
addError(ExpressionError("string literal length must be between 1 and 255", litval.position))
else {
litval.addToHeap(program.heap)
}
} else if (litval.isArray) {
if (litval.isArray) {
val vardecl = litval.parent as? VarDecl
if (vardecl!=null) {
if(litval.heapId!=null) {
val arrayDt = litval.type
if(arrayDt!=vardecl.datatype) {
// fix the datatype of the array (also on the heap) to match the vardecl
val litval2 = litval.cast(vardecl.datatype)!!
vardecl.value = litval2
litval2.linkParents(vardecl)
litval2.addToHeap(program.heap) // TODO is the previous array discarded from the resulting asm code?
return litval2
}
}
} else {
TODO("VISIT REFLITERAL OUTSIDE OF VARDECL $litval")
return fixupArrayDatatype(litval, vardecl, program.heap)
}
if(litval.heapId==null)
litval.addToHeap(program.heap)
}
}
return litval

View File

@ -4,35 +4,50 @@
main {
ubyte abc
sub start() {
; byte bvar
; ubyte var2
;
; for A in "hello" {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in [1,3,5,99] {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in 10 to 20 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
A=abc
ubyte zzz
repeat {
uword wvar
Y=abc
Y=zzz
wvar=99
} until 99
repeat {
uword wvar
Y=abc
Y=zzz
wvar=99
} until 99
if A>0 {
uword wvar
Y=abc
Y=zzz
wvar=99
for float fl in [1.1, 2.2, 5.5, 99.99] {
c64flt.print_f(fl)
c64.CHROUT(',')
}
c64.CHROUT('\n')
; for var2 in 10 to 20 {
; c64scr.print_ub(var2)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for ubyte var3 in 10 to 20 {
; c64scr.print_ub(var3)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for bvar in -5 to 5 {
; c64scr.print_b(bvar)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
}
}