tweak DataType class and memsizer related to subtypes/elementtypes

This commit is contained in:
Irmen de Jong 2024-12-23 17:27:57 +01:00
parent 126d4c69e6
commit 2727a4dcb3
22 changed files with 175 additions and 187 deletions

View File

@ -55,43 +55,18 @@ val BaseDataType.isPassByRef get() = this.isIterable
val BaseDataType.isPassByValue get() = !this.isIterable
sealed class SubType(val dt: BaseDataType) {
companion object {
private val types by lazy {
// lazy because of static initialization order
mapOf(
BaseDataType.UBYTE to SubUnsignedByte,
BaseDataType.BYTE to SubSignedByte,
BaseDataType.UWORD to SubUnsignedWord,
BaseDataType.WORD to SubSignedWord,
BaseDataType.FLOAT to SubFloat,
BaseDataType.BOOL to SubBool
)}
fun forDt(dt: BaseDataType) = types.getValue(dt)
}
}
data object SubUnsignedByte: SubType(BaseDataType.UBYTE)
data object SubSignedByte: SubType(BaseDataType.BYTE)
data object SubUnsignedWord: SubType(BaseDataType.UWORD)
data object SubSignedWord: SubType(BaseDataType.WORD)
data object SubBool: SubType(BaseDataType.BOOL)
data object SubFloat: SubType(BaseDataType.FLOAT)
class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
class DataType private constructor(val base: BaseDataType, val sub: BaseDataType?) {
init {
if(base.isArray) {
require(sub != null)
if(base.isSplitWordArray)
require(sub.dt == BaseDataType.UWORD || sub.dt == BaseDataType.WORD)
require(sub == BaseDataType.UWORD || sub == BaseDataType.WORD)
}
else if(base==BaseDataType.STR)
require(sub?.dt==BaseDataType.UBYTE) { "STR subtype should be ubyte" }
require(sub==BaseDataType.UBYTE) { "string subtype should be ubyte" }
else
require(sub == null)
require(sub == null) { "only string and array base types can have a subtype"}
}
override fun equals(other: Any?): Boolean {
@ -111,7 +86,7 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
BaseDataType.LONG to DataType(BaseDataType.LONG, null),
BaseDataType.FLOAT to DataType(BaseDataType.FLOAT, null),
BaseDataType.BOOL to DataType(BaseDataType.BOOL, null),
BaseDataType.STR to DataType(BaseDataType.STR, SubUnsignedByte),
BaseDataType.STR to DataType(BaseDataType.STR, BaseDataType.UBYTE),
BaseDataType.UNDEFINED to DataType(BaseDataType.UNDEFINED, null)
)
@ -119,10 +94,14 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
fun arrayFor(elementDt: BaseDataType, splitwordarray: Boolean=true): DataType {
val actualElementDt = if(elementDt==BaseDataType.STR) BaseDataType.UWORD else elementDt // array of strings is actually just an array of UWORD pointers
return if(splitwordarray && elementDt.isWord)
DataType(BaseDataType.ARRAY_SPLITW, SubType.forDt(actualElementDt))
else
DataType(BaseDataType.ARRAY, SubType.forDt(actualElementDt))
return if(splitwordarray && actualElementDt.isWord)
DataType(BaseDataType.ARRAY_SPLITW, actualElementDt)
else {
if(actualElementDt.isNumericOrBool && actualElementDt != BaseDataType.LONG)
DataType(BaseDataType.ARRAY, actualElementDt)
else
throw NoSuchElementException("invalid element dt "+elementDt)
}
}
}
@ -133,26 +112,26 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
fun elementType(): DataType =
if(base.isArray || base==BaseDataType.STR)
forDt(sub!!.dt)
forDt(sub!!)
else
throw IllegalArgumentException("not an array")
override fun toString(): String = when(base) {
BaseDataType.ARRAY -> {
when(sub) {
SubBool -> "bool[]"
SubFloat -> "float[]"
SubSignedByte -> "byte[]"
SubSignedWord -> "word[]"
SubUnsignedByte -> "ubyte[]"
SubUnsignedWord -> "uword[]"
null -> throw IllegalArgumentException("invalid sub type")
BaseDataType.BOOL -> "bool[]"
BaseDataType.FLOAT -> "float[]"
BaseDataType.BYTE -> "byte[]"
BaseDataType.WORD -> "word[]"
BaseDataType.UBYTE -> "ubyte[]"
BaseDataType.UWORD -> "uword[]"
else -> throw IllegalArgumentException("invalid sub type")
}
}
BaseDataType.ARRAY_SPLITW -> {
when(sub) {
SubSignedWord -> "word[] (split)"
SubUnsignedWord -> "uword[] (split)"
BaseDataType.WORD -> "word[] (split)"
BaseDataType.UWORD -> "uword[] (split)"
else -> throw IllegalArgumentException("invalid sub type")
}
}
@ -170,19 +149,19 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
BaseDataType.STR -> "str"
BaseDataType.ARRAY -> {
when(sub) {
SubUnsignedByte -> "ubyte["
SubUnsignedWord -> "@nosplit uword["
SubBool -> "bool["
SubSignedByte -> "byte["
SubSignedWord -> "@nosplit word["
SubFloat -> "float["
null -> throw IllegalArgumentException("invalid sub type")
BaseDataType.UBYTE -> "ubyte["
BaseDataType.UWORD -> "@nosplit uword["
BaseDataType.BOOL -> "bool["
BaseDataType.BYTE -> "byte["
BaseDataType.WORD -> "@nosplit word["
BaseDataType.FLOAT -> "float["
else -> throw IllegalArgumentException("invalid sub type")
}
}
BaseDataType.ARRAY_SPLITW -> {
when(sub) {
SubUnsignedWord -> "uword["
SubSignedWord -> "word["
BaseDataType.UWORD -> "uword["
BaseDataType.WORD -> "word["
else -> throw IllegalArgumentException("invalid sub type")
}
}
@ -228,22 +207,22 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
val isSigned = base.isSigned
val isUnsigned = !base.isSigned
val isArray = base.isArray
val isBoolArray = base.isArray && sub?.dt == BaseDataType.BOOL
val isByteArray = base.isArray && (sub?.dt == BaseDataType.UBYTE || sub?.dt == BaseDataType.BYTE)
val isUnsignedByteArray = base.isArray && sub?.dt == BaseDataType.UBYTE
val isSignedByteArray = base.isArray && sub?.dt == BaseDataType.BYTE
val isWordArray = base.isArray && (sub?.dt == BaseDataType.UWORD || sub?.dt == BaseDataType.WORD)
val isUnsignedWordArray = base.isArray && sub?.dt == BaseDataType.UWORD
val isSignedWordArray = base.isArray && sub?.dt == BaseDataType.WORD
val isFloatArray = base.isArray && sub?.dt == BaseDataType.FLOAT
val isBoolArray = base.isArray && sub == BaseDataType.BOOL
val isByteArray = base.isArray && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE)
val isUnsignedByteArray = base.isArray && sub == BaseDataType.UBYTE
val isSignedByteArray = base.isArray && sub == BaseDataType.BYTE
val isWordArray = base.isArray && (sub == BaseDataType.UWORD || sub == BaseDataType.WORD)
val isUnsignedWordArray = base.isArray && sub == BaseDataType.UWORD
val isSignedWordArray = base.isArray && sub == BaseDataType.WORD
val isFloatArray = base.isArray && sub == BaseDataType.FLOAT
val isString = base == BaseDataType.STR
val isBool = base == BaseDataType.BOOL
val isFloat = base == BaseDataType.FLOAT
val isLong = base == BaseDataType.LONG
val isStringly = base == BaseDataType.STR || base == BaseDataType.UWORD || (base == BaseDataType.ARRAY && (sub?.dt == BaseDataType.UBYTE || sub?.dt == BaseDataType.BYTE))
val isStringly = base == BaseDataType.STR || base == BaseDataType.UWORD || (base == BaseDataType.ARRAY && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE))
val isSplitWordArray = base.isSplitWordArray
val isSplitUnsignedWordArray = base.isSplitWordArray && sub?.dt == BaseDataType.UWORD
val isSplitSignedWordArray = base.isSplitWordArray && sub?.dt == BaseDataType.WORD
val isSplitUnsignedWordArray = base.isSplitWordArray && sub == BaseDataType.UWORD
val isSplitSignedWordArray = base.isSplitWordArray && sub == BaseDataType.WORD
val isIterable = base.isIterable
val isPassByRef = base.isPassByRef
val isPassByValue = base.isPassByValue

