adding split array type

This commit is contained in:
Irmen de Jong 2023-05-22 20:31:28 +02:00
parent 0c94e377fc
commit 52a77db60f
16 changed files with 138 additions and 22 deletions

View File

@ -11,7 +11,9 @@ enum class DataType {
ARRAY_UB, // pass by reference
ARRAY_B, // pass by reference
ARRAY_UW, // pass by reference
ARRAY_UW_SPLIT, // pass by reference, lo/hi byte split
ARRAY_W, // pass by reference
ARRAY_W_SPLIT, // pass by reference, lo/hi byte split
ARRAY_F, // pass by reference
ARRAY_BOOL, // pass by reference
UNDEFINED;
@ -119,12 +121,13 @@ val IntegerDatatypesNoBool = arrayOf(DataType.UBYTE, DataType.BYTE, DataType.UWO
val NumericDatatypes = arrayOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT, DataType.BOOL)
val NumericDatatypesNoBool = arrayOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT)
val SignedDatatypes = arrayOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
val ArrayDatatypes = arrayOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F, DataType.ARRAY_BOOL)
val ArrayDatatypes = arrayOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_UW_SPLIT, DataType.ARRAY_W, DataType.ARRAY_W_SPLIT, DataType.ARRAY_F, DataType.ARRAY_BOOL)
val StringlyDatatypes = arrayOf(DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, DataType.UWORD)
val IterableDatatypes = arrayOf(
DataType.STR,
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.ARRAY_UW_SPLIT, DataType.ARRAY_W_SPLIT,
DataType.ARRAY_F, DataType.ARRAY_BOOL
)
val PassByValueDatatypes = NumericDatatypes
@ -135,6 +138,8 @@ val ArrayToElementTypes = mapOf(
DataType.ARRAY_UB to DataType.UBYTE,
DataType.ARRAY_W to DataType.WORD,
DataType.ARRAY_UW to DataType.UWORD,
DataType.ARRAY_W_SPLIT to DataType.WORD,
DataType.ARRAY_UW_SPLIT to DataType.UWORD,
DataType.ARRAY_F to DataType.FLOAT,
DataType.ARRAY_BOOL to DataType.BOOL
)

View File

@ -449,6 +449,14 @@ $loopLabel sty $indexVar
}
asmgen.out(endLabel)
}
DataType.ARRAY_UW_SPLIT -> {
asmgen.out("; TODO iterate over split uword array")
// TODO("iterate over split uword array")
}
DataType.ARRAY_W_SPLIT -> {
asmgen.out("; TODO iterate over split word array")
// TODO("iterate over split word array")
}
DataType.ARRAY_F -> {
throw AssemblyError("for loop with floating point variables is not supported")
}

View File

