mirror of
https://github.com/irmen/prog8.git
synced 2024-09-08 10:55:08 +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())
|
heapId = heap.addIntegerArray(type, intArrayWithAddressOfs.toTypedArray())
|
||||||
} else {
|
} else {
|
||||||
val valuesInArray = array.map { (it as NumericLiteralValue).number }
|
val valuesInArray = array.map { (it as? NumericLiteralValue)?.number }
|
||||||
heapId = if(type== DataType.ARRAY_F) {
|
if(null !in valuesInArray) {
|
||||||
val doubleArray = valuesInArray.map { it.toDouble() }.toDoubleArray()
|
heapId = if (type == DataType.ARRAY_F) {
|
||||||
heap.addDoublesArray(doubleArray)
|
val doubleArray = valuesInArray.map { it!!.toDouble() }.toDoubleArray()
|
||||||
} else {
|
heap.addDoublesArray(doubleArray)
|
||||||
val integerArray = valuesInArray.map { it.toInt() }
|
} else {
|
||||||
heap.addIntegerArray(type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
|
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")
|
return err("invalid word array size, must be 1-128")
|
||||||
}
|
}
|
||||||
TODO("${value.position}")
|
|
||||||
return err("invalid word array initialization value ${value.type}, expected $targetDt")
|
return err("invalid word array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
|
@ -7,6 +7,7 @@ import prog8.ast.Program
|
|||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
import prog8.compiler.HeapValues
|
||||||
import prog8.compiler.target.c64.AssemblyProgram
|
import prog8.compiler.target.c64.AssemblyProgram
|
||||||
import prog8.functions.BuiltinFunctions
|
import prog8.functions.BuiltinFunctions
|
||||||
|
|
||||||
@ -233,10 +234,49 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(refLiteral: ReferenceLiteralValue): Expression {
|
override fun visit(refLiteral: ReferenceLiteralValue): Expression {
|
||||||
if(refLiteral.parent !is VarDecl) {
|
val litval = super.visit(refLiteral)
|
||||||
return makeIdentifierFromRefLv(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 {
|
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) {
|
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) {
|
private fun translate(stmt: PostIncrDecr) {
|
||||||
|
@ -5,6 +5,7 @@ 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.fixupArrayDatatype
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE
|
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE
|
||||||
import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE
|
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 {
|
override fun visit(refLiteral: ReferenceLiteralValue): Expression {
|
||||||
val litval = super.visit(refLiteral)
|
val litval = super.visit(refLiteral)
|
||||||
if(litval is ReferenceLiteralValue) {
|
if(litval is ReferenceLiteralValue) {
|
||||||
if (litval.isString) {
|
if (litval.isArray) {
|
||||||
// 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) {
|
|
||||||
val vardecl = litval.parent as? VarDecl
|
val vardecl = litval.parent as? VarDecl
|
||||||
if (vardecl!=null) {
|
if (vardecl!=null) {
|
||||||
if(litval.heapId!=null) {
|
return fixupArrayDatatype(litval, vardecl, program.heap)
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(litval.heapId==null)
|
|
||||||
litval.addToHeap(program.heap)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return litval
|
return litval
|
||||||
|
@ -4,35 +4,50 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
ubyte abc
|
|
||||||
|
|
||||||
|
|
||||||
sub start() {
|
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
|
for float fl in [1.1, 2.2, 5.5, 99.99] {
|
||||||
ubyte zzz
|
c64flt.print_f(fl)
|
||||||
|
c64.CHROUT(',')
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
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…
Reference in New Issue
Block a user