mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
tweak DataType class and memsizer related to subtypes/elementtypes
This commit is contained in:
parent
126d4c69e6
commit
2727a4dcb3
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 -> { }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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") {
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
@ -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")
|
||||
}
|
||||
|
@ -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 -> { }
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user