@ -627,6 +627,14 @@ internal class ProgramAndVarsGen(
asmgen.out(" .sint " + chunk.joinToString())
}
}
DataType.ARRAY_UW_SPLIT -> {
val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros)
// TODO("gen split uword array $data")
}
DataType.ARRAY_W_SPLIT -> {
val data = makeArrayFillDataSigned(dt, value, orNumberOfZeros)
// TODO("gen split word array $data")
}
DataType.ARRAY_F -> {
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
val floatFills = array.map {
@ -686,7 +694,7 @@ internal class ProgramAndVarsGen(
val number = it.number!!.toInt()
"$"+number.toString(16).padStart(2, '0')
}
DataType.ARRAY_UW -> array.map {
DataType.ARRAY_UW, DataType.ARRAY_UW_SPLIT -> array.map {
if(it.number!=null) {
"$" + it.number!!.toInt().toString(16).padStart(4, '0')
}
@ -718,11 +726,11 @@ internal class ProgramAndVarsGen(
else
"-$$hexnum"
}
DataType.ARRAY_UW -> array.map {
DataType.ARRAY_UW, DataType.ARRAY_UW_SPLIT -> array.map {
val number = it.number!!.toInt()
"$" + number.toString(16).padStart(4, '0')
}
DataType.ARRAY_W -> array.map {
DataType.ARRAY_W, DataType.ARRAY_W_SPLIT -> array.map {
val number = it.number!!.toInt()
val hexnum = number.absoluteValue.toString(16).padStart(4, '0')
if(number>=0)

View File

@ -165,7 +165,8 @@ internal class AstChecker(private val program: Program,
}
DataType.UWORD -> {
if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.UWORD && iterableDt != DataType.STR &&
iterableDt != DataType.ARRAY_UB && iterableDt!= DataType.ARRAY_UW)
iterableDt != DataType.ARRAY_UB && iterableDt != DataType.ARRAY_UW &&
iterableDt != DataType.ARRAY_UW_SPLIT)
errors.err("uword loop variable can only loop over unsigned bytes, words or strings", forLoop.position)
checkUnsignedLoopDownto0(forLoop.iterable as? RangeExpression)
@ -176,7 +177,8 @@ internal class AstChecker(private val program: Program,
}
DataType.WORD -> {
if(iterableDt!= DataType.BYTE && iterableDt!= DataType.WORD &&
iterableDt != DataType.ARRAY_B && iterableDt!= DataType.ARRAY_W)
iterableDt != DataType.ARRAY_B && iterableDt!= DataType.ARRAY_W &&
iterableDt != DataType.ARRAY_W_SPLIT)
errors.err("word loop variable can only loop over bytes or words", forLoop.position)
}
DataType.FLOAT -> {
@ -629,6 +631,9 @@ internal class AstChecker(private val program: Program,
DataType.ARRAY_W, DataType.ARRAY_UW ->
if(arraySize > 128)
err("word array length must be 1-128")
DataType.ARRAY_W_SPLIT, DataType.ARRAY_UW_SPLIT ->
if(arraySize > 256)
err("split word array length must be 1-256")
DataType.ARRAY_F ->
if(arraySize > 51)
err("float array length must be 1-51")
@ -1443,6 +1448,10 @@ internal class AstChecker(private val program: Program,
}
return err("invalid word array initialization value ${value.type}, expected $targetDt")
}
DataType.ARRAY_UW_SPLIT, DataType.ARRAY_W_SPLIT -> {
return true
TODO("check split array type")
}
DataType.ARRAY_F -> {
// value may be either a single float, or a float arraysize
if(value.type istype targetDt) {

View File

@ -30,7 +30,7 @@ internal class BoolRemover(val program: Program) : AstWalker() {
newvalue = NumericLiteral(DataType.UBYTE, 1.0, newvalue.position)
}
val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, decl.arraysize, decl.name,
newvalue, decl.isArray, decl.sharedWithAsm, decl.position)
newvalue, decl.isArray, decl.sharedWithAsm, decl.splitArray, decl.position)
return listOf(IAstModification.ReplaceNode(decl, ubyteDecl, parent))
}
@ -47,7 +47,7 @@ internal class BoolRemover(val program: Program) : AstWalker() {
newarray = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_UB), convertedArray, decl.position)
}
val ubyteArrayDecl = VarDecl(decl.type, decl.origin, DataType.ARRAY_UB, decl.zeropage, decl.arraysize, decl.name,
newarray, true, decl.sharedWithAsm, decl.position)
newarray, true, decl.sharedWithAsm, decl.splitArray, decl.position)
return listOf(IAstModification.ReplaceNode(decl, ubyteArrayDecl, parent))
}

View File

@ -162,6 +162,7 @@ internal class StatementReorderer(val program: Program,
null,
false,
it.sharedWithAsm,
it.splitArray,
it.position
)
IAstModification.ReplaceNode(it, newvar, subroutine)

View File

@ -40,7 +40,7 @@ fun Program.getTempVar(dt: DataType, altNames: Boolean=false): Pair<List<String>
// add new temp variable to the ast directly (we can do this here because we're not iterating inside those container blocks)
val decl = VarDecl(
VarDeclType.VAR, VarDeclOrigin.AUTOGENERATED, dt, ZeropageWish.DONTCARE,
null, tmpvarName[1], null, isArray = false, sharedWithAsm = false, position = Position.DUMMY
null, tmpvarName[1], null, isArray = false, sharedWithAsm = false, splitArray = false, position = Position.DUMMY
)
block.statements.add(decl)
decl.linkParents(block)

View File

@ -85,7 +85,7 @@ class Program(val name: String,
val varName = "string_${internedStringsBlock.statements.size}"
val decl = VarDecl(
VarDeclType.VAR, VarDeclOrigin.STRINGLITERAL, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, varName, string,
isArray = false, sharedWithAsm = false, position = string.position
isArray = false, sharedWithAsm = false, splitArray = false, position = string.position
)
internedStringsBlock.statements.add(decl)
decl.linkParents(internedStringsBlock)

View File

@ -615,7 +615,6 @@ private fun Prog8ANTLRParser.VardeclContext.toAst(type: VarDeclType, value: Expr
options.ZEROPAGE().isNotEmpty() -> ZeropageWish.PREFER_ZEROPAGE
else -> ZeropageWish.DONTCARE
}
val shared = options.SHARED().isNotEmpty()
return VarDecl(
type, VarDeclOrigin.USERCODE,
datatype()?.toAst() ?: DataType.UNDEFINED,
@ -624,7 +623,8 @@ private fun Prog8ANTLRParser.VardeclContext.toAst(type: VarDeclType, value: Expr
varname.text,
value,
ARRAYSIG() != null || arrayindex() != null,
shared,
options.SHARED().isNotEmpty(),
options.SPLIT().isNotEmpty(),
toPosition()
)
}

View File

@ -73,7 +73,9 @@ object InferredTypes {
DataType.ARRAY_UB to InferredType.known(DataType.ARRAY_UB),
DataType.ARRAY_B to InferredType.known(DataType.ARRAY_B),
DataType.ARRAY_UW to InferredType.known(DataType.ARRAY_UW),
DataType.ARRAY_UW_SPLIT to InferredType.known(DataType.ARRAY_UW_SPLIT),
DataType.ARRAY_W to InferredType.known(DataType.ARRAY_W),
DataType.ARRAY_W_SPLIT to InferredType.known(DataType.ARRAY_W_SPLIT),
DataType.ARRAY_F to InferredType.known(DataType.ARRAY_F),
DataType.ARRAY_BOOL to InferredType.known(DataType.ARRAY_BOOL)
)

View File

@ -197,6 +197,7 @@ class VarDecl(val type: VarDeclType,
var value: Expression?,
val isArray: Boolean,
val sharedWithAsm: Boolean,
val splitArray: Boolean,
override val position: Position) : Statement(), INamedStatement {
override lateinit var parent: Node
var allowInitializeWithZero = true
@ -210,6 +211,7 @@ class VarDecl(val type: VarDeclType,
return VarDecl(VarDeclType.VAR, VarDeclOrigin.SUBROUTINEPARAM, param.type, ZeropageWish.DONTCARE, null, param.name, null,
isArray = false,
sharedWithAsm = false,
splitArray = false,
position = param.position
)
}
@ -220,12 +222,15 @@ class VarDecl(val type: VarDeclType,
val declaredType = ArrayToElementTypes.getValue(arrayDt)
val arraysize = ArrayIndex.forArray(array)
return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
isArray = true, sharedWithAsm = false, position = array.position)
isArray = true, sharedWithAsm = false, splitArray = false, position = array.position)
}
}
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
val datatype =
val datatype: DataType
init {
val dt =
if (!isArray) declaredDatatype
else when (declaredDatatype) {
DataType.UBYTE -> DataType.ARRAY_UB
@ -241,6 +246,18 @@ class VarDecl(val type: VarDeclType,
}
}
datatype = if(splitArray) {
when(dt) {
DataType.ARRAY_UW -> DataType.ARRAY_UW_SPLIT
DataType.ARRAY_W -> DataType.ARRAY_W_SPLIT
else -> {
datatypeErrors.add(SyntaxError("split can only be used on word arrays", position))
DataType.UNDEFINED
}
}
} else dt
}
override fun linkParents(parent: Node) {
this.parent = parent
arraysize?.linkParents(this)
@ -267,14 +284,14 @@ class VarDecl(val type: VarDeclType,
override fun copy(): VarDecl {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), name, value?.copy(),
isArray, sharedWithAsm, position)
isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero
return copy
}
fun renamed(newName: String): VarDecl {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize, newName, value,
isArray, sharedWithAsm, position)
isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero
return copy
}

