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 { compression {
%option no_symbol_prefixing, ignore_unused
sub encode_rle_outfunc(uword data, uword size, uword output_function, bool is_last_block) { 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. ; -- Compress the given data block using ByteRun1 aka PackBits RLE encoding.
; output_function = address of a routine that gets a byte arg in A, ; 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) { fun checkType(target: AssignTarget, value: Expression, augmentable: Boolean) {
val targetDt = target.inferType(program) val targetDt = target.inferType(program)
val valueDt = value.inferType(program) val valueDt = value.inferType(program)
if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) { if(valueDt.isKnown && !(valueDt isAssignableTo targetDt) && !targetDt.isIterable) {
if(targetDt.isIterable) if(!(valueDt issimpletype BaseDataType.STR && targetDt issimpletype BaseDataType.UWORD)) {
errors.err("cannot assign value to string or array", value.position)
else if(!(valueDt.isString && targetDt issimpletype BaseDataType.UWORD)) {
if(targetDt.isUnknown) { if(targetDt.isUnknown) {
if(target.identifier?.targetStatement(program)!=null) if(target.identifier?.targetStatement(program)!=null)
errors.err("target datatype is unknown", target.position) 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) { else if(targetDatatype.isBool && !sourceDatatype.isBool) {
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position) 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 { else {
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position) 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) val targetType = assignment.target.inferType(program)
if(targetType.isArray && valueType.isArray) { if(targetType.isArray && valueType.isArray) {
if (assignment.value is ArrayLiteral) { checkCopyArrayValue(assignment)
errors.err("cannot assign array literal here, use separate assignment per element", assignment.position)
} else {
return copyArrayValue(assignment)
}
} }
if(!assignment.isAugmentable) { 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 // replace string assignment by a call to stringcopy
return copyStringValue(assignment) return copyStringValue(assignment)
} }
@ -250,18 +246,22 @@ internal class StatementReorderer(
return noModifications return noModifications
} }
private fun copyArrayValue(assign: Assignment): List<IAstModification> { private fun checkCopyArrayValue(assign: Assignment) {
val identifier = assign.target.identifier!! val identifier = assign.target.identifier!!
val targetVar = identifier.targetVarDecl(program)!! val targetVar = identifier.targetVarDecl(program)!!
if(targetVar.arraysize==null) { if(targetVar.arraysize==null) {
errors.err("array has no defined size", assign.position) 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) { if(assign.value !is IdentifierReference) {
errors.err("invalid array value to assign to other array", assign.value.position) errors.err("invalid array value to assign to other array", assign.value.position)
return noModifications return
} }
val sourceIdent = assign.value as IdentifierReference val sourceIdent = assign.value as IdentifierReference
val sourceVar = sourceIdent.targetVarDecl(program)!! val sourceVar = sourceIdent.targetVarDecl(program)!!
@ -276,7 +276,6 @@ internal class StatementReorderer(
errors.err("element size mismatch", assign.position) errors.err("element size mismatch", assign.position)
} }
} }
return noModifications
} }
private fun copyStringValue(assign: Assignment): List<IAstModification> { 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 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 (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. always have to be constants. Here are some examples of arrays::
Here are some examples of arrays::
byte[10] array ; array of 10 bytes, initially set to 0 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[] 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) 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[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) 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:: .. note::
Right now, the array should be small enough to be indexable by a single byte index. 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`` can't be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
for instance. for instance.
It's possible to assign an array to another array; this will overwrite all elements in the target
It's possible to assign a new array to another array, this will overwrite all elements in the original array with those in the source array. The number and types of elements have to match for this to work!
array with those in the value array. The number and types of elements have to match.
For large arrays this is a slow operation because every element is copied over. It should probably be avoided. 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, 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 Augmented assignments (such as ``aa += xx``) are also available, but these are just shorthands
for normal assignments (``aa = aa + xx``). 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 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. for the three individual assignments with the same value 42.

View File

@ -1,6 +1,8 @@
TODO TODO
==== ====
Put palette fade to white / black in.
Regenerate skeleton doc files. Regenerate skeleton doc files.
Improve register load order in subroutine call args assignments: 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 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 - 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? - 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?) - 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 textio
%import string
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit
main { main {
sub start() { 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
} }
} }