Merge branch 'master' into next_compositetypes

# Conflicts:
#	compiler/src/prog8/compiler/astprocessing/AstChecker.kt
#	compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt
#	examples/test.p8
This commit is contained in:
Irmen de Jong 2024-10-09 00:56:45 +02:00
commit d217d4ab01
6 changed files with 49 additions and 26 deletions

View File

@ -2,6 +2,8 @@
compression {
%option no_symbol_prefixing, ignore_unused
sub encode_rle_outfunc(uword data, uword size, uword output_function, bool is_last_block) {
; -- Compress the given data block using ByteRun1 aka PackBits RLE encoding.
; output_function = address of a routine that gets a byte arg in A,

View File

@ -551,10 +551,8 @@ internal class AstChecker(private val program: Program,
fun checkType(target: AssignTarget, value: Expression, augmentable: Boolean) {
val targetDt = target.inferType(program)
val valueDt = value.inferType(program)
if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) {
if(targetDt.isIterable)
errors.err("cannot assign value to string or array", value.position)
else if(!(valueDt.isString && targetDt issimpletype BaseDataType.UWORD)) {
if(valueDt.isKnown && !(valueDt isAssignableTo targetDt) && !targetDt.isIterable) {
if(!(valueDt issimpletype BaseDataType.STR && targetDt issimpletype BaseDataType.UWORD)) {
if(targetDt.isUnknown) {
if(target.identifier?.targetStatement(program)!=null)
errors.err("target datatype is unknown", target.position)
@ -1843,6 +1841,12 @@ internal class AstChecker(private val program: Program,
else if(targetDatatype.isBool && !sourceDatatype.isBool) {
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
}
else if(targetDatatype.isString) {
if(sourceDatatype.isUnsignedWord)
errors.err("can't assign UWORD to STR. If the source is a string and you actually want to overwrite the target string, use an explicit string.copy(src,tgt) instead.", position)
else
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
}
else {
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
}

View File

@ -213,15 +213,11 @@ internal class StatementReorderer(
val targetType = assignment.target.inferType(program)
if(targetType.isArray && valueType.isArray) {
if (assignment.value is ArrayLiteral) {
errors.err("cannot assign array literal here, use separate assignment per element", assignment.position)
} else {
return copyArrayValue(assignment)
}
checkCopyArrayValue(assignment)
}
if(!assignment.isAugmentable) {
if (valueType.isString && (targetType issimpletype BaseDataType.STR || targetType.isByteArray)) {
if (valueType issimpletype BaseDataType.STR && targetType issimpletype BaseDataType.STR) {
// replace string assignment by a call to stringcopy
return copyStringValue(assignment)
}
@ -250,18 +246,22 @@ internal class StatementReorderer(
return noModifications
}
private fun copyArrayValue(assign: Assignment): List<IAstModification> {
private fun checkCopyArrayValue(assign: Assignment) {
val identifier = assign.target.identifier!!
val targetVar = identifier.targetVarDecl(program)!!
if(targetVar.arraysize==null) {
errors.err("array has no defined size", assign.position)
return noModifications
return
}
if(assign.value is ArrayLiteral) {
return // invalid assignment of literals will be reported elsewhere
}
if(assign.value !is IdentifierReference) {
errors.err("invalid array value to assign to other array", assign.value.position)
return noModifications
return
}
val sourceIdent = assign.value as IdentifierReference
val sourceVar = sourceIdent.targetVarDecl(program)!!
@ -276,7 +276,6 @@ internal class StatementReorderer(
errors.err("element size mismatch", assign.position)
}
}
return noModifications
}
private fun copyStringValue(assign: Assignment): List<IAstModification> {

View File

@ -286,8 +286,7 @@ Arrays
^^^^^^
Array types are also supported. They can be formed from a list of booleans, bytes, words, floats, or addresses of other variables
(such as explicit address-of expressions, strings, or other array variables) - values in an array literal
always have to be constants. Putting variables inside an array has to be done on a value-by-value basis.
Here are some examples of arrays::
always have to be constants. Here are some examples of arrays::
byte[10] array ; array of 10 bytes, initially set to 0
byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value
@ -300,6 +299,7 @@ Here are some examples of arrays::
value = array[3] ; the fourth value in the array (index is 0-based)
char = string[4] ; the fifth character (=byte) in the string
char = string[-2] ; the second-to-last character in the string (Python-style indexing from the end)
flags = [false, true] ; reset all flags in the array
.. note::
Right now, the array should be small enough to be indexable by a single byte index.
@ -312,9 +312,8 @@ Note that the various keywords for the data type and variable type (``byte``, ``
can't be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
for instance.
It's possible to assign a new array to another array, this will overwrite all elements in the original
array with those in the value array. The number and types of elements have to match.
It's possible to assign an array to another array; this will overwrite all elements in the target
array with those in the source array. The number and types of elements have to match for this to work!
For large arrays this is a slow operation because every element is copied over. It should probably be avoided.
Using the ``in`` operator you can easily check if a value is present in an array,
@ -650,10 +649,6 @@ Assignment statements assign a single value to a target variable or memory locat
Augmented assignments (such as ``aa += xx``) are also available, but these are just shorthands
for normal assignments (``aa = aa + xx``).
Only variables of type byte, word and float can be assigned a new value.
It's not possible to set a new value to string or array variables etc, because they get allocated
a fixed amount of memory which will not change. (You *can* change the value of elements in a string or array though).
It is possible to "chain" assignments: ``x = y = z = 42``, this is just a shorthand
for the three individual assignments with the same value 42.

View File

@ -1,6 +1,8 @@
TODO
====
Put palette fade to white / black in.
Regenerate skeleton doc files.
Improve register load order in subroutine call args assignments:
@ -12,6 +14,7 @@ Maybe this routine can be made more intelligent. See usesOtherRegistersWhileEva
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- The string assignment footgun should be removed in favor of just calling string.copy explicitly. Get rid of sys.internal_stringcopy asm routine. Fix docs too.
- 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?
- Don't add "random" rts to %asm blocks but instead give a warning about it? (but this breaks existing behavior that others already depend on... command line switch? block directive?)

View File

@ -1,10 +1,30 @@
%import textio
%import string
%zeropage basicsafe
%option no_sysinit
main {
sub start() {
txt.print("hello")
str name1 = "irmen"
str name2 = "other"
bool[2] flags = [true, false]
txt.print(name1)
txt.nl()
name1 = name2
txt.print(name1)
txt.nl()
flags = [false, true]
ubyte[10] array
ubyte[10] array2
void string.copy(name2, name1)
array = array2
name2 = "zzz"
array = [1,2,3,4,5,6,7,8,9,10]
;; array = cx16.r0
;; array = name1
;; name1 = array
;; name1 = cx16.r0
}
}