View File

@ -5,12 +5,47 @@
main {
sub start() {
ubyte[] array = [ $00, $11, $22, $33, $44, $55, $66, $77, $88, $99, $aa, $bb]
uword[] @split split_uwords = [12345, 60000, 4096]
word[] @split split_words = [-12345, -2222, 22222]
uword[256] @split @shared split2
word[256] @split @shared split3
ubyte x = 2
ubyte y = 3
txt.print_uwhex(mkword(array[9], array[8]), true)
txt.print_uwhex(mkword(array[x*y+y], array[y*x+x]), true)
print_arrays()
sub print_arrays() {
for cx16.r0 in split_uwords {
txt.print_uw(cx16.r0)
txt.spc()
}
txt.nl()
for cx16.r0s in split_words {
txt.print_w(cx16.r0s)
txt.spc()
}
txt.nl()
}
ubyte idx
for idx in 0 to 2 {
cx16.r0 = split_uwords[idx]
cx16.r1s = split_words[idx]
txt.print_uw(cx16.r0)
txt.spc()
txt.print_w(cx16.r1s)
txt.nl()
}
split_uwords[1] = 9999
split_words[1] = -9999
print_arrays()
split_uwords[1]++
split_words[1]--
print_arrays()
}
}

View File

@ -488,6 +488,8 @@ class IRFileReader {
"uword" -> DataType.ARRAY_UW
"float" -> DataType.ARRAY_F
"bool" -> DataType.ARRAY_B
"uword_split" -> DataType.ARRAY_UW_SPLIT
"word_split" -> DataType.ARRAY_W_SPLIT
else -> throw IRParseException("invalid dt $type")
}
} else {

View File

@ -10,10 +10,13 @@ fun getTypeString(dt : DataType): String = when(dt) {
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[]"
DataType.ARRAY_B -> "byte[]"
DataType.ARRAY_UW -> "uword[]"
DataType.ARRAY_UW_SPLIT -> "uword_split[]"
DataType.ARRAY_W -> "word[]"
DataType.ARRAY_W_SPLIT -> "word_split[]"
DataType.ARRAY_F -> "float[]"
else -> throw InternalCompilerException("weird dt")
}
@ -24,10 +27,13 @@ fun getTypeString(memvar: StMemVar): String = when(memvar.dt) {
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${memvar.length}]"
DataType.ARRAY_B -> "byte[${memvar.length}]"
DataType.ARRAY_UW -> "uword[${memvar.length}]"
DataType.ARRAY_UW_SPLIT -> "uword_split[${memvar.length}]"
DataType.ARRAY_W -> "word[${memvar.length}]"
DataType.ARRAY_W_SPLIT -> "word_split[${memvar.length}]"
DataType.ARRAY_F -> "float[${memvar.length}]"
else -> throw InternalCompilerException("weird dt")
}
@ -38,10 +44,13 @@ fun getTypeString(variable : StStaticVariable): String = when(variable.dt) {
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${variable.length}]"
DataType.ARRAY_B -> "byte[${variable.length}]"
DataType.ARRAY_UW -> "uword[${variable.length}]"
DataType.ARRAY_UW_SPLIT -> "uword_split[${variable.length}]"
DataType.ARRAY_W -> "word[${variable.length}]"
DataType.ARRAY_W_SPLIT -> "word_split[${variable.length}]"
DataType.ARRAY_F -> "float[${variable.length}]"
else -> throw InternalCompilerException("weird dt")
}

