From 476bacc27671de92e8fdbc5b2a904bbf8bc80377 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 24 Aug 2025 17:07:41 -0400 Subject: More splitting out into separate files. --- src/compile/types.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/compile/types.c (limited to 'src/compile/types.c') diff --git a/src/compile/types.c b/src/compile/types.c new file mode 100644 index 00000000..9b7cf4df --- /dev/null +++ b/src/compile/types.c @@ -0,0 +1,154 @@ +#include "../types.h" +#include "../ast.h" +#include "../environment.h" +#include "../naming.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/text.h" +#include "../stdlib/util.h" + +static Text_t quoted_str(const char *str) { return Text$quoted(Text$from_str(str), false, Text("\"")); } + +static inline Text_t quoted_text(Text_t text) { return Text$quoted(text, false, Text("\"")); } + +public +Text_t compile_type(type_t *t) { + if (t == PATH_TYPE) return Text("Path_t"); + else if (t == PATH_TYPE_TYPE) return Text("PathType_t"); + + switch (t->tag) { + case ReturnType: errx(1, "Shouldn't be compiling ReturnType to a type"); + case AbortType: return Text("void"); + case VoidType: return Text("void"); + case MemoryType: return Text("void"); + case BoolType: return Text("Bool_t"); + case ByteType: return Text("Byte_t"); + case CStringType: return Text("const char*"); + case BigIntType: return Text("Int_t"); + case IntType: return Texts("Int", String(Match(t, IntType)->bits), "_t"); + case NumType: + return Match(t, NumType)->bits == TYPE_NBITS64 ? Text("Num_t") + : Texts("Num", String(Match(t, NumType)->bits), "_t"); + case TextType: { + DeclareMatch(text, t, TextType); + if (!text->lang || streq(text->lang, "Text")) return Text("Text_t"); + else return namespace_name(text->env, text->env->namespace, Text("$type")); + } + case ListType: return Text("List_t"); + case SetType: return Text("Table_t"); + case TableType: return Text("Table_t"); + case FunctionType: { + DeclareMatch(fn, t, FunctionType); + Text_t code = Texts(compile_type(fn->ret), " (*)("); + for (arg_t *arg = fn->args; arg; arg = arg->next) { + code = Texts(code, compile_type(arg->type)); + if (arg->next) code = Texts(code, ", "); + } + if (!fn->args) code = Texts(code, "void"); + return Texts(code, ")"); + } + case ClosureType: return Text("Closure_t"); + case PointerType: return Texts(compile_type(Match(t, PointerType)->pointed), "*"); + case StructType: { + DeclareMatch(s, t, StructType); + if (s->external) return Text$from_str(s->name); + return Texts("struct ", namespace_name(s->env, s->env->namespace, Text("$struct"))); + } + case EnumType: { + DeclareMatch(e, t, EnumType); + return namespace_name(e->env, e->env->namespace, Text("$type")); + } + case OptionalType: { + type_t *nonnull = Match(t, OptionalType)->type; + switch (nonnull->tag) { + case CStringType: + case FunctionType: + case ClosureType: + case PointerType: + case EnumType: return compile_type(nonnull); + case TextType: return Match(nonnull, TextType)->lang ? compile_type(nonnull) : Text("OptionalText_t"); + case IntType: + case BigIntType: + case NumType: + case BoolType: + case ByteType: + case ListType: + case TableType: + case SetType: return Texts("Optional", compile_type(nonnull)); + case StructType: { + if (nonnull == PATH_TYPE) return Text("OptionalPath_t"); + if (nonnull == PATH_TYPE_TYPE) return Text("OptionalPathType_t"); + DeclareMatch(s, nonnull, StructType); + return namespace_name(s->env, s->env->namespace->parent, Texts("$Optional", s->name, "$$type")); + } + default: compiler_err(NULL, NULL, NULL, "Optional types are not supported for: ", type_to_str(t)); + } + } + case TypeInfoType: return Text("TypeInfo_t"); + default: compiler_err(NULL, NULL, NULL, "Compiling type is not implemented for type with tag ", t->tag); + } + return EMPTY_TEXT; +} + +public +Text_t compile_type_info(type_t *t) { + if (t == NULL) compiler_err(NULL, NULL, NULL, "Attempt to compile a NULL type"); + if (t == PATH_TYPE) return Text("&Path$info"); + else if (t == PATH_TYPE_TYPE) return Text("&PathType$info"); + + switch (t->tag) { + case BoolType: + case ByteType: + case IntType: + case BigIntType: + case NumType: + case CStringType: return Texts("&", type_to_text(t), "$info"); + case TextType: { + DeclareMatch(text, t, TextType); + if (!text->lang || streq(text->lang, "Text")) return Text("&Text$info"); + return Texts("(&", namespace_name(text->env, text->env->namespace, Text("$info")), ")"); + } + case StructType: { + DeclareMatch(s, t, StructType); + return Texts("(&", namespace_name(s->env, s->env->namespace, Text("$info")), ")"); + } + case EnumType: { + DeclareMatch(e, t, EnumType); + return Texts("(&", namespace_name(e->env, e->env->namespace, Text("$info")), ")"); + } + case ListType: { + type_t *item_t = Match(t, ListType)->item_type; + return Texts("List$info(", compile_type_info(item_t), ")"); + } + case SetType: { + type_t *item_type = Match(t, SetType)->item_type; + return Texts("Set$info(", compile_type_info(item_type), ")"); + } + case TableType: { + DeclareMatch(table, t, TableType); + type_t *key_type = table->key_type; + type_t *value_type = table->value_type; + return Texts("Table$info(", compile_type_info(key_type), ", ", compile_type_info(value_type), ")"); + } + case PointerType: { + DeclareMatch(ptr, t, PointerType); + const char *sigil = ptr->is_stack ? "&" : "@"; + return Texts("Pointer$info(", quoted_str(sigil), ", ", compile_type_info(ptr->pointed), ")"); + } + case FunctionType: { + return Texts("Function$info(", quoted_text(type_to_text(t)), ")"); + } + case ClosureType: { + return Texts("Closure$info(", quoted_text(type_to_text(t)), ")"); + } + case OptionalType: { + type_t *non_optional = Match(t, OptionalType)->type; + return Texts("Optional$info(sizeof(", compile_type(non_optional), "), __alignof__(", compile_type(non_optional), + "), ", compile_type_info(non_optional), ")"); + } + case TypeInfoType: return Texts("Type$info(", quoted_text(type_to_text(Match(t, TypeInfoType)->type)), ")"); + case MemoryType: return Text("&Memory$info"); + case VoidType: return Text("&Void$info"); + default: compiler_err(NULL, 0, 0, "I couldn't convert to a type info: ", type_to_str(t)); + } + return EMPTY_TEXT; +} -- cgit v1.2.3