aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/text.h2
-rw-r--r--compile.c15
-rw-r--r--typecheck.c12
3 files changed, 23 insertions, 6 deletions
diff --git a/builtins/text.h b/builtins/text.h
index edf3dc9f..ec65a7f9 100644
--- a/builtins/text.h
+++ b/builtins/text.h
@@ -14,6 +14,8 @@
int printf_text(FILE *stream, const struct printf_info *info, const void *const args[]);
int printf_text_size(const struct printf_info *info, size_t n, int argtypes[n], int sizes[n]);
+#define Text(str) ((Text_t){.length=sizeof(str)-1, .tag=TEXT_ASCII, .ascii="" str})
+
int Text$print(FILE *stream, Text_t t);
void Text$visualize(Text_t t);
Text_t Text$_concat(int n, Text_t items[n]);
diff --git a/compile.c b/compile.c
index 69fa345c..688490ab 100644
--- a/compile.c
+++ b/compile.c
@@ -1786,10 +1786,17 @@ CORD compile(env_t *env, ast_t *ast)
case TextLiteral: {
CORD literal = Match(ast, TextLiteral)->cord;
if (literal == CORD_EMPTY)
- return "((Text_t){.length=0})";
- CORD code = "Text$from_str(\"";
+ return "Text(\"\")";
+ bool all_ascii = true;
CORD_pos i;
CORD_FOR(i, literal) {
+ if (!isascii(CORD_pos_fetch(i))) {
+ all_ascii = false;
+ break;
+ }
+ }
+ CORD code = all_ascii ? "Text(\"" : "Text$from_str(\"";
+ CORD_FOR(i, literal) {
char c = CORD_pos_fetch(i);
switch (c) {
case '\\': code = CORD_cat(code, "\\\\"); break;
@@ -1804,7 +1811,7 @@ CORD compile(env_t *env, ast_t *ast)
if (isprint(c))
code = CORD_cat_char(code, c);
else
- CORD_sprintf(&code, "%r\"\"\\x%02X\"\"", code, (uint8_t)c);
+ CORD_sprintf(&code, "%r\\x%02X\"\"", code, (uint8_t)c);
break;
}
}
@@ -1818,7 +1825,7 @@ CORD compile(env_t *env, ast_t *ast)
code_err(ast, "%s is not a valid text language name", lang);
ast_list_t *chunks = Match(ast, TextJoin)->children;
if (!chunks) {
- return "((Text_t){.length=0})";
+ return "Text(\"\")";
} else if (!chunks->next && chunks->ast->tag == TextLiteral) {
return compile(env, chunks->ast);
} else {
diff --git a/typecheck.c b/typecheck.c
index 27e20b04..b5a4a4c1 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -1377,8 +1377,16 @@ bool is_constant(env_t *env, ast_t *ast)
}
case TextJoin: {
auto text = Match(ast, TextJoin);
- // TODO: support short literal strings
- return !text->children;
+ if (!text->children) return true; // Empty string, OK
+ if (text->children->next) return false; // Concatenation, not constant
+
+ CORD literal = Match(text->children->ast, TextLiteral)->cord;
+ CORD_pos i;
+ CORD_FOR(i, literal) {
+ if (!isascii(CORD_pos_fetch(i)))
+ return false; // Non-ASCII requires grapheme logic, not constant
+ }
+ return true; // Literal ASCII string, OK
}
case Not: return is_constant(env, Match(ast, Not)->value);
case Negative: return is_constant(env, Match(ast, Negative)->value);