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

View File

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

View File

@ -2,8 +2,12 @@ package prog8tests.ast
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.statements.InlineAssembly import prog8.ast.statements.InlineAssembly
import prog8.codegen.target.C64Target
import prog8.compiler.compileProgram
import prog8tests.helpers.compileText
class TestVarious: FunSpec({ class TestVarious: FunSpec({
test("symbol names in inline assembly blocks") { test("symbol names in inline assembly blocks") {
@ -25,5 +29,26 @@ label2:
names2 shouldBe setOf("label", "lda", "sta", "ea", "value", "label2", "othervalue", "valid", "words") 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.DataType
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.statements.ZeropageWish import prog8.ast.statements.ZeropageWish
import prog8.ast.toHex
/** /**
@ -123,8 +122,8 @@ open class StNode(val name: String,
class StStaticVariable(name: String, class StStaticVariable(name: String,
val dt: DataType, val dt: DataType,
val initialNumericValue: Double?, val initialNumericValue: Double?,
val initialStringValue: Pair<String, Encoding>?, val initialStringValue: StString?,
val initialArrayValue: DoubleArray?, val initialArrayValue: StArray?,
val arraysize: Int?, val arraysize: Int?,
val zpw: ZeropageWish, val zpw: ZeropageWish,
position: Position) : StNode(name, StNodeType.STATICVAR, position) { 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 StNode(name, StNodeType.MEMVAR, position
) { ) {
override fun printProperties() { 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 Arrays
^^^^^^ ^^^^^^
Array types are also supported. They can be made of bytes, words or floats, strings, and other arrays Array types are also supported. They can be formed from a list of bytes, words, floats, or addresses of other variables
(although the usefulness of the latter is very limited for now):: (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[10] array ; array of 10 bytes, initially set to 0
byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value

View File

@ -3,13 +3,10 @@ TODO
For next release 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 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. 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!!
... ...