aboutsummaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-03-09 18:22:12 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-03-09 18:22:12 -0500
commit2b83ab279dbfb77cfd699d6da944c51c2353e64a (patch)
tree820f23b5c418e9d501a9fecf4fc84d2e26158cb2 /compile.c
parent1b8f7307a9c9cef191f6277cea5f2d11ef0a5788 (diff)
Add langs to the language
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/compile.c b/compile.c
index 41323128..83927cab 100644
--- a/compile.c
+++ b/compile.c
@@ -82,7 +82,7 @@ CORD compile_type(type_t *t)
case IntType: return Match(t, IntType)->bits == 64 ? "Int_t" : CORD_asprintf("Int%ld_t", Match(t, IntType)->bits);
case NumType: return Match(t, NumType)->bits == 64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits);
case TextType: {
- const char *dsl = Match(t, TextType)->dsl;
+ const char *dsl = Match(t, TextType)->lang;
return dsl ? CORD_cat(dsl, "_t") : "Text_t";
}
case ArrayType: return "array_t";
@@ -109,7 +109,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
{
CORD stmt;
switch (ast->tag) {
- case If: case When: case For: case While: case FunctionDef: case Return: case StructDef: case EnumDef:
+ case If: case When: case For: case While: case FunctionDef: case Return: case StructDef: case EnumDef: case LangDef:
case Declare: case Assign: case UpdateAssign: case DocTest: case Block:
stmt = compile(env, ast);
break;
@@ -578,21 +578,45 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_cat_char(code, '"');
}
case TextJoin: {
+ const char *lang = Match(ast, TextJoin)->lang;
+ type_t *text_t = Type(TextType, .lang=lang);
+ table_t *lang_ns = lang ? Table_str_get(*env->type_namespaces, lang) : NULL;
ast_list_t *chunks = Match(ast, TextJoin)->children;
if (!chunks) {
return "(CORD)CORD_EMPTY";
- } else if (!chunks->next) {
- type_t *t = get_type(env, chunks->ast);
- if (t->tag == TextType)
- return compile(env, chunks->ast);
- return compile_string(env, chunks->ast, "no");
+ } else if (!chunks->next && chunks->ast->tag == TextLiteral) {
+ return compile(env, chunks->ast);
} else {
CORD code = "CORD_all(";
for (ast_list_t *chunk = chunks; chunk; chunk = chunk->next) {
+ CORD chunk_code;
type_t *chunk_t = get_type(env, chunk->ast);
- CORD chunk_str = (chunk_t->tag == TextType) ?
- compile(env, chunk->ast) : compile_string(env, chunk->ast, "no");
- code = CORD_cat(code, chunk_str);
+ if (chunk->ast->tag == TextLiteral) {
+ chunk_code = compile(env, chunk->ast);
+ } else if (chunk_t->tag == TextType && streq(Match(chunk_t, TextType)->lang, lang)) {
+ chunk_code = compile(env, chunk->ast);
+ } else if (lang && lang_ns) {
+ // Get conversion function:
+ chunk_code = compile(env, chunk->ast);
+ for (int64_t i = 1; i <= Table_length(*lang_ns); i++) {
+ struct {const char *name; binding_t *b; } *entry = Table_entry(*lang_ns, i);
+ if (entry->b->type->tag != FunctionType) continue;
+ if (strncmp(entry->name, "escape_", strlen("escape_")) != 0) continue;
+ auto fn = Match(entry->b->type, FunctionType);
+ if (!fn->args || fn->args->next) continue;
+ if (fn->ret->tag != TextType || !streq(Match(fn->ret, TextType)->lang, lang))
+ continue;
+ if (!promote(env, &chunk_code, chunk_t, fn->args->type))
+ continue;
+ chunk_code = CORD_all(entry->b->code, "(", chunk_code, ")");
+ goto found_conversion;
+ }
+ code_err(chunk->ast, "I don't know how to convert a %T to a %T", chunk_t, text_t);
+ found_conversion:;
+ } else {
+ chunk_code = compile_string(env, chunk->ast, "no");
+ }
+ code = CORD_cat(code, chunk_code);
if (chunk->next) code = CORD_cat(code, ", ");
}
return CORD_cat(code, ")");
@@ -767,7 +791,7 @@ CORD compile(env_t *env, ast_t *ast)
CORD body = compile(body_scope, fndef->body);
if (CORD_fetch(body, 0) != '{')
body = CORD_asprintf("{\n%r\n}", body);
- env->code->funcs = CORD_all(env->code->funcs, code, " ", body);
+ env->code->funcs = CORD_all(env->code->funcs, code, " ", body, "\n");
if (fndef->cache && fndef->cache->tag == Int && Match(fndef->cache, Int)->i > 0) {
const char *arg_type_name = heap_strf("%s$args", CORD_to_const_char_star(name));
@@ -798,7 +822,7 @@ CORD compile(env_t *env, ast_t *ast)
pop_code,
"Table_set(&$cache, &$args, &$ret, $table_type);\n"
"return $ret;\n"
- "}");
+ "}\n");
env->code->funcs = CORD_cat(env->code->funcs, wrapper);
}
@@ -1197,7 +1221,6 @@ CORD compile(env_t *env, ast_t *ast)
return "return;";
}
}
- // Extern,
case StructDef: {
compile_struct_def(env, ast);
return CORD_EMPTY;
@@ -1206,6 +1229,17 @@ CORD compile(env_t *env, ast_t *ast)
compile_enum_def(env, ast);
return CORD_EMPTY;
}
+ case LangDef: {
+ // TODO: implement
+ auto def = Match(ast, LangDef);
+ CORD_appendf(&env->code->typedefs, "typedef CORD %s_t;\n", def->name);
+ CORD_appendf(&env->code->typedefs, "extern const TypeInfo %s;\n", def->name);
+ CORD_appendf(&env->code->typeinfos, "public const TypeInfo %s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%s}}};\n",
+ def->name, sizeof(CORD), __alignof__(CORD),
+ Text__quoted(def->name, false), "}}};\n");
+ compile_namespace(env, def->name, def->namespace);
+ return CORD_EMPTY;
+ }
case DocTest: {
auto test = Match(ast, DocTest);
CORD src = heap_strn(test->expr->start, (size_t)(test->expr->end - test->expr->start));
@@ -1444,7 +1478,7 @@ CORD compile_type_info(env_t *env, type_t *t)
{
switch (t->tag) {
case BoolType: case IntType: case NumType: return CORD_asprintf("&%r", type_to_cord(t));
- case TextType: return CORD_all("(&", Match(t, TextType)->dsl ? Match(t, TextType)->dsl : "Text", ")");
+ case TextType: return CORD_all("(&", Match(t, TextType)->lang ? Match(t, TextType)->lang : "Text", ")");
case StructType: return CORD_all("(&", Match(t, StructType)->name, ")");
case EnumType: return CORD_all("(&", Match(t, EnumType)->name, ")");
case ArrayType: {