Support literal Text("blah") for text that is constant ASCII strings

This commit is contained in:
Bruce Hill 2024-09-03 14:48:54 -04:00
parent de7b564a91
commit 29a87ff325
3 changed files with 23 additions and 6 deletions

View File

@ -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]);

View File

@ -1786,9 +1786,16 @@ 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) {
@ -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 {

View File

@ -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);