View File

@ -2,5 +2,14 @@ package prog8.code.core
interface IMemSizer {
fun memorySize(dt: DataType, numElements: Int?): Int
fun memorySize(dt: SubType): Int
fun memorySize(dt: BaseDataType): Int {
if(dt.isPassByRef)
return memorySize(DataType.forDt(BaseDataType.UWORD), null) // a pointer size
try {
return memorySize(DataType.forDt(dt), null)
} catch (x: NoSuchElementException) {
throw IllegalArgumentException(x.message)
}
}
}

View File

@ -15,23 +15,26 @@ class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
if(numElements==null) return 2 // treat it as a pointer size
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.STR -> numElements * 2
BaseDataType.FLOAT-> numElements * machine.FLOAT_MEM_SIZE
BaseDataType.UNDEFINED -> throw IllegalArgumentException("undefined has no memory size")
else -> throw IllegalArgumentException("invalid sub type")
}
}
else if (dt.isString) {
if(numElements!=null) return numElements // treat it as the size of the given string with the length
else return 2 // treat it as the size to store a string pointer
}
return when {
dt.isByteOrBool -> 1 * (numElements ?: 1)
dt.isFloat -> machine.FLOAT_MEM_SIZE * (numElements ?: 1)
dt.isLong -> throw IllegalArgumentException("long can not yet be put into memory")
dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size")
else -> 2 * (numElements ?: 1)
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
}
}