View File

@ -53,6 +53,8 @@ ZEROPAGEREQUIRE : '@requirezp' ;
SHARED : '@shared' ;
SPLIT: '@split' ;
ARRAYSIG :
'[]'
;
@ -130,7 +132,7 @@ directivearg : stringliteral | identifier | integerliteral ;
vardecl: datatype (arrayindex | ARRAYSIG)? decloptions varname=identifier ;
decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE)* ;
decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | SPLIT)* ;
varinitializer : vardecl '=' expression ;

View File

@ -223,6 +223,12 @@ class VmProgramLoader {
memory.setFloat(addr, 0.0f)
addr += program.options.compTarget.machine.FLOAT_MEM_SIZE
}
DataType.ARRAY_UW_SPLIT, DataType.ARRAY_W_SPLIT -> {
// lo bytes come after the hi bytes
memory.setUB(addr, 0u)
memory.setUB(addr+variable.length!!, 0u)
addr++
}
else -> throw IRParseException("invalid dt")
}
}
@ -274,6 +280,12 @@ class VmProgramLoader {
addr+=2
}
}
DataType.ARRAY_UW_SPLIT -> {
TODO("$it")
}
DataType.ARRAY_W_SPLIT -> {
TODO("$it")
}
DataType.ARRAY_F -> {
repeat(variable.length!!) {
memory.setFloat(addr, value.toFloat())
@ -315,6 +327,12 @@ class VmProgramLoader {
addr+=2
}
}
DataType.ARRAY_UW_SPLIT -> {
TODO("$it")
}
DataType.ARRAY_W_SPLIT -> {
TODO("$it")
}
DataType.ARRAY_F -> {
for(elt in it) {
memory.setFloat(addr, elt.number!!.toFloat())