From d14c61b160a45978b04df62a1ff12bbea2eda554 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 17 Mar 2024 23:18:33 +0100 Subject: [PATCH] added string.findstr(). string.find() returns 255 if not found. also fix string assignment bug for sub args. --- .../res/prog8lib/shared_string_functions.p8 | 40 ++++++++++ compiler/res/prog8lib/string.p8 | 25 +----- compiler/res/prog8lib/virtual/string.p8 | 24 +----- .../astprocessing/StatementReorderer.kt | 8 +- docs/source/syntaxreference.rst | 4 +- examples/test.p8 | 80 ++++++++++++++++--- gradle.properties | 2 +- 7 files changed, 122 insertions(+), 61 deletions(-) diff --git a/compiler/res/prog8lib/shared_string_functions.p8 b/compiler/res/prog8lib/shared_string_functions.p8 index d6ee81caa..28b1441ec 100644 --- a/compiler/res/prog8lib/shared_string_functions.p8 +++ b/compiler/res/prog8lib/shared_string_functions.p8 @@ -76,4 +76,44 @@ string { return s+cx16.r0L } + sub startswith(str st, str prefix) -> bool { + ubyte prefix_len = string.length(prefix) + ubyte str_len = string.length(st) + if prefix_len > str_len + return false + cx16.r9L = st[prefix_len] + st[prefix_len] = 0 + cx16.r9H = string.compare(st, prefix) as ubyte + st[prefix_len] = cx16.r9L + return cx16.r9H==0 + } + + sub endswith(str st, str suffix) -> bool { + ubyte suffix_len = string.length(suffix) + ubyte str_len = string.length(st) + if suffix_len > str_len + return false + return string.compare(st + str_len - suffix_len, suffix) == 0 + } + + sub findstr(str haystack, str needle) -> ubyte { + ; searches for needle in haystack. + ; returns index in haystack where it first occurs, and Carry set, + ; or if needle doesn't occur in haystack it returns Carry clear and 255 (an invalid index.) + cx16.r2L = string.length(haystack) + cx16.r3L = string.length(needle) + if cx16.r3L <= cx16.r2L { + cx16.r2L = cx16.r2L-cx16.r3L+1 + cx16.r3 = haystack + repeat cx16.r2L { + if string.startswith(cx16.r3, needle) { + sys.set_carry() + return cx16.r3-haystack as ubyte + } + cx16.r3++ + } + } + sys.clear_carry() + return 255 + } } diff --git a/compiler/res/prog8lib/string.p8 b/compiler/res/prog8lib/string.p8 index 01ede3844..4a6ab1367 100644 --- a/compiler/res/prog8lib/string.p8 +++ b/compiler/res/prog8lib/string.p8 @@ -129,7 +129,7 @@ _startloop dey asmsub find(uword string @AY, ubyte character @X) -> ubyte @A, bool @Pc { ; Locates the first position of the given character in the string, - ; returns Carry set if found + index in A, or A=0 + Carry clear if not found. + ; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index). %asm {{ ; need to copy the the cx16 virtual registers to zeropage to make this run on C64... sta P8ZP_SCRATCH_W1 @@ -142,7 +142,7 @@ _startloop dey beq _found iny bne - -_notfound lda #0 +_notfound lda #255 clc rts _found tya @@ -277,26 +277,6 @@ _done rts }} } - sub startswith(str st, str prefix) -> bool { - ubyte prefix_len = length(prefix) - ubyte str_len = length(st) - if prefix_len > str_len - return false - cx16.r9L = st[prefix_len] - st[prefix_len] = 0 - cx16.r9H = compare(st, prefix) as ubyte - st[prefix_len] = cx16.r9L - return cx16.r9H==0 - } - - sub endswith(str st, str suffix) -> bool { - ubyte suffix_len = length(suffix) - ubyte str_len = length(st) - if suffix_len > str_len - return false - return compare(st + str_len - suffix_len, suffix) == 0 - } - asmsub pattern_match(str string @AY, str pattern @R0) clobbers(Y) -> bool @A { %asm {{ ; pattern matching of a string. @@ -366,7 +346,6 @@ fail clc ; yes, no match found, return with c=0 }} } - asmsub hash(str string @R0) -> ubyte @A { ; experimental 8 bit hashing function. ; hash(-1)=179; clear carry; hash(i) = ROL hash(i-1) XOR string[i] diff --git a/compiler/res/prog8lib/virtual/string.p8 b/compiler/res/prog8lib/virtual/string.p8 index 5b73720db..531fb39cb 100644 --- a/compiler/res/prog8lib/virtual/string.p8 +++ b/compiler/res/prog8lib/virtual/string.p8 @@ -55,7 +55,7 @@ string { sub find(str st, ubyte character) -> ubyte { ; Locates the first position of the given character in the string, - ; returns Carry set if found + index in A, or Carry clear if not found. + ; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index). ubyte ix for ix in 0 to length(st)-1 { if st[ix]==character { @@ -64,7 +64,7 @@ string { } } sys.clear_carry() - return 0 + return 255 } sub contains(str st, ubyte character) -> bool { @@ -147,26 +147,6 @@ string { return char } - sub startswith(str st, str prefix) -> bool { - ubyte prefix_len = length(prefix) - ubyte str_len = length(st) - if prefix_len > str_len - return false - cx16.r9L = st[prefix_len] - st[prefix_len] = 0 - cx16.r9H = compare(st, prefix) as ubyte - st[prefix_len] = cx16.r9L - return cx16.r9H==0 - } - - sub endswith(str st, str suffix) -> bool { - ubyte suffix_len = length(suffix) - ubyte str_len = length(st) - if suffix_len > str_len - return false - return compare(st + str_len - suffix_len, suffix) == 0 - } - sub hash(str st) -> ubyte { ; experimental 8 bit hashing function. ; hash(-1)=179; hash(i) = ROL hash(i-1) XOR string[i] diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index e42a2e28c..43993e0fb 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -214,8 +214,12 @@ internal class StatementReorderer( } } - if(valueType.isString && (targetType istype DataType.STR || targetType istype DataType.ARRAY_B || targetType istype DataType.ARRAY_UB)) - return copyStringValue(assignment) + if(!assignment.isAugmentable) { + if (valueType.isString && (targetType istype DataType.STR || targetType istype DataType.ARRAY_B || targetType istype DataType.ARRAY_UB)) { + // replace string assignment by a call to stringcopy + return copyStringValue(assignment) + } + } return noModifications } diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index b89dea6d6..ece8a1a31 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -238,7 +238,6 @@ Directives Level: not at module scope. Declares that a piece of *assembly code* is inside the curly braces. This code will be copied as-is into the generated output assembly source file. - The assembler syntax used should be for the 3rd party cross assembler tool that Prog8 uses (64tass). Note that the start and end markers are both *double curly braces* to minimize the chance that the assembly code itself contains either of those. If it does contain a ``}}``, it will confuse the parser. @@ -247,6 +246,9 @@ Directives the assembly code. Sometimes you'll have to declare a variable in prog8 with `@shared` if it is only used in such assembly code. + .. note:: + 64tass syntax is required for the assembly code. As such, mnemonics need to be written in lowercase. + .. caution:: Avoid using single-letter symbols in included assembly code, as they could be confused with CPU registers. Also, note that all prog8 symbols are prefixed in assembly code, see :ref:`symbol-prefixing`. diff --git a/examples/test.p8 b/examples/test.p8 index 34c9f1da7..fb38e6ef2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,22 +1,78 @@ %import textio +%import string %zeropage basicsafe -%option no_sysinit main { sub start() { - ubyte[] ubarray = [11,22,33] - uword[] uwarray = [1111,2222,3333] - uword[] @split suwarray = [1111,2222,3333] - - ubarray[1] *= 10 - uwarray[1] *= 10 - suwarray[1] *= 10 - - txt.print_ub(ubarray[1]) + str name = "irmen@de@jong" + cx16.r0L = findstr(name, "de-") + if_cs { + txt.print("found1. error. ") + } else { + txt.print("not found1. ok ") + } + txt.print_ub(cx16.r0L) txt.nl() - txt.print_uw(uwarray[1]) txt.nl() - txt.print_uw(suwarray[1]) + cx16.r0L = findstr(name, "de@") + if_cs { + txt.print("found2 (6?). ") + } else { + txt.print("not found2. error ") + } + txt.print_ub(cx16.r0L) + txt.nl() + txt.nl() + cx16.r0L = findstr(name, "irmen@de@jong") + if_cs { + txt.print("found3 (0?). ") + } else { + txt.print("not found3. error ") + } + txt.print_ub(cx16.r0L) + txt.nl() + txt.nl() + cx16.r0L = findstr(name, "irmen@de@jong1") + if_cs { + txt.print("found4. error. ") + } else { + txt.print("not found4. ok ") + } + txt.print_ub(cx16.r0L) + txt.nl() + txt.nl() + cx16.r0L = findstr(name, "jong") + if_cs { + txt.print("found5 (9?). ") + } else { + txt.print("not found5. error ") + } + txt.print_ub(cx16.r0L) + txt.nl() txt.nl() } + + sub findstr(str haystack, str needle) -> ubyte { + ; searches for needle in haystack. + ; returns index in haystack where it first occurs, and Carry set, + ; or if needle doesn't occur in haystack it returns Carry clear and 255 (an invalid index.) + txt.print_uwhex(haystack, true) + txt.spc() + txt.print(haystack) + txt.nl() + cx16.r2L = string.length(haystack) + cx16.r3L = string.length(needle) + if cx16.r3L <= cx16.r2L { + cx16.r2L = cx16.r2L-cx16.r3L+1 + repeat cx16.r2L { + if string.startswith(haystack, needle) { + sys.set_carry() + return 13 as ubyte + } + haystack++ + } + } + sys.clear_carry() + return 255 + } } diff --git a/gradle.properties b/gradle.properties index dc6fb83c2..11bdc8a45 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,4 +5,4 @@ org.gradle.daemon=true kotlin.code.style=official javaVersion=11 kotlinVersion=1.9.22 -version=10.2 +version=10.3-SNAPSHOT