mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +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) {
|
||||
DataType.STR -> {
|
||||
// use subroutine
|
||||
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)
|
||||
asmgen.out(" pla")
|
||||
asmgen.out(" ldy #${numElements-1}")
|
||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||
return
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
throw AssemblyError("containment check of floats not supported")
|
||||
TODO("containment check of floats")
|
||||
}
|
||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||
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)
|
||||
asmgen.out(" pla")
|
||||
asmgen.out(" ldy #$numElements")
|
||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||
return
|
||||
}
|
||||
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||
assignExpressionToVariable(containment.element, "P8ZP_SCRATCH_W1", elementDt)
|
||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
|
||||
asmgen.out(" ldy #$numElements")
|
||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
||||
return
|
||||
}
|
||||
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.
|
||||
; 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.
|
||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||
%asm {{
|
||||
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
||||
ldy cx16.r0
|
||||
sty P8ZP_SCRATCH_W1
|
||||
ldy cx16.r0+1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy cx16.r1
|
||||
sty P8ZP_SCRATCH_W2
|
||||
ldy cx16.r1+1
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
tay
|
||||
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
||||
sta P8ZP_SCRATCH_W1
|
||||
stx P8ZP_SCRATCH_W1+1
|
||||
lda cx16.r1
|
||||
sta P8ZP_SCRATCH_W2
|
||||
lda cx16.r1+1
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
lda #0
|
||||
sta (P8ZP_SCRATCH_W2),y
|
||||
cpy #0
|
||||
@ -51,16 +48,16 @@ _loop dey
|
||||
; 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.
|
||||
; 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.
|
||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||
%asm {{
|
||||
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
|
||||
sta P8ZP_SCRATCH_B1
|
||||
lda cx16.r0
|
||||
ldy cx16.r0+1
|
||||
stx P8ZP_SCRATCH_B1
|
||||
sta cx16.r0
|
||||
sty cx16.r0+1
|
||||
jsr string.length
|
||||
tya
|
||||
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,
|
||||
; returns Carry set if found + index in A, or A=0 + Carry clear if not found.
|
||||
%asm {{
|
||||
; 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
|
||||
; need to copy the the cx16 virtual registers to zeropage to make this run on C64...
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
stx P8ZP_SCRATCH_B1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
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 {
|
||||
; Copy a string to another, overwriting that one.
|
||||
; Returns the length of the string that was copied.
|
||||
|
@ -65,6 +65,13 @@ string {
|
||||
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 {
|
||||
; Copy a string to another, overwriting that one.
|
||||
; 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
|
||||
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 -> {
|
||||
val constValues = (containment.iterable as RangeExpression).toConstantIntegerRange()
|
||||
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.
|
||||
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``
|
||||
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
|
||||
|
@ -1,66 +1,61 @@
|
||||
%import textio
|
||||
%import string
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; is optimizing this useful? : not a1 or not a2 -> not(a1 and a2) likewise for and.
|
||||
bool @shared a1 = true
|
||||
bool @shared a2
|
||||
bool @shared a
|
||||
bool @shared b
|
||||
str s = "?"
|
||||
s[0] = 's'
|
||||
txt.print(s)
|
||||
txt.nl()
|
||||
|
||||
; absorbption opt:
|
||||
; if a or (a and b)
|
||||
; cx16.r0 ++
|
||||
; if a or (b and a)
|
||||
; 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 ++
|
||||
if 's' in s {
|
||||
txt.print("ok1\n")
|
||||
} else {
|
||||
txt.print("fail1\n")
|
||||
}
|
||||
|
||||
bool @shared iteration_in_progress = false
|
||||
ubyte @shared num_bytes = 99
|
||||
void string.find(s, 's')
|
||||
if_cs {
|
||||
txt.print("ok2\n")
|
||||
} else {
|
||||
txt.print("fail2\n")
|
||||
}
|
||||
|
||||
if not iteration_in_progress or not num_bytes
|
||||
txt.print("yep1")
|
||||
else
|
||||
txt.print("nope1")
|
||||
if string.contains(s, 's') {
|
||||
txt.print("ok3\n")
|
||||
} else {
|
||||
txt.print("fail3\n")
|
||||
}
|
||||
|
||||
iteration_in_progress = true
|
||||
if not iteration_in_progress or not num_bytes
|
||||
txt.print("yep2")
|
||||
else
|
||||
txt.print("nope2")
|
||||
if 'q' in s {
|
||||
txt.print("ok1\n")
|
||||
} else {
|
||||
txt.print("fail1\n")
|
||||
}
|
||||
|
||||
;
|
||||
; if a1==0 and a2==0
|
||||
; cx16.r0++
|
||||
;
|
||||
; if (a1!=0 or a2!=0)==0
|
||||
; cx16.r0++
|
||||
;
|
||||
; if a1==0 or a2==0
|
||||
; cx16.r0++
|
||||
;
|
||||
; if (a1!=0 and a2!=0)==0
|
||||
; cx16.r0++
|
||||
void string.find(s, 'q')
|
||||
if_cs {
|
||||
txt.print("ok2\n")
|
||||
} else {
|
||||
txt.print("fail2\n")
|
||||
}
|
||||
|
||||
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…
Reference in New Issue
Block a user