diff options
| -rw-r--r-- | builtins/text.h | 2 | ||||
| -rw-r--r-- | compile.c | 15 | ||||
| -rw-r--r-- | typecheck.c | 12 |
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]); @@ -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); |
