code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(143 lines)
1 // This file defines how to compile types and type info values
3 #include "../types.h"
4 #include "../ast.h"
5 #include "../environment.h"
6 #include "../naming.h"
7 #include "../stdlib/datatypes.h"
8 #include "../stdlib/text.h"
9 #include "../stdlib/util.h"
10 #include "compilation.h"
12 public
13 Text_t compile_type(type_t *t) {
14 switch (t->tag) {
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");
25 case NumType:
26 return Match(t, NumType)->bits == TYPE_NBITS64 ? Text("Num_t")
27 : Texts("Num", (int32_t)Match(t, NumType)->bits, "_t");
28 case TextType: {
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");
35 case FunctionType: {
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), "*");
47 case StructType: {
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")));
52 case EnumType: {
53 DeclareMatch(e, t, EnumType);
54 return namespace_name(e->env, e->env->namespace, Text("$type"));
56 case OptionalType: {
57 type_t *nonnull = Match(t, OptionalType)->type;
58 switch (nonnull->tag) {
59 case CStringType:
60 case FunctionType:
61 case ClosureType:
62 case PointerType:
63 case EnumType: return compile_type(nonnull);
64 case TextType:
65 case IntType:
66 case BigIntType:
67 case NumType:
68 case BoolType:
69 case ByteType:
70 case PathType:
71 case ListType:
72 case TableType: return Texts("Optional", compile_type(nonnull));
73 case StructType: {
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);
83 return EMPTY_TEXT;
86 public
87 Text_t compile_type_info(type_t *t) {
88 if (t == NULL) compiler_err(NULL, NULL, NULL, "Attempt to compile a NULL type");
90 switch (t->tag) {
91 case BoolType:
92 case ByteType:
93 case IntType:
94 case BigIntType:
95 case NumType:
96 case CStringType: return Texts("&", type_to_text(t), "$info");
97 case PathType: return Text("&Path$info");
98 case TextType: {
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")), ")");
103 case StructType: {
104 DeclareMatch(s, t, StructType);
105 return Texts("(&", namespace_name(s->env, s->env->namespace, Text("$info")), ")");
107 case EnumType: {
108 DeclareMatch(e, t, EnumType);
109 return Texts("(&", namespace_name(e->env, e->env->namespace, Text("$info")), ")");
111 case ListType: {
112 type_t *item_t = Match(t, ListType)->item_type;
113 return Texts("List$info(", compile_type_info(item_t), ")");
115 case TableType: {
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), ")");
121 case PointerType: {
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), ")");
126 case FunctionType: {
127 return Texts("Function$info(", quoted_text(type_to_text(t)), ")");
129 case ClosureType: {
130 return Texts("Closure$info(", quoted_text(type_to_text(t)), ")");
132 case OptionalType: {
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));
142 return EMPTY_TEXT;