mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
added string.contains().
fixed string and array containment check for length 1.
This commit is contained in:
parent
f2daa17b92
commit
334e6dca28
@ -1898,33 +1898,29 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
when(dt) {
|
when(dt) {
|
||||||
DataType.STR -> {
|
DataType.STR -> {
|
||||||
// use subroutine
|
|
||||||
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
|
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
|
||||||
asmgen.out(" pha")
|
asmgen.out(" pha") // need to keep the scratch var safe so we have to do it in this order
|
||||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position,"P8ZP_SCRATCH_W1"), symbolName, null, null)
|
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position,"P8ZP_SCRATCH_W1"), symbolName, null, null)
|
||||||
asmgen.out(" pla")
|
asmgen.out(" pla")
|
||||||
asmgen.out(" ldy #${numElements-1}")
|
asmgen.out(" ldy #${numElements-1}")
|
||||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
throw AssemblyError("containment check of floats not supported")
|
TODO("containment check of floats")
|
||||||
}
|
}
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
|
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
|
||||||
asmgen.out(" pha")
|
asmgen.out(" pha") // need to keep the scratch var safe so we have to do it in this order
|
||||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
|
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
|
||||||
asmgen.out(" pla")
|
asmgen.out(" pla")
|
||||||
asmgen.out(" ldy #$numElements")
|
asmgen.out(" ldy #$numElements")
|
||||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||||
assignExpressionToVariable(containment.element, "P8ZP_SCRATCH_W1", elementDt)
|
assignExpressionToVariable(containment.element, "P8ZP_SCRATCH_W1", elementDt)
|
||||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
|
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
|
||||||
asmgen.out(" ldy #$numElements")
|
asmgen.out(" ldy #$numElements")
|
||||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid dt")
|
else -> throw AssemblyError("invalid dt")
|
||||||
}
|
}
|
||||||
|
@ -20,22 +20,19 @@ string {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub left(uword source @R0, ubyte length @A, uword target @R1) clobbers(A, Y) {
|
asmsub left(uword source @AX, ubyte length @Y, uword target @R1) clobbers(A, Y) {
|
||||||
; Copies the left side of the source string of the given length to target string.
|
; Copies the left side of the source string of the given length to target string.
|
||||||
; It is assumed the target string buffer is large enough to contain the result.
|
; It is assumed the target string buffer is large enough to contain the result.
|
||||||
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||||
%asm {{
|
%asm {{
|
||||||
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
||||||
ldy cx16.r0
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1
|
stx P8ZP_SCRATCH_W1+1
|
||||||
ldy cx16.r0+1
|
lda cx16.r1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sta P8ZP_SCRATCH_W2
|
||||||
ldy cx16.r1
|
lda cx16.r1+1
|
||||||
sty P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2+1
|
||||||
ldy cx16.r1+1
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
tay
|
|
||||||
lda #0
|
lda #0
|
||||||
sta (P8ZP_SCRATCH_W2),y
|
sta (P8ZP_SCRATCH_W2),y
|
||||||
cpy #0
|
cpy #0
|
||||||
@ -51,16 +48,16 @@ _loop dey
|
|||||||
; asmgen.out(" jsr prog8_lib.func_leftstr")
|
; asmgen.out(" jsr prog8_lib.func_leftstr")
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub right(uword source @R0, ubyte length @A, uword target @R1) clobbers(A,Y) {
|
asmsub right(uword source @AY, ubyte length @X, uword target @R1) clobbers(A,Y) {
|
||||||
; Copies the right side of the source string of the given length to target string.
|
; Copies the right side of the source string of the given length to target string.
|
||||||
; It is assumed the target string buffer is large enough to contain the result.
|
; It is assumed the target string buffer is large enough to contain the result.
|
||||||
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||||
%asm {{
|
%asm {{
|
||||||
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
||||||
sta P8ZP_SCRATCH_B1
|
stx P8ZP_SCRATCH_B1
|
||||||
lda cx16.r0
|
sta cx16.r0
|
||||||
ldy cx16.r0+1
|
sty cx16.r0+1
|
||||||
jsr string.length
|
jsr string.length
|
||||||
tya
|
tya
|
||||||
sec
|
sec
|
||||||
@ -128,16 +125,14 @@ _startloop dey
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub find(uword string @R0, ubyte character @A) -> ubyte @A, bool @Pc {
|
asmsub find(uword string @AY, ubyte character @X) -> ubyte @A, bool @Pc {
|
||||||
; Locates the first position of the given character in the string,
|
; 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 A=0 + Carry clear if not found.
|
||||||
%asm {{
|
%asm {{
|
||||||
; need to copy the the cx16 virtual registers to zeropage to make this run on C64...
|
; need to copy the the cx16 virtual registers to zeropage to make this run on C64...
|
||||||
sta P8ZP_SCRATCH_B1
|
|
||||||
lda cx16.r0
|
|
||||||
ldy cx16.r0+1
|
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
stx P8ZP_SCRATCH_B1
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda (P8ZP_SCRATCH_W1),y
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
beq _notfound
|
beq _notfound
|
||||||
@ -154,6 +149,13 @@ _found tya
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asmsub contains(uword string @AY, ubyte character @X) -> bool @Pc {
|
||||||
|
; Just return true/false if the character is in the given string or not.
|
||||||
|
%asm {{
|
||||||
|
jmp find
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
asmsub copy(uword source @R0, uword target @AY) clobbers(A) -> ubyte @Y {
|
asmsub copy(uword source @R0, uword target @AY) clobbers(A) -> ubyte @Y {
|
||||||
; Copy a string to another, overwriting that one.
|
; Copy a string to another, overwriting that one.
|
||||||
; Returns the length of the string that was copied.
|
; Returns the length of the string that was copied.
|
||||||
|
@ -65,6 +65,13 @@ string {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub contains(str st, ubyte character) -> bool {
|
||||||
|
void find(st, character)
|
||||||
|
if_cs
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
sub copy(str source, str target) -> ubyte {
|
sub copy(str source, str target) -> ubyte {
|
||||||
; Copy a string to another, overwriting that one.
|
; Copy a string to another, overwriting that one.
|
||||||
; Returns the length of the string that was copied.
|
; Returns the length of the string that was copied.
|
||||||
|
@ -225,19 +225,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
|||||||
val array = (containment.iterable as ArrayLiteral).value
|
val array = (containment.iterable as ArrayLiteral).value
|
||||||
return checkArray(array)
|
return checkArray(array)
|
||||||
}
|
}
|
||||||
is IdentifierReference -> {
|
|
||||||
val variable = (containment.iterable as IdentifierReference).targetVarDecl(program)
|
|
||||||
when(variable?.datatype) {
|
|
||||||
DataType.STR -> {
|
|
||||||
val stringVal = (variable.value as StringLiteral)
|
|
||||||
return checkString(stringVal)
|
|
||||||
}
|
|
||||||
in ArrayDatatypes -> {
|
|
||||||
return checkArray(variable!!)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is RangeExpression -> {
|
is RangeExpression -> {
|
||||||
val constValues = (containment.iterable as RangeExpression).toConstantIntegerRange()
|
val constValues = (containment.iterable as RangeExpression).toConstantIntegerRange()
|
||||||
if(constValues!=null) {
|
if(constValues!=null) {
|
||||||
|
@ -258,6 +258,10 @@ Provides string manipulation routines.
|
|||||||
Simply call this and only act on the carry status with ``if_cc`` for example.
|
Simply call this and only act on the carry status with ``if_cc`` for example.
|
||||||
Much like the difference between len(str) and length(str).
|
Much like the difference between len(str) and length(str).
|
||||||
|
|
||||||
|
``contains (string, char) -> bool``
|
||||||
|
Just returns true if the character is in the given string, or false if it's not.
|
||||||
|
For string literals, you can use a containment check expression instead: ``char in "hello world"``.
|
||||||
|
|
||||||
``compare (string1, string2) -> ubyte result``
|
``compare (string1, string2) -> ubyte result``
|
||||||
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
||||||
Note that you can also directly compare strings and string values with each other
|
Note that you can also directly compare strings and string values with each other
|
||||||
|
@ -1,66 +1,61 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import string
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
; is optimizing this useful? : not a1 or not a2 -> not(a1 and a2) likewise for and.
|
str s = "?"
|
||||||
bool @shared a1 = true
|
s[0] = 's'
|
||||||
bool @shared a2
|
txt.print(s)
|
||||||
bool @shared a
|
txt.nl()
|
||||||
bool @shared b
|
|
||||||
|
|
||||||
; absorbption opt:
|
if 's' in s {
|
||||||
; if a or (a and b)
|
txt.print("ok1\n")
|
||||||
; cx16.r0 ++
|
} else {
|
||||||
; if a or (b and a)
|
txt.print("fail1\n")
|
||||||
; cx16.r0 ++
|
}
|
||||||
; if a and (a or b)
|
|
||||||
; cx16.r0 ++
|
|
||||||
; if a and (b or a)
|
|
||||||
; cx16.r0 ++
|
|
||||||
;
|
|
||||||
; ; no opt:
|
|
||||||
; if a and (b and a)
|
|
||||||
; cx16.r0 ++
|
|
||||||
; if a or (b or a)
|
|
||||||
; cx16.r0 ++
|
|
||||||
|
|
||||||
bool @shared iteration_in_progress = false
|
void string.find(s, 's')
|
||||||
ubyte @shared num_bytes = 99
|
if_cs {
|
||||||
|
txt.print("ok2\n")
|
||||||
|
} else {
|
||||||
|
txt.print("fail2\n")
|
||||||
|
}
|
||||||
|
|
||||||
if not iteration_in_progress or not num_bytes
|
if string.contains(s, 's') {
|
||||||
txt.print("yep1")
|
txt.print("ok3\n")
|
||||||
else
|
} else {
|
||||||
txt.print("nope1")
|
txt.print("fail3\n")
|
||||||
|
}
|
||||||
|
|
||||||
iteration_in_progress = true
|
if 'q' in s {
|
||||||
if not iteration_in_progress or not num_bytes
|
txt.print("ok1\n")
|
||||||
txt.print("yep2")
|
} else {
|
||||||
else
|
txt.print("fail1\n")
|
||||||
txt.print("nope2")
|
}
|
||||||
|
|
||||||
;
|
void string.find(s, 'q')
|
||||||
; if a1==0 and a2==0
|
if_cs {
|
||||||
; cx16.r0++
|
txt.print("ok2\n")
|
||||||
;
|
} else {
|
||||||
; if (a1!=0 or a2!=0)==0
|
txt.print("fail2\n")
|
||||||
; cx16.r0++
|
}
|
||||||
;
|
|
||||||
; if a1==0 or a2==0
|
|
||||||
; cx16.r0++
|
|
||||||
;
|
|
||||||
; if (a1!=0 and a2!=0)==0
|
|
||||||
; cx16.r0++
|
|
||||||
|
|
||||||
|
if string.contains(s, 'q') {
|
||||||
|
txt.print("ok3\n")
|
||||||
|
} else {
|
||||||
|
txt.print("fail3\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
str buffer="?" * 20
|
||||||
|
str name = "irmen de jong"
|
||||||
|
string.left(name, 5, buffer)
|
||||||
|
txt.print(buffer)
|
||||||
|
txt.nl()
|
||||||
|
string.right(name, 4, buffer)
|
||||||
|
txt.print(buffer)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
; if not a1 or not a2
|
|
||||||
; cx16.r0++
|
|
||||||
; if not (a1 and a2)
|
|
||||||
; cx16.r0++
|
|
||||||
; if not a1 and not a2
|
|
||||||
; cx16.r0++
|
|
||||||
; if not (a1 or a2)
|
|
||||||
; cx16.r0++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user