mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
fixed arrayliteral regression
This commit is contained in:
parent
5a54066f81
commit
7d20458e82
@ -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"
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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!!
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user