aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-09-06 14:47:45 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-09-06 14:47:45 -0400
commita8316252db95e3d77f9f0e9beb89cfcb4573d5b1 (patch)
treee5905bce9611e35ccb2f84481232fca0e657ff42 /src/stdlib
parenta0ac652cd1eebdc42425b34f1685f8cb20cb4eea (diff)
parent73246764f88f6f652316ee0c138a990d836698a7 (diff)
Merge branch 'main' into simplified-quotes
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/integers.c4
-rw-r--r--src/stdlib/integers.h1
-rw-r--r--src/stdlib/nums.c36
-rw-r--r--src/stdlib/nums.h10
-rw-r--r--src/stdlib/pointers.c2
-rw-r--r--src/stdlib/stacktrace.c2
-rw-r--r--src/stdlib/stdlib.c3
-rw-r--r--src/stdlib/text.c50
-rw-r--r--src/stdlib/text.h15
9 files changed, 77 insertions, 46 deletions
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index 7dda77bd..863bb42d 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -430,7 +430,7 @@ OptionalInt_t Int$parse(Text_t text, Text_t *remainder) {
else if (*end != '\0') return NONE_INT;
result = mpz_init_set_str(i, str + 2, 2);
} else {
- const char *end = str + 2 + strspn(str + 2, "0123456789");
+ const char *end = str + strspn(str, "0123456789");
if (remainder) *remainder = Text$from_str(end);
else if (*end != '\0') return NONE_INT;
result = mpz_init_set_str(i, str, 10);
@@ -618,6 +618,8 @@ void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_
return colorize ? Texts(Text("\033[35m"), text, Text("\033[m")) : text; \
} \
public \
+ Text_t KindOfInt##$value_as_text(c_type i) { return _int64_to_text((int64_t)i); } \
+ public \
PUREFUNC int32_t KindOfInt##$compare(const void *x, const void *y, const TypeInfo_t *info) { \
(void)info; \
return (*(c_type *)x > *(c_type *)y) - (*(c_type *)x < *(c_type *)y); \
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 40c40754..34195d23 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -22,6 +22,7 @@
bool is_none : 1; \
} Optional##type_name##_t; \
Text_t type_name##$as_text(const void *i, bool colorize, const TypeInfo_t *type); \
+ Text_t type_name##$value_as_text(c_type i); \
PUREFUNC int32_t type_name##$compare(const void *x, const void *y, const TypeInfo_t *type); \
PUREFUNC bool type_name##$equal(const void *x, const void *y, const TypeInfo_t *type); \
Text_t type_name##$hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
diff --git a/src/stdlib/nums.c b/src/stdlib/nums.c
index 55131cfd..4bbb1f6a 100644
--- a/src/stdlib/nums.c
+++ b/src/stdlib/nums.c
@@ -14,13 +14,18 @@
#include "types.h"
public
-PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
- (void)info;
- if (!f) return Text("Num");
+PUREFUNC Text_t Num$value_as_text(double x) {
char *str = GC_MALLOC_ATOMIC(24);
- int len = fpconv_dtoa(*(double *)f, str);
+ int len = fpconv_dtoa(x, str);
+ return Text$from_strn(str, (size_t)len);
+}
+
+public
+PUREFUNC Text_t Num$as_text(const void *x, bool colorize, const TypeInfo_t *info) {
+ (void)info;
+ if (!x) return Text("Num");
static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m");
- Text_t text = Text$from_strn(str, (size_t)len);
+ Text_t text = Num$value_as_text(*(double *)x);
return colorize ? Texts(color_prefix, text, color_suffix) : text;
}
@@ -60,10 +65,10 @@ CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
}
public
-Text_t Num$percent(double f, double precision) {
- double d = 100. * f;
+Text_t Num$percent(double x, double precision) {
+ double d = 100. * x;
d = Num$with_precision(d, precision);
- return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
+ return Texts(Num$value_as_text(d), Text("%"));
}
public
@@ -142,10 +147,13 @@ const TypeInfo_t Num$info = {
};
public
-PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
+PUREFUNC Text_t Num32$value_as_text(float x) { return Num$value_as_text((double)x); }
+
+public
+PUREFUNC Text_t Num32$as_text(const void *x, bool colorize, const TypeInfo_t *info) {
(void)info;
- if (!f) return Text("Num32");
- double d = (double)(*(float *)f);
+ if (!x) return Text("Num32");
+ double d = (double)(*(float *)x);
return Num$as_text(&d, colorize, &Num$info);
}
@@ -178,10 +186,10 @@ CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
}
public
-Text_t Num32$percent(float f, float precision) {
- double d = 100. * (double)f;
+Text_t Num32$percent(float x, float precision) {
+ double d = 100. * (double)x;
d = Num$with_precision(d, (double)precision);
- return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
+ return Texts(Num$value_as_text(d), Text("%"));
}
public
diff --git a/src/stdlib/nums.h b/src/stdlib/nums.h
index db051ed2..303aa362 100644
--- a/src/stdlib/nums.h
+++ b/src/stdlib/nums.h
@@ -15,11 +15,12 @@
#define N32(n) ((float)(n))
#define N64(n) ((double)(n))
-Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *type);
+Text_t Num$as_text(const void *x, bool colorize, const TypeInfo_t *type);
+Text_t Num$value_as_text(double x);
PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute);
-Text_t Num$percent(double f, double precision);
+Text_t Num$percent(double x, double precision);
double CONSTFUNC Num$with_precision(double num, double precision);
double Num$mod(double num, double modulus);
double Num$mod1(double num, double modulus);
@@ -70,11 +71,12 @@ MACROLIKE CONSTFUNC double Num$from_byte(Byte_t i) { return (double)i; }
extern const TypeInfo_t Num$info;
-Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *type);
+Text_t Num32$as_text(const void *x, bool colorize, const TypeInfo_t *type);
+Text_t Num32$value_as_text(float x);
PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute);
-Text_t Num32$percent(float f, float precision);
+Text_t Num32$percent(float x, float precision);
float CONSTFUNC Num32$with_precision(float num, float precision);
float Num32$mod(float num, float modulus);
float Num32$mod1(float num, float modulus);
diff --git a/src/stdlib/pointers.c b/src/stdlib/pointers.c
index b5e6400f..0a1623a0 100644
--- a/src/stdlib/pointers.c
+++ b/src/stdlib/pointers.c
@@ -44,7 +44,7 @@ Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
TypeInfo_t rec_table = *Table$info(type, &Int64$info);
int64_t *id = Table$get(pending, x, &rec_table);
if (id) {
- Text_t text = Texts(Text$from_str(ptr_info.sigil), Int64$as_text(id, false, &Int64$info));
+ Text_t text = Texts(Text$from_str(ptr_info.sigil), Int64$value_as_text(*id));
return colorize ? Texts(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
}
int64_t next_id = pending.entries.length + 2;
diff --git a/src/stdlib/stacktrace.c b/src/stdlib/stacktrace.c
index 266dc4ef..0953e660 100644
--- a/src/stdlib/stacktrace.c
+++ b/src/stdlib/stacktrace.c
@@ -98,7 +98,7 @@ void print_stacktrace(FILE *out, int offset) {
cwd[cwd_len++] = '/';
cwd[cwd_len] = '\0';
- const char *install_dir = TOMO_PREFIX "/share/tomo_" TOMO_VERSION "/installed/";
+ const char *install_dir = String(TOMO_PATH, "/lib/tomo_" TOMO_VERSION "/");
static void *stack[1024];
int64_t size = (int64_t)backtrace(stack, sizeof(stack) / sizeof(stack[0]));
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c
index bf36ca0d..5ea8cb79 100644
--- a/src/stdlib/stdlib.c
+++ b/src/stdlib/stdlib.c
@@ -41,6 +41,9 @@ bool USE_COLOR;
public
Text_t TOMO_VERSION_TEXT = Text(TOMO_VERSION);
+public
+const char *TOMO_PATH = TOMO_INSTALL;
+
static _Noreturn void signal_handler(int sig, siginfo_t *info, void *userdata) {
(void)info, (void)userdata;
assert(sig == SIGILL);
diff --git a/src/stdlib/text.c b/src/stdlib/text.c
index ed4023a4..d3757a0d 100644
--- a/src/stdlib/text.c
+++ b/src/stdlib/text.c
@@ -1390,17 +1390,8 @@ Text_t Text$title(Text_t text, Text_t language) {
}
public
-Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark) {
- if (quotation_mark.length != 1) fail("Invalid quote text: ", quotation_mark, " (must have length == 1)");
-
+Text_t Text$escaped(Text_t text, bool colorize, Text_t extra_escapes) {
Text_t ret = colorize ? Text("\x1b[35m") : EMPTY_TEXT;
- if (!Text$equal_values(quotation_mark, Text("\"")) && !Text$equal_values(quotation_mark, Text("'"))
- && !Text$equal_values(quotation_mark, Text("`")))
- ret = concat2_assuming_safe(ret, Text("$"));
-
- ret = concat2_assuming_safe(ret, quotation_mark);
- int32_t quote_char = Text$get_grapheme(quotation_mark, 0);
-
#define flush_unquoted() \
({ \
if (unquoted_span > 0) { \
@@ -1454,15 +1445,18 @@ Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark) {
break;
}
default: {
- if (g == quote_char) {
- flush_unquoted();
- if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m"));
- ret = concat2_assuming_safe(ret, Text("\\"));
- ret = concat2_assuming_safe(ret, quotation_mark);
- if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[0;35m"));
- } else {
- unquoted_span += 1;
+ TextIter_t esc_state = NEW_TEXT_ITER_STATE(extra_escapes);
+ for (int64_t j = 0; j < extra_escapes.length; j++) {
+ int32_t esc = Text$get_grapheme_fast(&esc_state, j);
+ if (g == esc) {
+ flush_unquoted();
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m"));
+ ret = concat2_assuming_safe(ret, Text("\\"));
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[0;35m"));
+ break;
+ }
}
+ unquoted_span += 1;
break;
}
}
@@ -1470,10 +1464,19 @@ Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark) {
flush_unquoted();
#undef add_escaped
#undef flush_unquoted
-
- ret = concat2_assuming_safe(ret, quotation_mark);
if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[m"));
+ return ret;
+}
+
+public
+Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark) {
+ if (quotation_mark.length != 1) fail("Invalid quote text: ", quotation_mark, " (must have length == 1)");
+ Text_t ret = Text$escaped(text, colorize, quotation_mark);
+ if (!(Text$equal_values(quotation_mark, Text("\"")) || Text$equal_values(quotation_mark, Text("'"))
+ || Text$equal_values(quotation_mark, Text("`"))))
+ ret = Texts("$", quotation_mark, ret, quotation_mark);
+ else ret = Texts(quotation_mark, ret, quotation_mark);
return ret;
}
@@ -1726,10 +1729,9 @@ Int_t Text$memory_size(Text_t text) {
public
Text_t Text$layout(Text_t text) {
switch (text.tag) {
- case TEXT_ASCII: return Texts(Text("ASCII("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
- case TEXT_GRAPHEMES:
- return Texts(Text("Graphemes("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
- case TEXT_BLOB: return Texts(Text("Blob("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
+ case TEXT_ASCII: return Texts(Text("ASCII("), Int64$value_as_text(text.length), Text(")"));
+ case TEXT_GRAPHEMES: return Texts(Text("Graphemes("), Int64$value_as_text(text.length), Text(")"));
+ case TEXT_BLOB: return Texts(Text("Blob("), Int64$value_as_text(text.length), Text(")"));
case TEXT_CONCAT:
return Texts(Text("Concat("), Text$layout(*text.left), Text(", "), Text$layout(*text.right), Text(")"));
default: errx(1, "Invalid text tag: %d", text.tag);
diff --git a/src/stdlib/text.h b/src/stdlib/text.h
index 5fa95675..7f7fc2c6 100644
--- a/src/stdlib/text.h
+++ b/src/stdlib/text.h
@@ -7,7 +7,9 @@
#include <stdint.h>
#include "datatypes.h"
+#include "integers.h" // IWYU pragma: export
#include "mapmacro.h"
+#include "nums.h" // IWYU pragma: export
#include "types.h"
#include "util.h"
@@ -31,7 +33,17 @@ static inline Text_t Text_from_str_literal(const char *str) {
static inline Text_t Text_from_text(Text_t t) { return t; }
-#define convert_to_text(x) _Generic(x, Text_t: Text_from_text, char *: Text$from_str, const char *: Text$from_str)(x)
+#define convert_to_text(x) \
+ _Generic(x, \
+ Text_t: Text_from_text, \
+ char *: Text$from_str, \
+ const char *: Text$from_str, \
+ int8_t: Int8$value_as_text, \
+ int16_t: Int16$value_as_text, \
+ int32_t: Int32$value_as_text, \
+ int64_t: Int64$value_as_text, \
+ double: Num$value_as_text, \
+ float: Num32$value_as_text)(x)
Text_t Text$_concat(int n, Text_t items[n]);
#define Text$concat(...) Text$_concat(sizeof((Text_t[]){__VA_ARGS__}) / sizeof(Text_t), (Text_t[]){__VA_ARGS__})
@@ -54,6 +66,7 @@ Text_t Text$upper(Text_t text, Text_t language);
Text_t Text$lower(Text_t text, Text_t language);
Text_t Text$title(Text_t text, Text_t language);
Text_t Text$as_text(const void *text, bool colorize, const TypeInfo_t *info);
+Text_t Text$escaped(Text_t text, bool colorize, Text_t extra_escapes);
Text_t Text$quoted(Text_t str, bool colorize, Text_t quotation_mark);
PUREFUNC bool Text$starts_with(Text_t text, Text_t prefix, Text_t *remainder);
PUREFUNC bool Text$ends_with(Text_t text, Text_t suffix, Text_t *remainder);