From db3e2320e4d7085f0841bc94afaacf08ec6ed435 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 12:43:49 -0700 Subject: [PATCH 1/5] add isUpper string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 ++++++++++ src/vm/datatypes/strings.c | 24 ++++++++++++++++++++++++ tests/strings/isUpper.du | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tests/strings/isUpper.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index bc4520af..5b8eebcc 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -276,4 +276,14 @@ Returns a new string with the original string repeated the given number of times ```cs "ba"+"na".repeat(2); // banana "la".repeat(2) + " land"; // lala land +``` + +### string.isUpper() -> Boolean + +Returns a boolean indicating that the given string is an upper case letter. + +```cs +"D".isUpper(); // true +"d".isUpper() // false +"Dog".isUpper() // false ``` \ No newline at end of file diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 297ca010..18edf6c0 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -598,6 +598,29 @@ static Value repeatString(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(takeString(vm, temp, tempLen - 1)); } +static Value isUpperString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "isUpper() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + bool ret = false; + + if (strlen(string) > 1) { + return ret; + } + + char s = string[0]; + + if (s >= 'A' && s <= 'Z') { + ret = true; + } + + return ret; +} + void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "len", lenString); defineNative(vm, &vm->stringMethods, "toNumber", toNumberString); @@ -618,5 +641,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "toBool", boolNative); // Defined in util defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); + defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); } diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du new file mode 100644 index 00000000..74bc673c --- /dev/null +++ b/tests/strings/isUpper.du @@ -0,0 +1,18 @@ +/** + * isUpper.du + * + * Testing the str.isUpper() method + * + * .isUpper() returns a boolean indicating that the given string is + * an upper case letter. + */ +from UnitTest import UnitTest; + +class TestStringIsUpper < UnitTest { + testStringIsUpper() { + this.assertTruthy("D".isUpper()); + this.assertFalsey("Maple".isUpper()); + } +} + +TestStringIsUpper().run(); \ No newline at end of file From c08c4a9756aad352fc1bca24662554e37b92749b Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 12:56:24 -0700 Subject: [PATCH 2/5] add toLower string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 ++++++++++ src/vm/datatypes/strings.c | 26 +++++++++++++++++++++++--- tests/strings/import.du | 2 ++ tests/strings/isLower.du | 19 +++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/strings/isLower.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 5b8eebcc..cddff2ac 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -286,4 +286,14 @@ Returns a boolean indicating that the given string is an upper case letter. "D".isUpper(); // true "d".isUpper() // false "Dog".isUpper() // false +``` + +### string.isLower() -> Boolean + +Returns a boolean indicating that the given string is an lower case letter. + +```cs +"D".isLower(); // false +"d".isLower() // true +"Dog".isLower() // false ``` \ No newline at end of file diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 18edf6c0..f2453841 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -612,13 +612,32 @@ static Value isUpperString(DictuVM *vm, int argCount, Value *args) { return ret; } - char s = string[0]; + if (string[0] >= 'A' && string[0] <= 'Z') { + ret = true; + } + + return BOOL_VAL(ret); +} + +static Value isLowerString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "isLower() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + bool ret = false; + + if (strlen(string) > 1) { + return ret; + } - if (s >= 'A' && s <= 'Z') { + if (string[0] >= 'a' && string[0] <= 'z') { ret = true; } - return ret; + return BOOL_VAL(ret); } void declareStringMethods(DictuVM *vm) { @@ -642,5 +661,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); + defineNative(vm, &vm->stringMethods, "isLower", isLowerString); } diff --git a/tests/strings/import.du b/tests/strings/import.du index 624c70e2..045fc19a 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -26,3 +26,5 @@ import "toBool.du"; import "escapeCodes.du"; import "repeat.du"; import "title.du"; +import "isUpper.du"; +import "isLower.du"; diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du new file mode 100644 index 00000000..a3dc335a --- /dev/null +++ b/tests/strings/isLower.du @@ -0,0 +1,19 @@ +/** + * isLower.du + * + * Testing the str.isLower() method + * + * .isLower() returns a boolean indicating that the given string is + * an lower case letter. + */ +from UnitTest import UnitTest; + +class TestStringIsLower < UnitTest { + testStringIsLower() { + this.assertTruthy("d".isLower()); + this.assertFalsey("D".isLower()); + this.assertFalsey("Maple".isLower()); + } +} + +TestStringIsLower().run(); \ No newline at end of file From 0b96d02baeb91e878b6b7753bdf043a9bf4bf2e6 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 13:00:39 -0700 Subject: [PATCH 3/5] add newline chars Signed-off-by: Brian Downs --- tests/strings/isLower.du | 2 +- tests/strings/isUpper.du | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du index a3dc335a..d48afe8c 100644 --- a/tests/strings/isLower.du +++ b/tests/strings/isLower.du @@ -16,4 +16,4 @@ class TestStringIsLower < UnitTest { } } -TestStringIsLower().run(); \ No newline at end of file +TestStringIsLower().run(); diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du index 74bc673c..ab7c45c2 100644 --- a/tests/strings/isUpper.du +++ b/tests/strings/isUpper.du @@ -15,4 +15,4 @@ class TestStringIsUpper < UnitTest { } } -TestStringIsUpper().run(); \ No newline at end of file +TestStringIsUpper().run(); From 2d751741b6d2ebcbbe530680704a16191b5fd64a Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 18:39:26 -0700 Subject: [PATCH 4/5] added wordCount method Signed-off-by: Brian Downs --- docs/docs/strings.md | 13 ++++++++++++- src/vm/datatypes/strings.c | 27 +++++++++++++++++++++++++++ tests/strings/import.du | 1 + tests/strings/wordCount.du | 19 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/strings/wordCount.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index cddff2ac..9b4ada2d 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -296,4 +296,15 @@ Returns a boolean indicating that the given string is an lower case letter. "D".isLower(); // false "d".isLower() // true "Dog".isLower() // false -``` \ No newline at end of file +``` + +### string.wordCount() -> Number + +Returns the number of words in the given string. + +```cs +"".wordCount(); // 0 +"This".wordCount(); // 1 +"This is a sentence".wordCount(); // 4 +"This is an even longer sentence".wordCount(); // 6 +``` diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index f2453841..e3bafaee 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -545,6 +545,32 @@ static Value countString(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(count); } +static Value wordCountString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "count() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + int count = 0; + int len = strlen(string); + bool in = false; + + for (int i = 0; i < len; i++) { + if (isspace(string[i])) { + in = false; + } else if(isalpha(string[i])) { + if(!in) { + in = true; + count++; + } + } + } + + return NUMBER_VAL(count); +} + static Value titleString(DictuVM *vm, int argCount, Value *args) { if (argCount != 0) { runtimeError(vm, "title() takes no arguments (%d given)", argCount); @@ -657,6 +683,7 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "rightStrip", rightStripString); defineNative(vm, &vm->stringMethods, "strip", stripString); defineNative(vm, &vm->stringMethods, "count", countString); + defineNative(vm, &vm->stringMethods, "wordCount", wordCountString); defineNative(vm, &vm->stringMethods, "toBool", boolNative); // Defined in util defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); diff --git a/tests/strings/import.du b/tests/strings/import.du index 045fc19a..709f74fe 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -28,3 +28,4 @@ import "repeat.du"; import "title.du"; import "isUpper.du"; import "isLower.du"; +import "wordCount.du"; diff --git a/tests/strings/wordCount.du b/tests/strings/wordCount.du new file mode 100644 index 00000000..6f93cfde --- /dev/null +++ b/tests/strings/wordCount.du @@ -0,0 +1,19 @@ +/** + * wordCount.du + * + * Testing the str.wordCount() method + * + * .wordCount() returns the number of words in the given string. + */ +from UnitTest import UnitTest; + +class TestStringWordCount < UnitTest { + testStringWordCount() { + this.assertEquals("".wordCount(), 0); + this.assertEquals("This".wordCount(), 1); + this.assertEquals("This is a sentence".wordCount(), 4); + this.assertEquals("This is an even longer sentence".wordCount(), 6); + } +} + +TestStringWordCount().run(); From 56bfce0e5d3fe0806c2019511fe52ebcb7bded18 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 9 Jan 2024 14:19:40 -0700 Subject: [PATCH 5/5] refactor implementations Signed-off-by: Brian Downs --- docs/docs/strings.md | 6 ++++-- src/vm/datatypes/strings.c | 34 ++++++++++++++++++---------------- tests/strings/isLower.du | 2 ++ tests/strings/isUpper.du | 2 ++ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 9b4ada2d..8b8e6cf9 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -285,22 +285,24 @@ Returns a boolean indicating that the given string is an upper case letter. ```cs "D".isUpper(); // true "d".isUpper() // false +"G00D!".isUpper() // true "Dog".isUpper() // false ``` ### string.isLower() -> Boolean -Returns a boolean indicating that the given string is an lower case letter. +Returns a boolean indicating that the given string is an lower case letter. Empty strings are considered false. ```cs "D".isLower(); // false "d".isLower() // true +"g00d!".isLower() // true "Dog".isLower() // false ``` ### string.wordCount() -> Number -Returns the number of words in the given string. +Returns the number of words in the given string. Empty strings are considered false. ```cs "".wordCount(); // 0 diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index e3bafaee..929acdba 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -631,18 +631,19 @@ static Value isUpperString(DictuVM *vm, int argCount, Value *args) { } char *string = AS_CSTRING(args[0]); + int len = strlen(string); - bool ret = false; - - if (strlen(string) > 1) { - return ret; + if (len == 0) { + return BOOL_VAL(false); } - if (string[0] >= 'A' && string[0] <= 'Z') { - ret = true; + for (int i = 0; i < len; i++) { + if (!isupper(string[i]) && isalpha(string[i])) { + return BOOL_VAL(false); + } } - - return BOOL_VAL(ret); + + return BOOL_VAL(true); } static Value isLowerString(DictuVM *vm, int argCount, Value *args) { @@ -652,18 +653,19 @@ static Value isLowerString(DictuVM *vm, int argCount, Value *args) { } char *string = AS_CSTRING(args[0]); + int len = strlen(string); - bool ret = false; - - if (strlen(string) > 1) { - return ret; + if (len == 0) { + return BOOL_VAL(false); } - if (string[0] >= 'a' && string[0] <= 'z') { - ret = true; + for (int i = 0; i < len; i++) { + if (!islower(string[i]) && isalpha(string[i])) { + return BOOL_VAL(false); + } } - - return BOOL_VAL(ret); + + return BOOL_VAL(true); } void declareStringMethods(DictuVM *vm) { diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du index d48afe8c..5b94fd34 100644 --- a/tests/strings/isLower.du +++ b/tests/strings/isLower.du @@ -11,6 +11,8 @@ from UnitTest import UnitTest; class TestStringIsLower < UnitTest { testStringIsLower() { this.assertTruthy("d".isLower()); + this.assertTruthy("dog".isLower()); + this.assertTruthy("g00d!".isLower()); this.assertFalsey("D".isLower()); this.assertFalsey("Maple".isLower()); } diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du index ab7c45c2..f7d3294c 100644 --- a/tests/strings/isUpper.du +++ b/tests/strings/isUpper.du @@ -11,6 +11,8 @@ from UnitTest import UnitTest; class TestStringIsUpper < UnitTest { testStringIsUpper() { this.assertTruthy("D".isUpper()); + this.assertTruthy("DOG".isUpper()); + this.assertTruthy("G00D!".isUpper()); this.assertFalsey("Maple".isUpper()); } }