mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
allow creating string arrays. Fixed array index scaling for word arrays.
This commit is contained in:
parent
066233eee8
commit
af0fb88adf
@ -569,6 +569,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
|
||||
val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) }
|
||||
return when {
|
||||
DataType.FLOAT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_F)
|
||||
DataType.STR in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
|
||||
DataType.WORD in dts -> InferredTypes.InferredType.known(DataType.ARRAY_W)
|
||||
DataType.UWORD in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
|
||||
DataType.BYTE in dts -> InferredTypes.InferredType.known(DataType.ARRAY_B)
|
||||
|
@ -742,7 +742,15 @@ internal class AstChecker(private val program: Program,
|
||||
checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), null, arrayspec, array)
|
||||
}
|
||||
|
||||
if(!array.value.all { it is NumericLiteralValue || it is AddressOf || it is StringLiteralValue }) {
|
||||
fun isStringElement(e: Expression): Boolean {
|
||||
if(e is IdentifierReference) {
|
||||
val decl = e.targetVarDecl(program.namespace)!!
|
||||
return decl.datatype==DataType.STR
|
||||
}
|
||||
return e is StringLiteralValue
|
||||
}
|
||||
|
||||
if(!array.value.all { it is NumericLiteralValue || it is AddressOf || isStringElement(it) }) {
|
||||
// TODO for now, array literals have to consist of all compile time constant values...
|
||||
errors.err("array literal doesn't consist of only compile time constant values", array.position)
|
||||
}
|
||||
|
@ -26,6 +26,19 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private fun argTypeCompatible(argDt: DataType, paramDt: DataType): Boolean {
|
||||
if(argDt==paramDt)
|
||||
return true
|
||||
|
||||
// there are some exceptions that are considered compatible, such as STR <> UWORD
|
||||
if(argDt==DataType.STR && paramDt==DataType.UWORD ||
|
||||
argDt==DataType.UWORD && paramDt==DataType.STR)
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun checkTypes(call: IFunctionCall, scope: INameScope, program: Program): String? {
|
||||
val argtypes = call.args.map { it.inferType(program).typeOrElse(DataType.STRUCT) }
|
||||
val target = call.target.targetStatement(scope)
|
||||
@ -34,7 +47,7 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
||||
if(call.args.size != target.parameters.size)
|
||||
return "invalid number of arguments"
|
||||
val paramtypes = target.parameters.map { it.type }
|
||||
val mismatch = argtypes.zip(paramtypes).indexOfFirst { it.first != it.second}
|
||||
val mismatch = argtypes.zip(paramtypes).indexOfFirst { !argTypeCompatible(it.first, it.second) }
|
||||
if(mismatch>=0) {
|
||||
val actual = argtypes[mismatch].toString()
|
||||
val expected = paramtypes[mismatch].toString()
|
||||
@ -47,7 +60,8 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
||||
return "invalid number of arguments"
|
||||
val paramtypes = func.parameters.map { it.possibleDatatypes }
|
||||
for (x in argtypes.zip(paramtypes).withIndex()) {
|
||||
if (x.value.first !in x.value.second) {
|
||||
val anyCompatible = x.value.second.any { argTypeCompatible(x.value.first, it) }
|
||||
if (!anyCompatible) {
|
||||
val actual = x.value.first.toString()
|
||||
val expected = x.value.second.toString()
|
||||
return "argument ${x.index + 1} type mismatch, was: $actual expected: $expected"
|
||||
|
@ -214,8 +214,9 @@ open class VarDecl(val type: VarDeclType,
|
||||
DataType.UWORD -> DataType.ARRAY_UW
|
||||
DataType.WORD -> DataType.ARRAY_W
|
||||
DataType.FLOAT -> DataType.ARRAY_F
|
||||
DataType.STR -> DataType.ARRAY_UW // use memory address of the string instead
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
|
||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats/strings(ptrs)", position))
|
||||
DataType.ARRAY_UB
|
||||
}
|
||||
}
|
||||
|
@ -406,10 +406,17 @@ internal class AsmGen(private val program: Program,
|
||||
"$"+number.toString(16).padStart(2, '0')
|
||||
}
|
||||
DataType.ARRAY_UW -> array.map {
|
||||
if(it is NumericLiteralValue) {
|
||||
"$" + it.number.toInt().toString(16).padStart(4, '0')
|
||||
} else {
|
||||
(it as AddressOf).identifier.nameInSource.joinToString(".")
|
||||
when (it) {
|
||||
is NumericLiteralValue -> {
|
||||
"$" + it.number.toInt().toString(16).padStart(4, '0')
|
||||
}
|
||||
is AddressOf -> {
|
||||
it.identifier.nameInSource.joinToString(".")
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
it.nameInSource.joinToString(".")
|
||||
}
|
||||
else -> throw AssemblyError("weird array elt dt")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("invalid arraysize type")
|
||||
@ -711,10 +718,40 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
else {
|
||||
expressionsAsmGen.translateExpression(index)
|
||||
when(register) {
|
||||
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
||||
CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax")
|
||||
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
||||
when(elementDt) {
|
||||
in ByteDatatypes -> {
|
||||
when (register) {
|
||||
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
||||
CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax")
|
||||
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
||||
}
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
out("""
|
||||
inx
|
||||
lda P8ESTACK_LO,x
|
||||
asl a""")
|
||||
when (register) {
|
||||
CpuRegister.A -> {}
|
||||
CpuRegister.X -> out(" tax")
|
||||
CpuRegister.Y -> out(" tay")
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
require(DataType.FLOAT.memorySize()==5)
|
||||
out("""
|
||||
inx
|
||||
lda P8ESTACK_LO,x
|
||||
asl a
|
||||
asl a
|
||||
clc
|
||||
adc P8ESTACK_LO,x""")
|
||||
when (register) {
|
||||
CpuRegister.A -> {}
|
||||
CpuRegister.X -> out(" tax")
|
||||
CpuRegister.Y -> out(" tay")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,12 +236,13 @@ The largest 5-byte MFLPT float that can be stored is: **1.7014118345e+38** (ne
|
||||
|
||||
Arrays
|
||||
^^^^^^
|
||||
Array types are also supported. They can be made of bytes, words or floats::
|
||||
Array types are also supported. They can be made of bytes, words or floats, and strings::
|
||||
|
||||
byte[10] array ; array of 10 bytes, initially set to 0
|
||||
byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value
|
||||
byte[99] array = 255 ; initialize array with 99 times 255 [255, 255, 255, 255, ...]
|
||||
byte[] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
|
||||
str[] names = ["ally", "pete"] ; array of string pointers/addresses (equivalent to uword)
|
||||
|
||||
value = array[3] ; the fourth value in the array (index is 0-based)
|
||||
char = string[4] ; the fifth character (=byte) in the string
|
||||
@ -293,6 +294,12 @@ large enough to contain the new value::
|
||||
string1 = "new value"
|
||||
|
||||
|
||||
.. info::
|
||||
Strings and uwords (=memory address) can often be interchanged.
|
||||
An array of strings is actually an array of uwords where every element is the memory
|
||||
address of the string. You can pass a memory address to assembly functions
|
||||
that require a string as an argument.
|
||||
|
||||
.. caution::
|
||||
It's probably best to avoid changing strings after they've been created. This
|
||||
includes changing certain letters by index, or by assigning a new value, or by
|
||||
@ -718,7 +725,7 @@ sort(array)
|
||||
floating point values.
|
||||
|
||||
reverse(array)
|
||||
Reverse the values in the array (in-place). Supports all data types including floats.
|
||||
Reverse the values in the array (in-place).
|
||||
Can be used after sort() to sort an array in descending order.
|
||||
|
||||
len(x)
|
||||
|
@ -281,6 +281,7 @@ type identifier type storage size example var declara
|
||||
``word[]`` signed word array depends on value ``word[] myvar = [1, 2, 3, 4]``
|
||||
``uword[]`` unsigned word array depends on value ``uword[] myvar = [1, 2, 3, 4]``
|
||||
``float[]`` floating-point array depends on value ``float[] myvar = [1.1, 2.2, 3.3, 4.4]``
|
||||
``str[]`` array with string ptrs 2*x bytes + strs ``str[] names = ["ally", "pete"]``
|
||||
``str`` string (petscii) varies ``str myvar = "hello."``
|
||||
implicitly terminated by a 0-byte
|
||||
=============== ======================= ================= =========================================
|
||||
|
@ -4,8 +4,28 @@
|
||||
|
||||
|
||||
main {
|
||||
|
||||
str[] names = ["aap", "noot", "mies", "vuur"]
|
||||
uword[] names3 = ["aap", "noot", "mies", "vuur"]
|
||||
ubyte[] values = [11,22,33,44]
|
||||
|
||||
sub start() {
|
||||
txt.print("hello\n")
|
||||
uword s
|
||||
for s in names {
|
||||
txt.print(s)
|
||||
txt.chrout('\n')
|
||||
}
|
||||
txt.chrout('\n')
|
||||
|
||||
txt.print(names[2])
|
||||
txt.chrout('\n')
|
||||
txt.print(names[3])
|
||||
txt.chrout('\n')
|
||||
|
||||
repeat {
|
||||
txt.print(names3[rnd()&3]) ; TODO doesn't show correct names? only shows 'aap' and 'noot' works fine if idx in separate var
|
||||
txt.chrout(' ')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user