diff --git a/docs/text.md b/docs/text.md index ecf3224..96d0f7d 100644 --- a/docs/text.md +++ b/docs/text.md @@ -1125,6 +1125,31 @@ replacement text. --- +## `reversed` + +**Description:** +Return a text that has the grapheme clusters in reverse order. + +**Signature:** +```tomo +func reversed(text: Text -> Text) +``` + +**Parameters:** + +- `text`: The text to reverse. + +**Returns:** +A reversed version of the text. + +**Example:** +```tomo +>> "Abc":reversed() += "cbA" +``` + +--- + ## `slice` **Description:** diff --git a/environment.c b/environment.c index 1af173b..3153a89 100644 --- a/environment.c +++ b/environment.c @@ -415,6 +415,7 @@ env_t *new_compilation_unit(CORD libname) {"repeat", "Text$repeat", "func(text:Text, count:Int -> Text)"}, {"replace", "Text$replace", "func(text:Text, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes -> Text)"}, {"replace_all", "Text$replace_all", "func(text:Text, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes -> Text)"}, + {"reversed", "Text$reversed", "func(text:Text -> Text)"}, {"slice", "Text$slice", "func(text:Text, from=1, to=-1 -> Text)"}, {"split", "Text$split", "func(text:Text, pattern=$Pattern'' -> [Text])"}, {"starts_with", "Text$starts_with", "func(text,prefix:Text -> Bool)"}, diff --git a/stdlib/text.c b/stdlib/text.c index 384bf7a..57a98e8 100644 --- a/stdlib/text.c +++ b/stdlib/text.c @@ -572,6 +572,47 @@ public Text_t Text$to(Text_t text, Int_t last) return Text$slice(text, I_small(1), last); } +public Text_t Text$reversed(Text_t text) +{ + switch (text.tag) { + case TEXT_SHORT_ASCII: { + Text_t ret = text; + for (int64_t i = 0; i < text.length; i++) + ret.short_ascii[text.length-1-i] = text.short_ascii[i]; + return ret; + } + case TEXT_ASCII: { + Text_t ret = text; + ret.ascii = GC_MALLOC_ATOMIC(sizeof(uint8_t[text.length])); + for (int64_t i = 0; i < text.length; i++) + ((char*)ret.ascii)[text.length-1-i] = text.ascii[i]; + return ret; + } + case TEXT_SHORT_GRAPHEMES: { + Text_t ret = text; + for (int64_t i = 0; i < text.length; i++) + ret.short_graphemes[text.length-1-i] = text.short_graphemes[i]; + return ret; + } + case TEXT_GRAPHEMES: { + Text_t ret = text; + ret.graphemes = GC_MALLOC_ATOMIC(sizeof(int32_t[text.length])); + for (int64_t i = 0; i < text.length; i++) + ((int32_t*)ret.graphemes)[text.length-1-i] = text.graphemes[i]; + return ret; + } + case TEXT_SUBTEXT: { + Text_t ret = text; + int64_t n = num_subtexts(text); + ret.subtexts = GC_MALLOC(sizeof(Text_t*[n])); + for (int64_t i = 0; i < n; i++) + ret.subtexts[n-1-i] = Text$reversed(text.subtexts[i]); + return ret; + } + default: errx(1, "Invalid tag"); + } +} + public Text_t Text$cluster(Text_t text, Int_t index_int) { int64_t index = Int_to_Int64(index_int, false); diff --git a/stdlib/text.h b/stdlib/text.h index 6e2ac41..f7785dd 100644 --- a/stdlib/text.h +++ b/stdlib/text.h @@ -31,6 +31,7 @@ Text_t Text$_concat(int n, Text_t items[n]); Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int); Text_t Text$from(Text_t text, Int_t first); Text_t Text$to(Text_t text, Int_t last); +Text_t Text$reversed(Text_t text); Text_t Text$cluster(Text_t text, Int_t index_int); OptionalText_t Text$from_str(const char *str); OptionalText_t Text$from_strn(const char *str, size_t len); diff --git a/test/text.tm b/test/text.tm index 26fd4c6..a95764d 100644 --- a/test/text.tm +++ b/test/text.tm @@ -292,6 +292,9 @@ func main(): >> "abcde":starts_with("cd") = no + >> ("hello" ++ " " ++ "Amélie"):reversed() + = "eilémA olleh" : Text + do: !! Testing concatenation-stability: >> ab := Text.from_codepoint_names(["LATIN SMALL LETTER E", "COMBINING VERTICAL LINE BELOW"])!