mirror of
https://github.com/irmen/prog8.git
synced 2024-12-22 18:30:01 +00:00
IR now contains "bool" as a type instead of already erasing it into "ubyte". (boolean literals still are simply just 1 and 0 values)
This commit is contained in:
parent
65ddcf91d0
commit
cbc4b75e50
@ -250,7 +250,13 @@ class StRomSub(name: String,
|
||||
|
||||
class StSubroutineParameter(val name: String, val type: DataType)
|
||||
class StRomSubParameter(val register: RegisterOrStatusflag, val type: DataType)
|
||||
class StArrayElement(val number: Double?, val addressOfSymbol: String?, val boolean: Boolean?)
|
||||
class StArrayElement(val number: Double?, val addressOfSymbol: String?, val boolean: Boolean?) {
|
||||
init {
|
||||
if(number!=null) require(addressOfSymbol==null && boolean==null)
|
||||
if(addressOfSymbol!=null) require(number==null && boolean==null)
|
||||
if(boolean!=null) require(addressOfSymbol==null && number==null)
|
||||
}
|
||||
}
|
||||
|
||||
typealias StString = Pair<String, Encoding>
|
||||
typealias StArray = List<StArrayElement>
|
||||
|
@ -9,7 +9,7 @@ Maybe this routine can be made more intelligent. See usesOtherRegistersWhileEva
|
||||
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- keep boolean array intact in IR so that it might be represented as a bitmask in the resulting code (8 times storage improvement)
|
||||
- ir: there are vars in INITGLOBALS that are initialized with code where they simpley have a static numerical initializer value, and could just as well be in VARIABLESWITHINIT . Why are their StVar's not initialized!?
|
||||
- improve detection that a variable is not read before being written so that initializing it to zero can be omitted (only happens now if a vardecl is immediately followed by a for loop for instance)
|
||||
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||
- Can we support signed % (remainder) somehow?
|
||||
|
@ -1,14 +1,23 @@
|
||||
%import diskio
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
|
||||
bool[] barray = [true, false, true, false]
|
||||
bool value1
|
||||
bool value2 = barray[cx16.r0L]
|
||||
bool value3 = true
|
||||
bool value4 = false
|
||||
|
||||
sub start() {
|
||||
txt.print_ub(txt.width())
|
||||
txt.print_bool(value1)
|
||||
txt.spc()
|
||||
txt.print_bool(value2)
|
||||
txt.spc()
|
||||
txt.print_bool(value3)
|
||||
txt.nl()
|
||||
txt.print_ub(txt.height())
|
||||
txt.print_bool(value4)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
@ -202,15 +202,19 @@ class IRFileReader {
|
||||
var initNumeric: Double? = null
|
||||
var initArray: StArray? = null
|
||||
when(dt) {
|
||||
DataType.BOOL -> initNumeric = if(value.lowercase()=="false") 0.0 else 1.0
|
||||
in NumericDatatypes -> initNumeric = parseIRValue(value)
|
||||
in NumericDatatypesWithBoolean -> initNumeric = parseIRValue(value)
|
||||
DataType.ARRAY_BOOL -> {
|
||||
initArray = value.split(',').map {
|
||||
val boolean = parseIRValue(it) != 0.0
|
||||
StArrayElement(null, null, boolean)
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
initArray = value.split(',').map {
|
||||
if (it.startsWith('@'))
|
||||
StArrayElement(null, it.drop(1), null)
|
||||
else
|
||||
StArrayElement(parseIRValue(it), null, null)
|
||||
// TODO Boolean IR value?
|
||||
}
|
||||
}
|
||||
DataType.STR -> throw IRParseException("STR should have been converted to byte array")
|
||||
@ -489,7 +493,7 @@ class IRFileReader {
|
||||
private fun parseDatatype(type: String, isArray: Boolean): DataType {
|
||||
if(isArray) {
|
||||
return when(type) {
|
||||
// note: there are no BOOLEANS arrays anymore in the IR. Only UBYTE.
|
||||
"bool" -> DataType.ARRAY_BOOL
|
||||
"byte" -> DataType.ARRAY_B
|
||||
"ubyte", "str" -> DataType.ARRAY_UB
|
||||
"word" -> DataType.ARRAY_W
|
||||
|
@ -264,7 +264,11 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
in ArrayDatatypes -> {
|
||||
if(variable.onetimeInitializationArrayValue!==null) {
|
||||
variable.onetimeInitializationArrayValue.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
if(it.bool==true)
|
||||
"1"
|
||||
else if(it.bool==false)
|
||||
"0"
|
||||
else if(it.number!=null)
|
||||
it.number.toInt().toHex()
|
||||
else
|
||||
"@${it.addressOfSymbol}"
|
||||
|
@ -72,7 +72,7 @@ class IRSymbolTable {
|
||||
array.forEach {
|
||||
if(it.addressOfSymbol!=null) {
|
||||
val target = variable.lookup(it.addressOfSymbol!!)!!
|
||||
newArray.add(IRStArrayElement(null, target.scopedName))
|
||||
newArray.add(IRStArrayElement(null, null, target.scopedName))
|
||||
} else {
|
||||
newArray.add(IRStArrayElement.from(it))
|
||||
}
|
||||
@ -80,13 +80,8 @@ class IRSymbolTable {
|
||||
return newArray
|
||||
}
|
||||
scopedName = variable.scopedName
|
||||
val dt = when(variable.dt) {
|
||||
DataType.BOOL -> DataType.UBYTE
|
||||
DataType.ARRAY_BOOL -> DataType.ARRAY_UB
|
||||
else -> variable.dt
|
||||
}
|
||||
varToadd = IRStStaticVariable(scopedName,
|
||||
dt,
|
||||
variable.dt,
|
||||
variable.onetimeInitializationNumericValue,
|
||||
variable.onetimeInitializationStringValue,
|
||||
fixupAddressOfInArray(variable.onetimeInitializationArrayValue),
|
||||
@ -215,27 +210,25 @@ class IRStStaticVariable(name: String,
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
require(dt!=DataType.BOOL && dt!=DataType.ARRAY_BOOL)
|
||||
}
|
||||
|
||||
val uninitialized = onetimeInitializationArrayValue==null && onetimeInitializationStringValue==null && onetimeInitializationNumericValue==null
|
||||
|
||||
val typeString: String = dt.typeString(length)
|
||||
}
|
||||
|
||||
class IRStArrayElement(val number: Double?, val addressOfSymbol: String?) {
|
||||
class IRStArrayElement(val bool: Boolean?, val number: Double?, val addressOfSymbol: String?) {
|
||||
companion object {
|
||||
fun from(elt: StArrayElement): IRStArrayElement {
|
||||
return if(elt.boolean!=null)
|
||||
IRStArrayElement(if(elt.boolean==true) 1.0 else 0.0, elt.addressOfSymbol)
|
||||
IRStArrayElement(elt.boolean, null, elt.addressOfSymbol)
|
||||
else
|
||||
IRStArrayElement(elt.number, elt.addressOfSymbol)
|
||||
IRStArrayElement(null, elt.number, elt.addressOfSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
require(number!=null || addressOfSymbol!=null)
|
||||
if(bool!=null) require(number==null && addressOfSymbol==null)
|
||||
if(number!=null) require(bool==null && addressOfSymbol==null)
|
||||
if(addressOfSymbol!=null) require(number==null || bool==null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import prog8.code.right
|
||||
fun DataType.typeString(length: Int?): String {
|
||||
val lengthStr = if(length==0) "" else length.toString()
|
||||
return when (this) {
|
||||
DataType.BOOL -> "ubyte" // in IR , a boolean is represented by an ubyte.
|
||||
DataType.BOOL -> "bool" // in IR , a boolean is represented by an ubyte.
|
||||
DataType.UBYTE -> "ubyte"
|
||||
DataType.BYTE -> "byte"
|
||||
DataType.UWORD -> "uword"
|
||||
@ -17,7 +17,7 @@ fun DataType.typeString(length: Int?): String {
|
||||
DataType.LONG -> "long"
|
||||
DataType.FLOAT -> "float"
|
||||
DataType.STR -> "ubyte[$lengthStr]" // here string doesn't exist as a seperate datatype anymore
|
||||
DataType.ARRAY_BOOL -> "ubyte[$lengthStr]" // in IR , a boolean is represented by an ubyte.
|
||||
DataType.ARRAY_BOOL -> "bool[$lengthStr]" // in IR , a boolean is represented by an ubyte.
|
||||
DataType.ARRAY_UB -> "ubyte[$lengthStr]"
|
||||
DataType.ARRAY_B -> "byte[$lengthStr]"
|
||||
DataType.ARRAY_UW -> "uword[$lengthStr]"
|
||||
|
@ -1,9 +1,12 @@
|
||||
package prog8.vm
|
||||
|
||||
import prog8.code.Either
|
||||
import prog8.code.core.ArrayDatatypes
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.SplitWordArrayTypes
|
||||
import prog8.code.left
|
||||
import prog8.code.right
|
||||
import prog8.intermediate.*
|
||||
|
||||
class VmProgramLoader {
|
||||
@ -227,7 +230,7 @@ class VmProgramLoader {
|
||||
|
||||
variable.onetimeInitializationNumericValue?.let {
|
||||
when(variable.dt) {
|
||||
DataType.UBYTE -> memory.setUB(addr, it.toInt().toUByte())
|
||||
DataType.UBYTE, DataType.BOOL -> memory.setUB(addr, it.toInt().toUByte())
|
||||
DataType.BYTE -> memory.setSB(addr, it.toInt().toByte())
|
||||
DataType.UWORD -> memory.setUW(addr, it.toInt().toUShort())
|
||||
DataType.WORD -> memory.setSW(addr, it.toInt().toShort())
|
||||
@ -236,19 +239,8 @@ class VmProgramLoader {
|
||||
}
|
||||
}
|
||||
variable.onetimeInitializationArrayValue?.let { iElts ->
|
||||
require(variable.length==iElts.size || iElts.size==1 || iElts.isEmpty())
|
||||
if(iElts.isEmpty() || iElts.size==1) {
|
||||
val iElt = if(iElts.isEmpty()) {
|
||||
require(variable.uninitialized)
|
||||
IRStArrayElement(0.0, null)
|
||||
} else {
|
||||
require(!variable.uninitialized)
|
||||
iElts[0]
|
||||
}
|
||||
initializeWithOneValue(variable, iElt, addr, symbolAddresses, memory, program)
|
||||
} else {
|
||||
initializeWithValues(variable, iElts, addr, symbolAddresses, memory, program)
|
||||
}
|
||||
require(variable.length==iElts.size)
|
||||
initializeWithValues(variable, iElts, addr, symbolAddresses, memory, program)
|
||||
}
|
||||
require(variable.onetimeInitializationStringValue==null) { "in vm/ir, strings should have been converted into bytearrays." }
|
||||
}
|
||||
@ -264,43 +256,71 @@ class VmProgramLoader {
|
||||
) {
|
||||
var address = startAddress
|
||||
when (variable.dt) {
|
||||
DataType.ARRAY_BOOL -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ throw IRParseException("didn't expect float") },
|
||||
{ b -> memory.setUB(address, if(b) 1u else 0u) }
|
||||
)
|
||||
address++
|
||||
}
|
||||
}
|
||||
DataType.STR, DataType.ARRAY_UB -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toUByte()
|
||||
memory.setUB(address, value)
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ memory.setUB(address, it.toInt().toUByte()) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address++
|
||||
}
|
||||
}
|
||||
|
||||
DataType.ARRAY_B -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toByte()
|
||||
memory.setSB(address, value)
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ memory.setSB(address, it.toInt().toByte()) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address++
|
||||
}
|
||||
}
|
||||
|
||||
DataType.ARRAY_UW -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toUShort()
|
||||
memory.setUW(address, value)
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ memory.setUW(address, it.toInt().toUShort()) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address += 2
|
||||
}
|
||||
}
|
||||
|
||||
DataType.ARRAY_W -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toInt().toShort()
|
||||
memory.setSW(address, value)
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ memory.setSW(address, it.toInt().toShort()) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address += 2
|
||||
}
|
||||
}
|
||||
|
||||
in SplitWordArrayTypes -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses).toUInt()
|
||||
memory.setUB(address, (value and 255u).toUByte())
|
||||
memory.setUB(address + variable.length!!, (value shr 8).toUByte())
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toUInt()
|
||||
memory.setUB(address, (integer and 255u).toUByte())
|
||||
memory.setUB(address + variable.length!!, (integer shr 8).toUByte())
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address++
|
||||
}
|
||||
}
|
||||
@ -308,7 +328,10 @@ class VmProgramLoader {
|
||||
DataType.ARRAY_F -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
memory.setFloat(address, value)
|
||||
value.fold(
|
||||
{ memory.setFloat(address, it) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||
}
|
||||
}
|
||||
@ -328,61 +351,96 @@ class VmProgramLoader {
|
||||
var address = startAddress
|
||||
when (variable.dt) {
|
||||
DataType.STR, DataType.ARRAY_UB -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toUByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUB(address, value)
|
||||
address++
|
||||
}
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toInt().toUByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUB(address, integer)
|
||||
address++
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
}
|
||||
|
||||
DataType.ARRAY_B -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setSB(address, value)
|
||||
address++
|
||||
}
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toInt().toByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setSB(address, integer)
|
||||
address++
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") },
|
||||
)
|
||||
}
|
||||
|
||||
DataType.ARRAY_UW -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toUShort()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUW(address, value)
|
||||
address += 2
|
||||
}
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toInt().toUShort()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUW(address, integer)
|
||||
address += 2
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
}
|
||||
|
||||
DataType.ARRAY_W -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toInt().toShort()
|
||||
repeat(variable.length!!) {
|
||||
memory.setSW(address, value)
|
||||
address += 2
|
||||
}
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toInt().toShort()
|
||||
repeat(variable.length!!) {
|
||||
memory.setSW(address, integer)
|
||||
address += 2
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
}
|
||||
|
||||
in SplitWordArrayTypes -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses).toUInt()
|
||||
val lsb = (value and 255u).toUByte()
|
||||
val msb = (value shr 8).toUByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUB(address, lsb)
|
||||
memory.setUB(address + variable.length!!, msb)
|
||||
address++
|
||||
}
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
value.fold(
|
||||
{
|
||||
val integer = it.toUInt()
|
||||
val lsb = (integer and 255u).toUByte()
|
||||
val msb = (integer shr 8).toUByte()
|
||||
repeat(variable.length!!) {
|
||||
memory.setUB(address, lsb)
|
||||
memory.setUB(address + variable.length!!, msb)
|
||||
address++
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
}
|
||||
|
||||
DataType.ARRAY_F -> {
|
||||
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
|
||||
repeat(variable.length!!) {
|
||||
memory.setFloat(address, value)
|
||||
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||
}
|
||||
value.fold(
|
||||
{ d ->
|
||||
repeat(variable.length!!) {
|
||||
memory.setFloat(address, d)
|
||||
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
|
||||
}
|
||||
},
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
}
|
||||
|
||||
else -> throw IRParseException("invalid dt")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitializerValue(arrayDt: DataType, elt: IRStArrayElement, symbolAddresses: MutableMap<String, Int>): Double {
|
||||
private fun getInitializerValue(arrayDt: DataType, elt: IRStArrayElement, symbolAddresses: MutableMap<String, Int>): Either<Double, Boolean> {
|
||||
if(elt.addressOfSymbol!=null) {
|
||||
when(arrayDt) {
|
||||
DataType.ARRAY_UB, DataType.STR, DataType.ARRAY_B, DataType.ARRAY_BOOL -> {
|
||||
@ -395,17 +453,18 @@ class VmProgramLoader {
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
||||
} else
|
||||
throw IRParseException("for byte-array address-of, expected < or > (lsb/msb)")
|
||||
return symbolAddress.toDouble()
|
||||
return left(symbolAddress.toDouble())
|
||||
}
|
||||
else -> {
|
||||
val name = elt.addressOfSymbol!!
|
||||
val symbolAddress = symbolAddresses[name]
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name")
|
||||
return symbolAddress.toDouble()
|
||||
return left(symbolAddress.toDouble())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return elt.number!!
|
||||
}
|
||||
} else if (elt.number!=null) {
|
||||
return left(elt.number!!)
|
||||
} else
|
||||
return right(elt.bool!!)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user