View File

@ -15,23 +15,26 @@ class Neo6502Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
if(numElements==null) return 2 // treat it as a pointer size
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.STR -> numElements * 2
BaseDataType.FLOAT-> numElements * machine.FLOAT_MEM_SIZE
BaseDataType.UNDEFINED -> throw IllegalArgumentException("undefined has no memory size")
else -> throw IllegalArgumentException("invalid sub type")
}
}
else if (dt.isString) {
if(numElements!=null) return numElements // treat it as the size of the given string with the length
else return 2 // treat it as the size to store a string pointer
}
return when {
dt.isByteOrBool -> 1 * (numElements ?: 1)
dt.isFloat -> machine.FLOAT_MEM_SIZE * (numElements ?: 1)
dt.isLong -> throw IllegalArgumentException("long can not yet be put into memory")
dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size")
else -> 2 * (numElements ?: 1)
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
}
}

View File

@ -14,23 +14,26 @@ class VMTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
if(numElements==null) return 2 // treat it as a pointer size
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.STR -> numElements * 2
BaseDataType.FLOAT-> numElements * machine.FLOAT_MEM_SIZE
BaseDataType.UNDEFINED -> throw IllegalArgumentException("undefined has no memory size")
else -> throw IllegalArgumentException("invalid sub type")
}
}
else if (dt.isString) {
if(numElements!=null) return numElements // treat it as the size of the given string with the length
else return 2 // treat it as the size to store a string pointer
}
return when {
dt.isByteOrBool -> 1 * (numElements ?: 1)
dt.isFloat -> machine.FLOAT_MEM_SIZE * (numElements ?: 1)
dt.isLong -> throw IllegalArgumentException("long can not yet be put into memory")
dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size")
else -> 2 * (numElements ?: 1)
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
}
}

View File

