1 // This file defines how to compile types and type info values
5 #include "../environment.h"
7 #include "../stdlib/datatypes.h"
8 #include "../stdlib/text.h"
9 #include "../stdlib/util.h"
10 #include "compilation.h"
13 Text_t compile_type(type_t *t) {
15 case ReturnType: errx(1, "Shouldn't be compiling ReturnType to a type");
16 case AbortType: return Text("void");
17 case VoidType: return Text("void");
18 case MemoryType: return Text("void");
19 case BoolType: return Text("Bool_t");
20 case ByteType: return Text("Byte_t");
21 case CStringType: return Text("const char*");
22 case PathType: return Text("Path_t");
23 case BigIntType: return Text("Int_t");
24 case IntType: return Texts("Int", (int32_t)Match(t, IntType)->bits, "_t");
26 return Match(t, NumType)->bits == TYPE_NBITS64 ? Text("Num_t")
27 : Texts("Num", (int32_t)Match(t, NumType)->bits, "_t");
29 DeclareMatch(text, t, TextType);
30 if (!text->lang || streq(text->lang, "Text")) return Text("Text_t");
31 else return namespace_name(text->env, text->env->namespace, Text("$type"));
33 case ListType: return Text("List_t");
34 case TableType: return Text("Table_t");
36 DeclareMatch(fn, t, FunctionType);
37 Text_t code = Texts(compile_type(fn->ret), " (*)(");
38 for (arg_t *arg = fn->args; arg; arg = arg->next) {
39 code = Texts(code, compile_type(arg->type));
40 if (arg->next) code = Texts(code, ", ");
42 if (!fn->args) code = Texts(code, "void");
43 return Texts(code, ")");
45 case ClosureType: return Text("Closure_t");
46 case PointerType: return Texts(compile_type(Match(t, PointerType)->pointed), "*");
48 DeclareMatch(s, t, StructType);
49 if (s->external) return Text$from_str(s->name);
50 return Texts("struct ", namespace_name(s->env, s->env->namespace, Text("$struct")));
53 DeclareMatch(e, t, EnumType);
54 return namespace_name(e->env, e->env->namespace, Text("$type"));
57 type_t *nonnull = Match(t, OptionalType)->type;
58 switch (nonnull->tag) {
63 case EnumType: return compile_type(nonnull);
72 case TableType: return Texts("Optional", compile_type(nonnull));
74 DeclareMatch(s, nonnull, StructType);
75 return namespace_name(s->env, s->env->namespace->parent, Texts("$Optional", s->name, "$$type"));
77 default: compiler_err(NULL, NULL, NULL, "Optional types are not supported for: ", type_to_text(t));
80 case TypeInfoType: return Text("TypeInfo_t");
81 default: compiler_err(NULL, NULL, NULL, "Compiling type is not implemented for type with tag ", t->tag);
87 Text_t compile_type_info(type_t *t) {
88 if (t == NULL) compiler_err(NULL, NULL, NULL, "Attempt to compile a NULL type");
96 case CStringType: return Texts("&", type_to_text(t), "$info");
97 case PathType: return Text("&Path$info");
99 DeclareMatch(text, t, TextType);
100 if (!text->lang || streq(text->lang, "Text")) return Text("&Text$info");
101 return Texts("(&", namespace_name(text->env, text->env->namespace, Text("$info")), ")");
104 DeclareMatch(s, t, StructType);
105 return Texts("(&", namespace_name(s->env, s->env->namespace, Text("$info")), ")");
108 DeclareMatch(e, t, EnumType);
109 return Texts("(&", namespace_name(e->env, e->env->namespace, Text("$info")), ")");
112 type_t *item_t = Match(t, ListType)->item_type;
113 return Texts("List$info(", compile_type_info(item_t), ")");
116 DeclareMatch(table, t, TableType);
117 type_t *key_type = table->key_type;
118 type_t *value_type = table->value_type;
119 return Texts("Table$info(", compile_type_info(key_type), ", ", compile_type_info(value_type), ")");
122 DeclareMatch(ptr, t, PointerType);
123 const char *sigil = ptr->is_stack ? "&" : "@";
124 return Texts("Pointer$info(", quoted_str(sigil), ", ", compile_type_info(ptr->pointed), ")");
127 return Texts("Function$info(", quoted_text(type_to_text(t)), ")");
130 return Texts("Closure$info(", quoted_text(type_to_text(t)), ")");
133 type_t *non_optional = Match(t, OptionalType)->type;
134 return Texts("Optional$info(", (int64_t)type_size(t), ", ", (int64_t)type_align(t), ", ",
135 compile_type_info(non_optional), ")");
137 case TypeInfoType: return Texts("Type$info(", quoted_text(type_to_text(Match(t, TypeInfoType)->type)), ")");
138 case MemoryType: return Text("&Memory$info");
139 case VoidType: return Text("&Void$info");
140 default: compiler_err(NULL, 0, 0, "I couldn't convert to a type info: ", type_to_text(t));