aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/integers.c15
-rw-r--r--builtins/integers.h7
-rw-r--r--builtins/text.c36
-rw-r--r--builtins/text.h1
-rw-r--r--docs/text.md26
-rw-r--r--environment.c1
-rw-r--r--test/text.tm3
7 files changed, 81 insertions, 8 deletions
diff --git a/builtins/integers.c b/builtins/integers.c
index bf55d0ae..d9361cf4 100644
--- a/builtins/integers.c
+++ b/builtins/integers.c
@@ -92,7 +92,7 @@ public Text_t Int$format(Int_t i, Int_t digits_int)
}
public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
- if (Int$compare(&i, (Int_t[1]){I_small(0)}, &$Int) < 0)
+ if (Int$is_negative(i))
return Text$concat(Text("-"), Int$hex(Int$negative(i), digits_int, uppercase, prefix));
int64_t digits = Int_to_Int64(digits_int, false);
@@ -119,8 +119,7 @@ public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
}
public Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) {
- Int_t zero = I_small(0);
- if (Int$compare(&i, &zero, &$Int) < 0)
+ if (Int$is_negative(i))
return Text$concat(Text("-"), Int$octal(Int$negative(i), digits_int, prefix));
int64_t digits = Int_to_Int64(digits_int, false);
@@ -317,7 +316,7 @@ public Int_t Int$sqrt(Int_t i)
}
public Int_t Int$random(Int_t min, Int_t max) {
- int32_t cmp = Int$compare(&min, &max, &$Int);
+ int32_t cmp = Int$compare_value(min, max);
if (cmp > 0) {
Text_t min_text = Int$as_text(&min, false, &$Int), max_text = Int$as_text(&max, false, &$Int);
fail("Random minimum value (%k) is larger than the maximum value (%k)",
@@ -342,7 +341,7 @@ public Int_t Int$random(Int_t min, Int_t max) {
}
public Range_t Int$to(Int_t from, Int_t to) {
- return (Range_t){from, to, Int$compare(&to, &from, &$Int) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}};
+ return (Range_t){from, to, Int$compare_value(to, from) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}};
}
public Int_t Int$from_str(const char *str, bool *success) {
@@ -369,7 +368,7 @@ public bool Int$is_prime(Int_t x, Int_t reps)
{
mpz_t p;
mpz_init_set_int(p, x);
- if (Int$compare(&reps, (Int_t[1]){I_small(9999)}, &$Int) > 0)
+ if (Int$compare_value(reps, I(9999)) > 0)
fail("Number of prime-test repetitions should not be above 9999");
int reps_int = Int_to_Int32(reps, false);
return (mpz_probab_prime_p(p, reps_int) != 0);
@@ -464,11 +463,11 @@ public const TypeInfo $Int = {
bool parsed_int = false; \
Int_t full_int = Int$from_text(text, &parsed_int); \
if (!parsed_int && success) *success = false; \
- if (Int$compare(&full_int, (Int_t[1]){I(min_val)}, &$Int) < 0) { \
+ if (Int$compare_value(full_int, I(min_val)) < 0) { \
if (success) *success = false; \
return min_val; \
} \
- if (Int$compare(&full_int, (Int_t[1]){I(max_val)}, &$Int) > 0) { \
+ if (Int$compare_value(full_int, I(max_val)) > 0) { \
if (success) *success = false; \
return max_val; \
} \
diff --git a/builtins/integers.h b/builtins/integers.h
index e24b7869..4ff862fc 100644
--- a/builtins/integers.h
+++ b/builtins/integers.h
@@ -257,6 +257,13 @@ static inline Int_t Int$negative(Int_t x)
return Int$slow_negative(x);
}
+static inline bool Int$is_negative(Int_t x)
+{
+ if (__builtin_expect((x.small & 1), 1))
+ return x.small < 0;
+ return Int$compare_value(x, I_small(0)) < 0;
+}
+
// Conversion functions:
static inline Int_t Int64_to_Int(int64_t i)
diff --git a/builtins/text.c b/builtins/text.c
index 97b50a40..b3fe25eb 100644
--- a/builtins/text.c
+++ b/builtins/text.c
@@ -268,6 +268,42 @@ public Text_t Text$_concat(int n, Text_t items[n])
return ret;
}
+public Text_t Text$repeat(Text_t text, Int_t count)
+{
+ if (text.length == 0 || Int$is_negative(count))
+ return Text("");
+
+ Int_t result_len = Int$times(count, I(text.length));
+ if (Int$compare_value(result_len, I(1l<<40)) > 0)
+ fail("Text repeating would produce too big of an result!");
+
+ int64_t count64 = Int_to_Int64(count, false);
+ if (text.tag == TEXT_SUBTEXT) {
+ int64_t subtexts = num_subtexts(text);
+ Text_t ret = {
+ .length=text.length * count64,
+ .tag=TEXT_SUBTEXT,
+ .subtexts=GC_MALLOC(sizeof(Text_t[subtexts * count64])),
+ };
+ for (int64_t c = 0; c < count64; c++) {
+ for (int64_t i = 0; i < subtexts; i++) {
+ if (text.subtexts[i].length > 0)
+ ret.subtexts[c*subtexts + i] = text.subtexts[i];
+ }
+ }
+ return ret;
+ } else {
+ Text_t ret = {
+ .length=text.length * count64,
+ .tag=TEXT_SUBTEXT,
+ .subtexts=GC_MALLOC(sizeof(Text_t[count64])),
+ };
+ for (int64_t i = 0; i < count64; i++)
+ ret.subtexts[i] = text;
+ return ret;
+ }
+}
+
public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
{
int64_t first = Int_to_Int64(first_int, false);
diff --git a/builtins/text.h b/builtins/text.h
index c93c6266..747f82a0 100644
--- a/builtins/text.h
+++ b/builtins/text.h
@@ -52,6 +52,7 @@ Text_t Text$from_bytes(array_t bytes);
array_t Text$lines(Text_t text);
Text_t Text$join(Text_t glue, array_t pieces);
Text_t Text$map(Text_t text, Pattern_t pattern, closure_t fn);
+Text_t Text$repeat(Text_t text, Int_t count);
extern const TypeInfo $Text;
diff --git a/docs/text.md b/docs/text.md
index 7039043f..3849f840 100644
--- a/docs/text.md
+++ b/docs/text.md
@@ -895,6 +895,32 @@ The text formatted as a quoted string.
---
+## `repeat`
+
+**Description:**
+Repeat some text multiple times.
+
+**Usage:**
+```tomo
+repeat(text: Text, count:Int) -> Text
+```
+
+**Parameters:**
+
+- `text`: The text to repeat.
+- `count`: The number of times to repeat it. (Negative numbers are equivalent to zero).
+
+**Returns:**
+The text repeated the given number of times.
+
+**Example:**
+```tomo
+>> "Abc":repeat(3)
+= "AbcAbcAbc"
+```
+
+---
+
## `replace`
**Description:**
diff --git a/environment.c b/environment.c
index 2c1a3f70..21cd04f7 100644
--- a/environment.c
+++ b/environment.c
@@ -259,6 +259,7 @@ env_t *new_compilation_unit(CORD *libname)
{"map", "Text$map", "func(text:Text, pattern:Pattern, fn:func(text:Text)->Text)->Text"},
{"matches", "Text$matches", "func(text:Text, pattern:Pattern)->Bool"},
{"quoted", "Text$quoted", "func(text:Text, color=no)->Text"},
+ {"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"},
{"split", "Text$split", "func(text:Text, pattern=$Pattern'')->[Text]"},
diff --git a/test/text.tm b/test/text.tm
index 74a53413..0a34e2a0 100644
--- a/test/text.tm
+++ b/test/text.tm
@@ -253,3 +253,6 @@ func main():
>> "hello world":map($/world/, Text.upper)
= "hello WORLD"
+
+ >> "Abc":repeat(3)
+ = "AbcAbcAbc"