mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
improved deduction of array datatypes
This commit is contained in:
parent
ae90a957c6
commit
cc9965cc96
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 -> {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user