fixed arrayliteral regression

This commit is contained in:
Irmen de Jong 2022-03-10 00:21:25 +01:00
parent 5a54066f81
commit 7d20458e82
6 changed files with 80 additions and 49 deletions

View File

@ -439,7 +439,7 @@ internal class ProgramAndVarsGen(
private class ZpArrayWithInitial(
val name: List<String>,
val alloc: Zeropage.ZpAllocation,
val value: DoubleArray
val value: StArray
)
private fun getZpStringVarsWithInitvalue(): Collection<ZpStringWithInitial> {
@ -518,7 +518,7 @@ internal class ProgramAndVarsGen(
}
}
private fun arrayVariable2asm(varname: String, dt: DataType, value: DoubleArray?, orNumberOfZeros: Int?) {
private fun arrayVariable2asm(varname: String, dt: DataType, value: StArray?, orNumberOfZeros: Int?) {
when(dt) {
DataType.ARRAY_UB -> {
val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros)
@ -561,9 +561,9 @@ internal class ProgramAndVarsGen(
}
}
DataType.ARRAY_F -> {
val array = value ?: DoubleArray(orNumberOfZeros!!)
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
val floatFills = array.map {
compTarget.machine.getFloat(it).makeFloatFillAsm()
compTarget.machine.getFloat(it.number!!).makeFloatFillAsm()
}
asmgen.out(varname)
for (f in array.zip(floatFills))
@ -573,6 +573,14 @@ internal class ProgramAndVarsGen(
}
}
private fun zeroFilledArray(numElts: Int): StArray {
val values = mutableListOf<StArrayElement>()
repeat(numElts) {
values.add(StArrayElement(0.0, null))
}
return values
}
private fun memdefsAndConsts2asm(memvars: Collection<StMemVar>, consts: Collection<StConstant>) {
memvars.forEach {
asmgen.out(" ${it.name} = ${it.address.toHex()}")
@ -602,48 +610,41 @@ internal class ProgramAndVarsGen(
asmgen.out(" .byte " + chunk.joinToString())
}
private fun makeArrayFillDataUnsigned(dt: DataType, value: DoubleArray?, orNumberOfZeros: Int?): List<String> {
val array = value ?: DoubleArray(orNumberOfZeros!!)
private fun makeArrayFillDataUnsigned(dt: DataType, value: StArray?, orNumberOfZeros: Int?): List<String> {
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
return when (dt) {
DataType.ARRAY_UB ->
// byte array can never contain pointer-to types, so treat values as all integers
array.map {
val number = it.toInt()
val number = it.number!!.toInt()
"$"+number.toString(16).padStart(2, '0')
}
DataType.ARRAY_UW -> array.map {
"$" + it.toInt().toString(16).padStart(4, '0')
// TODO: initial array literals with address-of, or just variable references, are no longer possible at this time
// when (it) {
// is NumericLiteral -> {
// "$" + it.number.toInt().toString(16).padStart(4, '0')
// }
// is AddressOf -> {
// asmgen.asmSymbolName(it.identifier)
// }
// is IdentifierReference -> {
// asmgen.asmSymbolName(it)
// }
// else -> throw AssemblyError("weird array elt dt")
// }
if(it.number!=null) {
"$" + it.number!!.toInt().toString(16).padStart(4, '0')
}
else if(it.addressOf!=null) {
asmgen.asmSymbolName(it.addressOf!!)
}
else
throw AssemblyError("weird array elt")
}
else -> throw AssemblyError("invalid dt")
}
}
private fun makeArrayFillDataSigned(dt: DataType, value: DoubleArray?, orNumberOfZeros: Int?): List<String> {
val array = value ?: DoubleArray(orNumberOfZeros!!)
private fun makeArrayFillDataSigned(dt: DataType, value: StArray?, orNumberOfZeros: Int?): List<String> {
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
return when (dt) {
// byte array can never contain pointer-to types, so treat values as all integers
DataType.ARRAY_UB ->
// byte array can never contain pointer-to types, so treat values as all integers
array.map {
val number = it.toInt()
val number = it.number!!.toInt()
"$"+number.toString(16).padStart(2, '0')
}
DataType.ARRAY_B ->
// byte array can never contain pointer-to types, so treat values as all integers
array.map {
val number = it.toInt()
val number = it.number!!.toInt()
val hexnum = number.absoluteValue.toString(16).padStart(2, '0')
if(number>=0)
"$$hexnum"
@ -651,11 +652,11 @@ internal class ProgramAndVarsGen(
"-$$hexnum"
}
DataType.ARRAY_UW -> array.map {
val number = it.toInt()
val number = it.number!!.toInt()
"$" + number.toString(16).padStart(4, '0')
}
DataType.ARRAY_W -> array.map {
val number = it.toInt()
val number = it.number!!.toInt()
val hexnum = number.absoluteValue.toString(16).padStart(4, '0')
if(number>=0)
"$$hexnum"

View File

@ -1,11 +1,10 @@
package prog8.compiler.astprocessing
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.base.Position
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.ArrayLiteral
import prog8.ast.expressions.NumericLiteral
import prog8.ast.expressions.StringLiteral
import prog8.ast.expressions.*
import prog8.ast.statements.Block
import prog8.ast.statements.Label
import prog8.ast.statements.Subroutine
@ -66,15 +65,17 @@ internal class SymbolTableMaker: IAstVisitor {
st.origAstLinks[decl] = node
}
private fun makeInitialArray(arrayLit: ArrayLiteral?): DoubleArray? {
private fun makeInitialArray(arrayLit: ArrayLiteral?): StArray? {
if(arrayLit==null)
return null
return arrayLit.value.map {
if(it !is NumericLiteral)
TODO("ability to have addressof or variables inside array literal currently not possible @ ${arrayLit.position}")
else
it.number
}.toDoubleArray()
when(it){
is AddressOf -> StArrayElement(null, it.identifier.nameInSource)
is IdentifierReference -> StArrayElement(null, it.nameInSource)
is NumericLiteral -> StArrayElement(it.number, null)
else -> throw FatalAstException("weird element dt in array literal")
}
}.toList()
}
override fun visit(label: Label) {
@ -82,4 +83,4 @@ internal class SymbolTableMaker: IAstVisitor {
scopestack.peek().add(node)
st.origAstLinks[label] = node
}
}
}

View File

@ -2,8 +2,12 @@ package prog8tests.ast
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import prog8.ast.base.Position
import prog8.ast.statements.InlineAssembly
import prog8.codegen.target.C64Target
import prog8.compiler.compileProgram
import prog8tests.helpers.compileText
class TestVarious: FunSpec({
test("symbol names in inline assembly blocks") {
@ -25,5 +29,26 @@ label2:
names2 shouldBe setOf("label", "lda", "sta", "ea", "value", "label2", "othervalue", "valid", "words")
}
test("array literals") {
val text="""
%zeropage basicsafe
main {
sub start() {
ubyte b1
ubyte b2
ubyte[] array1 = [1,2,3]
ubyte[] array2 = [9,8,7]
uword[] @shared addresses1 = [&b1, &b2]
uword[] @shared addresses2 = [array1, array2]
uword[] @shared addresses3 = [&array1, &array2]
uword[] @shared addresses4 = ["string1", "string2"]
uword[] @shared addresses5 = [1111, 2222]
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
})

View File

@ -4,7 +4,6 @@ import prog8.ast.Node
import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.ast.statements.ZeropageWish
import prog8.ast.toHex
/**
@ -123,8 +122,8 @@ open class StNode(val name: String,
class StStaticVariable(name: String,
val dt: DataType,
val initialNumericValue: Double?,
val initialStringValue: Pair<String, Encoding>?,
val initialArrayValue: DoubleArray?,
val initialStringValue: StString?,
val initialArrayValue: StArray?,
val arraysize: Int?,
val zpw: ZeropageWish,
position: Position) : StNode(name, StNodeType.STATICVAR, position) {
@ -153,6 +152,12 @@ class StMemVar(name: String, val dt: DataType, val address: UInt, position: Posi
StNode(name, StNodeType.MEMVAR, position
) {
override fun printProperties() {
print("$name dt=$dt address=${address.toHex()}")
print("$name dt=$dt address=${address.toString(16).padStart(4,'0')}")
}
}
class StArrayElement(val number: Double?, val addressOf: List<String>?)
typealias StString = Pair<String, Encoding>
typealias StArray = List<StArrayElement>

View File

@ -260,8 +260,10 @@ The largest 5-byte MFLPT float that can be stored is: **1.7014118345e+38** (ne
Arrays
^^^^^^
Array types are also supported. They can be made of bytes, words or floats, strings, and other arrays
(although the usefulness of the latter is very limited for now)::
Array types are also supported. They can be formed from a list of bytes, words, floats, or addresses of other variables
(such as explicit address-of expressions, strings, or other array variables) - values in an array literal
always have to be constants. Putting variables inside an array has to be done on a value-by-value basis.
Here are some examples of arrays::
byte[10] array ; array of 10 bytes, initially set to 0
byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value

View File

@ -3,13 +3,10 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- make 'intermediate' module containing the SymbolTable and dumbed down version of the Ast.
- make an intermediate representation containing the SymbolTable and dumbed down version of the Ast.
no vardecls in it anymore (these are part of the symboltable) and baked types, so no inferType too.
no name lookup in the Ast, always do this in the symbol table.
- codegen makeInitialArray()/makeArrayFillDataUnsigned():
initial array literals with address-of, or just variable references, are no longer possible at this time!!
...