From edd3a2284893bd6361f46acc0f5911a16b22eef3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 2 Jan 2021 16:46:57 +0100 Subject: [PATCH] added strfind() --- compiler/res/prog8lib/prog8_funcs.asm | 38 +++++++++++++++++++ compiler/src/prog8/ast/base/Base.kt | 1 + .../c64/codegen/BuiltinFunctionsAsmGen.kt | 9 +++++ .../codegen/assignment/AssignmentAsmGen.kt | 17 ++++++++- .../src/prog8/functions/BuiltinFunctions.kt | 19 +++++----- docs/source/programming.rst | 4 ++ syntax-files/IDEA/Prog8.xml | 2 +- 7 files changed, 79 insertions(+), 11 deletions(-) diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 23dd25d6f..6018d2cea 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -1368,3 +1368,41 @@ func_strcopy_to_stack .proc dex rts .pend + + +func_strfind .proc + lda _arg_string + ldy _arg_string+1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy #0 +- lda (P8ZP_SCRATCH_W1),y + beq _notfound + cmp _arg_char + beq _found + iny + bne - +_notfound lda #0 + ldy #0 + rts +_found sty P8ZP_SCRATCH_B1 + lda P8ZP_SCRATCH_W1 + clc + adc P8ZP_SCRATCH_B1 + sta P8ZP_SCRATCH_W1 + bcc + + inc P8ZP_SCRATCH_W1+1 ++ ldy P8ZP_SCRATCH_W1+1 + rts + +_arg_string .word 0 +_arg_char .byte 0 + .pend + +func_strfind_stack .proc + jsr func_strfind + sta P8ESTACK_LO,x + sty P8ESTACK_HI,x + dex + rts + .pend diff --git a/compiler/src/prog8/ast/base/Base.kt b/compiler/src/prog8/ast/base/Base.kt index 126303275..1dcf810bd 100644 --- a/compiler/src/prog8/ast/base/Base.kt +++ b/compiler/src/prog8/ast/base/Base.kt @@ -130,6 +130,7 @@ val WordDatatypes = setOf(DataType.UWORD, DataType.WORD) val IntegerDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD) val NumericDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT) val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F) +val StringlyDatatypes = setOf(DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, DataType.UWORD) val IterableDatatypes = setOf( DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 7700fceb2..784c21d41 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -80,6 +80,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val "clear_irqd" -> asmgen.out(" cli") "set_irqd" -> asmgen.out(" sei") "strlen" -> funcStrlen(fcall, resultToStack) + "strfind" -> funcStrfind(fcall, func, resultToStack, sscope) "strcmp" -> funcStrcmp(fcall, func, resultToStack, sscope) "strcopy" -> { translateArguments(fcall.args, func, sscope) @@ -197,6 +198,14 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } } + private fun funcStrfind(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) { + translateArguments(fcall.args, func, scope) + if(resultToStack) + asmgen.out(" jsr prog8_lib.func_strfind_stack") + else + asmgen.out(" jsr prog8_lib.func_strfind") + } + private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) { translateArguments(fcall.args, func, scope) if(resultToStack) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 305ef6549..83e3c1bd5 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -198,7 +198,22 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen when(returntype.typeOrElse(DataType.STRUCT)) { in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY - DataType.STR -> throw AssemblyError("missing code for assign string from builtin func => copy string or assign string address") + DataType.STR -> { + when (assign.target.datatype) { + DataType.STR -> { + asmgen.out(""" + pha + lda #<${assign.target.asmVarname} + sta P8ZP_SCRATCH_W1 + lda #>${assign.target.asmVarname} + sta P8ZP_SCRATCH_W1+1 + pla + jsr prog8_lib.strcpy""") + } + DataType.UWORD -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) + else -> throw AssemblyError("str return value type mismatch with target") + } + } DataType.FLOAT -> { // float result from function sits in FAC1 assignFAC1float(assign.target) diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 49674d5ec..a38a1d2ce 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -160,22 +160,23 @@ private val functionSignatures: List = listOf( FParam("address", IterableDatatypes + DataType.UWORD), FParam("numwords", setOf(DataType.UWORD)), FParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null), - FSignature("strlen" , true, listOf(FParam("string", setOf(DataType.STR))), DataType.UBYTE, ::builtinStrlen), - FSignature("strcopy" , false, listOf(FParam("from", IterableDatatypes + DataType.UWORD), FParam("to", IterableDatatypes + DataType.UWORD)), DataType.UBYTE), + FSignature("strlen" , true, listOf(FParam("string", StringlyDatatypes)), DataType.UBYTE, ::builtinStrlen), + FSignature("strcopy" , false, listOf(FParam("from", StringlyDatatypes), FParam("to", StringlyDatatypes)), DataType.UBYTE), FSignature("substr" , false, listOf( - FParam("source", IterableDatatypes + DataType.UWORD), - FParam("target", IterableDatatypes + DataType.UWORD), + FParam("source", StringlyDatatypes), + FParam("target", StringlyDatatypes), FParam("start", setOf(DataType.UBYTE)), FParam("length", setOf(DataType.UBYTE))), null), FSignature("leftstr" , false, listOf( - FParam("source", IterableDatatypes + DataType.UWORD), - FParam("target", IterableDatatypes + DataType.UWORD), + FParam("source", StringlyDatatypes), + FParam("target", StringlyDatatypes), FParam("length", setOf(DataType.UBYTE))), null), FSignature("rightstr" , false, listOf( - FParam("source", IterableDatatypes + DataType.UWORD), - FParam("target", IterableDatatypes + DataType.UWORD), + FParam("source", StringlyDatatypes), + FParam("target", StringlyDatatypes), FParam("length", setOf(DataType.UBYTE))), null), - FSignature("strcmp" , false, listOf(FParam("s1", IterableDatatypes + DataType.UWORD), FParam("s2", IterableDatatypes + DataType.UWORD)), DataType.BYTE, null) + FSignature("strcmp" , true, listOf(FParam("s1", StringlyDatatypes), FParam("s2", StringlyDatatypes)), DataType.BYTE, null), + FSignature("strfind" , true, listOf(FParam("string", StringlyDatatypes), FParam("char", setOf(DataType.UBYTE))), DataType.STR, null) ) val BuiltinFunctions = functionSignatures.associateBy { it.name } diff --git a/docs/source/programming.rst b/docs/source/programming.rst index c2e06a4dc..c646dea90 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -833,6 +833,10 @@ strcopy(from, to) Often you don't have to call this explicitly and can just write ``string1 = string2`` but this function is useful if you're dealing with addresses for instance. +strfind(string, char) + Locates the first position of the given character in the string, returns the string starting + with this character or $0000 if the character is not found. + Miscellaneous ^^^^^^^^^^^^^ diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml index 93da5721e..d509826a3 100644 --- a/syntax-files/IDEA/Prog8.xml +++ b/syntax-files/IDEA/Prog8.xml @@ -14,7 +14,7 @@ - +