@ -3,28 +3,31 @@ package prog8.code.target.cbm
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.code.core.IMemSizer
import prog8.code.core.SubType
internal object CbmMemorySizer: IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
if(numElements==null) return 2 // treat it as a pointer size
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.STR -> numElements * 2
BaseDataType.FLOAT-> numElements * Mflpt5.FLOAT_MEM_SIZE
BaseDataType.UNDEFINED -> throw IllegalArgumentException("undefined has no memory size")
else -> throw IllegalArgumentException("invalid sub type")
}
}
else if (dt.isString) {
if(numElements!=null) return numElements // treat it as the size of the given string with the length
else return 2 // treat it as the size to store a string pointer
}
return when {
dt.isByteOrBool -> 1 * (numElements ?: 1)
dt.isFloat -> Mflpt5.FLOAT_MEM_SIZE * (numElements ?: 1)
dt.isLong -> throw IllegalArgumentException("long can not yet be put into memory")
dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size")
else -> 2 * (numElements ?: 1)
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
}
}

View File

@ -7,7 +7,7 @@ internal object DummyMemsizer : IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray) {
require(numElements != null)
return when(dt.sub?.dt) {
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.BYTE, BaseDataType.UBYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements*2
BaseDataType.FLOAT -> numElements*5
@ -21,8 +21,8 @@ internal object DummyMemsizer : IMemSizer {
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
override fun memorySize(dt: BaseDataType): Int {
return memorySize(DataType.forDt(dt), null)
}
}

View File

@ -477,9 +477,8 @@ class IRCodeGen(
}
else -> {
// iterate over regular array
val element = iterable.type.sub!!
val elementDt = element.dt
val elementSize = program.memsizer.memorySize(element)
val elementDt = iterable.type.sub!!
val elementSize = program.memsizer.memorySize(elementDt)
val lengthBytes = iterableLength!! * elementSize
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=indexReg, immediate = 0), null)
result += IRCodeChunk(loopLabel, null).also {

View File

@ -5,7 +5,7 @@ internal object DummyMemsizer : IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray || dt.isSplitWordArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.BYTE, BaseDataType.UBYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements*2
BaseDataType.FLOAT -> numElements*5
@ -19,8 +19,8 @@ internal object DummyMemsizer : IMemSizer {
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
override fun memorySize(dt: BaseDataType): Int {
return memorySize(DataType.forDt(dt), null)
}
}

View File

@ -438,7 +438,7 @@ internal class ConstantIdentifierReplacer(
} else {
require(rangeType.sub!=null)
ArrayLiteral(InferredTypes.InferredType.known(decl.datatype),
constRange.map { NumericLiteral(rangeType.sub!!.dt, it.toDouble(), decl.value!!.position) }.toTypedArray(),
constRange.map { NumericLiteral(rangeType.sub!!, it.toDouble(), decl.value!!.position) }.toTypedArray(),
position = decl.value!!.position)
}
}

View File

@ -198,7 +198,7 @@ class AstPreprocessor(val program: Program,
options.dontSplitWordArrays && decl.datatype.isSplitWordArray
private fun makeUnSplitArray(decl: VarDecl): Iterable<IAstModification> {
val splitDt = DataType.arrayFor(decl.datatype.sub!!.dt, false)
val splitDt = DataType.arrayFor(decl.datatype.sub!!, false)
val newDecl = VarDecl(
decl.type, decl.origin, splitDt, decl.zeropage, decl.splitwordarray, decl.arraysize, decl.name, emptyList(),
decl.value?.copy(), decl.sharedWithAsm, decl.alignment, false, decl.position

View File

@ -743,8 +743,8 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
if(type.isSplitWordArray) {
// ranges are never a split word array!
when(type.sub) {
is SubSignedWord -> type = DataType.arrayFor(BaseDataType.WORD, false)
is SubUnsignedWord -> type = DataType.arrayFor(BaseDataType.UWORD, false)
BaseDataType.WORD -> type = DataType.arrayFor(BaseDataType.WORD, false)
BaseDataType.UWORD -> type = DataType.arrayFor(BaseDataType.UWORD, false)
else -> { }
}
}

View File

@ -253,32 +253,27 @@ class TestMemory: FunSpec({
}
context("memsizer") {
withData(VMTarget(), AtariTarget(), C64Target(), PETTarget(), AtariTarget(), C128Target()) { target ->
shouldThrow<NoSuchElementException> {
target.memorySize(SubType.forDt(BaseDataType.UNDEFINED))
withData(VMTarget(), AtariTarget(), C64Target(), PETTarget(), AtariTarget(), C128Target(), Neo6502Target()) { target ->
shouldThrow<IllegalArgumentException> {
target.memorySize(BaseDataType.UNDEFINED)
}
shouldThrow<NoSuchElementException> {
target.memorySize(SubType.forDt(BaseDataType.LONG))
shouldThrow<IllegalArgumentException> {
target.memorySize(BaseDataType.LONG)
}
shouldThrow<NoSuchElementException> {
target.memorySize(SubType.forDt(BaseDataType.STR))
}
shouldThrow<NoSuchElementException> {
target.memorySize(SubType.forDt(BaseDataType.ARRAY))
}
shouldThrow<NoSuchElementException> {
target.memorySize(SubType.forDt(BaseDataType.ARRAY_SPLITW))
}
target.memorySize(SubType.forDt(BaseDataType.BOOL)) shouldBe 1
target.memorySize(SubType.forDt(BaseDataType.BYTE)) shouldBe 1
target.memorySize(SubType.forDt(BaseDataType.WORD)) shouldBe 2
target.memorySize(SubType.forDt(BaseDataType.FLOAT)) shouldBe target.machine.FLOAT_MEM_SIZE
target.memorySize(BaseDataType.BOOL) shouldBe 1
target.memorySize(BaseDataType.BYTE) shouldBe 1
target.memorySize(BaseDataType.WORD) shouldBe 2
target.memorySize(BaseDataType.FLOAT) shouldBe target.machine.FLOAT_MEM_SIZE
target.memorySize(DataType.forDt(BaseDataType.UNDEFINED), null) shouldBe 2
target.memorySize(DataType.forDt(BaseDataType.BOOL), null) shouldBe 1
target.memorySize(DataType.forDt(BaseDataType.WORD), null) shouldBe 2
target.memorySize(DataType.forDt(BaseDataType.FLOAT), null) shouldBe target.machine.FLOAT_MEM_SIZE
target.memorySize(DataType.forDt(BaseDataType.STR), null) shouldBe 2
target.memorySize(DataType.forDt(BaseDataType.STR), 50) shouldBe 50
target.memorySize(BaseDataType.STR) shouldBe 2
target.memorySize(BaseDataType.ARRAY) shouldBe 2
target.memorySize(BaseDataType.ARRAY_SPLITW) shouldBe 2
target.memorySize(DataType.arrayFor(BaseDataType.BOOL), 10) shouldBe 10
target.memorySize(DataType.arrayFor(BaseDataType.BYTE), 10) shouldBe 10

View File

@ -15,7 +15,6 @@ import prog8.code.ast.*
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.core.SubType
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget
@ -846,29 +845,7 @@ main {
errors.errors[2] shouldEndWith "cannot assign to 'void', perhaps a void function call was intended"
}
test("datatype subtype consistencies") {
shouldThrow<NoSuchElementException> {
SubType.forDt(BaseDataType.STR)
}
shouldThrow<NoSuchElementException> {
SubType.forDt(BaseDataType.UNDEFINED)
}
shouldThrow<NoSuchElementException> {
SubType.forDt(BaseDataType.ARRAY_SPLITW)
}
shouldThrow<NoSuchElementException> {
SubType.forDt(BaseDataType.ARRAY)
}
SubType.forDt(BaseDataType.FLOAT).dt shouldBe BaseDataType.FLOAT
}
test("datatype consistencies") {
shouldThrow<NoSuchElementException> {
DataType.forDt(BaseDataType.ARRAY)
}
shouldThrow<NoSuchElementException> {
DataType.forDt(BaseDataType.ARRAY_SPLITW)
}
DataType.forDt(BaseDataType.UNDEFINED).isUndefined shouldBe true
DataType.forDt(BaseDataType.LONG).isLong shouldBe true
DataType.forDt(BaseDataType.WORD).isWord shouldBe true
@ -876,6 +853,19 @@ main {
DataType.forDt(BaseDataType.BYTE).isByte shouldBe true
DataType.forDt(BaseDataType.UBYTE).isByte shouldBe true
DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true
DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD, false).isSplitWordArray shouldBe false
shouldThrow<NoSuchElementException> {
DataType.forDt(BaseDataType.ARRAY)
}
shouldThrow<NoSuchElementException> {
DataType.forDt(BaseDataType.ARRAY_SPLITW)
}
shouldThrow<NoSuchElementException> {
DataType.arrayFor(BaseDataType.ARRAY)
}
@ -885,12 +875,6 @@ main {
shouldThrow<NoSuchElementException> {
DataType.arrayFor(BaseDataType.UNDEFINED)
}
DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true
DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true
DataType.arrayFor(BaseDataType.UWORD, false).isSplitWordArray shouldBe false
}
test("array of strings becomes array of uword pointers") {

View File

@ -24,7 +24,7 @@ internal object DummyMemsizer : IMemSizer {
override fun memorySize(dt: DataType, numElements: Int?): Int {
if(dt.isArray || dt.isSplitWordArray) {
require(numElements!=null)
return when(dt.sub?.dt) {
return when(dt.sub) {
BaseDataType.BOOL, BaseDataType.BYTE, BaseDataType.UBYTE -> numElements
BaseDataType.UWORD, BaseDataType.WORD -> numElements*2
BaseDataType.FLOAT -> numElements*5
@ -38,8 +38,8 @@ internal object DummyMemsizer : IMemSizer {
}
}
override fun memorySize(dt: SubType): Int {
return memorySize(DataType.forDt(dt.dt), null)
override fun memorySize(dt: BaseDataType): Int {
return memorySize(DataType.forDt(dt), null)
}
}
@ -82,7 +82,7 @@ internal object DummyCompilationTarget : ICompilationTarget {
throw NotImplementedError("dummy")
}
override fun memorySize(dt: SubType): Int {
override fun memorySize(dt: BaseDataType): Int {
throw NotImplementedError("dummy")
}
}

View File

@ -385,6 +385,4 @@ fun defaultZero(dt: BaseDataType, position: Position) = when(dt) {
else -> throw FatalAstException("can only determine default zero value for a numeric type")
}
fun defaultZero(dt: SubType, position: Position) = defaultZero(dt.dt, position)
fun defaultZero(idt: InferredTypes.InferredType, position: Position) = defaultZero(idt.getOrUndef().base, position)

View File

@ -83,7 +83,7 @@ object InferredTypes {
type.isString -> InferredType.known(BaseDataType.STR)
type.isLong -> InferredType.known(BaseDataType.LONG)
type.isSplitWordArray -> {
when(type.sub?.dt) {
when(type.sub) {
BaseDataType.UWORD -> InferredType.known(DataType.arrayFor(BaseDataType.UWORD, true))
BaseDataType.WORD -> InferredType.known(DataType.arrayFor(BaseDataType.WORD, true))
BaseDataType.STR -> InferredType.known(DataType.arrayFor(BaseDataType.STR, true))
@ -91,7 +91,7 @@ object InferredTypes {
}
}
type.isArray -> {
InferredType.known(DataType.arrayFor(type.sub!!.dt, false))
InferredType.known(DataType.arrayFor(type.sub!!, false))
}
else -> throw IllegalArgumentException("invalid type")
}

View File

@ -285,8 +285,8 @@ class VarDecl(val type: VarDeclType,
if(arrayDt.isSplitWordArray) {
// autovars for array literals are NOT stored as a split word array!
when(arrayDt.sub) {
is SubSignedWord -> arrayDt = DataType.arrayFor(BaseDataType.WORD, false)
is SubUnsignedWord -> arrayDt = DataType.arrayFor(BaseDataType.UWORD, false)
BaseDataType.WORD -> arrayDt = DataType.arrayFor(BaseDataType.WORD, false)
BaseDataType.UWORD -> arrayDt = DataType.arrayFor(BaseDataType.UWORD, false)
else -> { }
}
}

View File

@ -1,6 +1,7 @@
TODO
====
- add paypal donation button as well?
- announce prog8 on the 6502.org site?
...
@ -9,6 +10,7 @@ TODO
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- Kotlin: can we use inline value classes in certain spots?
- 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
- Compiling Libraries: improve ability to create library files in prog8; for instance there's still stuff injected into the start of the start() routine AND there is separate setup logic going on before calling it.
@ -20,6 +22,7 @@ Future Things and Ideas
- [problematic due to using 64tass:] better support for building library programs, where unused .proc are NOT deleted from the assembly.
Perhaps replace all uses of .proc/.pend/.endproc by .block/.bend will fix that with a compiler flag?
But all library code written in asm uses .proc already..... (textual search/replace when writing the actual asm?)
Maybe propose a patch to 64tass itself that will treat .proc as .block ?
Once new codegen is written that is based on the IR, this point is mostly moot anyway as that will have its own dead code removal on the IR level.
- Allow normal subroutines to return multiple values as well (just as asmsubs already can)

View File

@ -1,31 +1,40 @@
%import textio
%import sprites
%import palette
%import math
%zeropage basicsafe
%option no_sysinit
main {
sub start() {
str input = iso:"the quick brown fox jumps over the lazy dog"
word[128] xpos
word[128] ypos
for cx16.r2L in 0 to 127 {
sprites.init(cx16.r2L, 0, 0, sprites.SIZE_8, sprites.SIZE_8, sprites.COLORS_16, 0)
xpos[cx16.r2L] = math.rndw() & 511 as word + 64
ypos[cx16.r2L] = math.rnd()
}
txt.print_uwhex(math.crc16(input, len(input)), true)
txt.nl()
repeat {
sys.waitvsync()
palette.set_color(6, $f00)
math.crc32(input, len(input))
sprites.pos_batch(0, 128, &xpos, &ypos)
txt.print_uwhex(cx16.r15, true)
txt.print_uwhex(cx16.r14, false)
txt.nl()
math.crc32_start()
for cx16.r0L in input
math.crc32_update(cx16.r0L)
uword hiw,low
hiw,low = math.crc32_end_result()
txt.print_uwhex(hiw, true)
txt.print_uwhex(low, false)
txt.nl()
palette.set_color(6, $0f0)
for cx16.r2L in 0 to 127 {
if cx16.r2L & 1 == 0 {
xpos[cx16.r2L] ++
if xpos[cx16.r2L] > 640
xpos[cx16.r2L] = 0
} else {
ypos[cx16.r2L] ++
if ypos[cx16.r2L] > 480
ypos[cx16.r2L] = 0
}
}
palette.set_color(6, $00f)
}
}
}

View File

@ -3,4 +3,4 @@ org.gradle.console=rich
org.gradle.parallel=true
org.gradle.daemon=true
kotlin.code.style=official
version=11.0
version=11.1-SNAPSHOT

View File

@ -18,7 +18,7 @@ fun DataType.irTypeString(length: Int?): String {
BaseDataType.FLOAT -> "float"
BaseDataType.STR -> "ubyte[$lengthStr]" // here string doesn't exist as a seperate datatype anymore
BaseDataType.ARRAY -> {
when(this.sub?.dt) {
when(this.sub) {
BaseDataType.UBYTE -> "ubyte[$lengthStr]"
BaseDataType.UWORD -> "uword[$lengthStr]"
BaseDataType.BYTE -> "byte[$lengthStr]"
@ -29,7 +29,7 @@ fun DataType.irTypeString(length: Int?): String {
}
}
BaseDataType.ARRAY_SPLITW -> {
when(this.sub?.dt) {
when(this.sub) {
BaseDataType.UWORD -> "uword[$lengthStr]" // should be 2 separate byte arrays by now really?
BaseDataType.WORD -> "word[$lengthStr]" // should be 2 separate byte arrays by now really?
else -> throw IllegalArgumentException("invalid sub type")