diff options
Diffstat (limited to 'src/compile/optionals.c')
| -rw-r--r-- | src/compile/optionals.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/compile/optionals.c b/src/compile/optionals.c new file mode 100644 index 00000000..4b360b31 --- /dev/null +++ b/src/compile/optionals.c @@ -0,0 +1,85 @@ +#include "../compile.h" +#include "../environment.h" +#include "../naming.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/text.h" +#include "../stdlib/util.h" +#include "../types.h" + +Text_t optional_into_nonnone(type_t *t, Text_t value) { + if (t->tag == OptionalType) t = Match(t, OptionalType)->type; + switch (t->tag) { + case IntType: + case ByteType: return Texts(value, ".value"); + case StructType: + if (t == PATH_TYPE || t == PATH_TYPE_TYPE) return value; + return Texts(value, ".value"); + default: return value; + } +} + +public +Text_t promote_to_optional(type_t *t, Text_t code) { + if (t == PATH_TYPE || t == PATH_TYPE_TYPE) { + return code; + } else if (t->tag == IntType) { + switch (Match(t, IntType)->bits) { + case TYPE_IBITS8: return Texts("((OptionalInt8_t){.value=", code, "})"); + case TYPE_IBITS16: return Texts("((OptionalInt16_t){.value=", code, "})"); + case TYPE_IBITS32: return Texts("((OptionalInt32_t){.value=", code, "})"); + case TYPE_IBITS64: return Texts("((OptionalInt64_t){.value=", code, "})"); + default: errx(1, "Unsupported in type: %s", type_to_str(t)); + } + return code; + } else if (t->tag == ByteType) { + return Texts("((OptionalByte_t){.value=", code, "})"); + } else if (t->tag == StructType) { + return Texts("({ ", compile_type(Type(OptionalType, .type = t)), " nonnull = {.value=", code, + "}; nonnull.is_none = false; nonnull; })"); + } else { + return code; + } +} + +public +Text_t compile_none(type_t *t) { + if (t == NULL) compiler_err(NULL, NULL, NULL, "I can't compile a `none` value with no type"); + + if (t->tag == OptionalType) t = Match(t, OptionalType)->type; + + if (t == NULL) compiler_err(NULL, NULL, NULL, "I can't compile a `none` value with no type"); + + if (t == PATH_TYPE) return Text("NONE_PATH"); + else if (t == PATH_TYPE_TYPE) return Text("((OptionalPathType_t){})"); + + switch (t->tag) { + case BigIntType: return Text("NONE_INT"); + case IntType: { + switch (Match(t, IntType)->bits) { + case TYPE_IBITS8: return Text("NONE_INT8"); + case TYPE_IBITS16: return Text("NONE_INT16"); + case TYPE_IBITS32: return Text("NONE_INT32"); + case TYPE_IBITS64: return Text("NONE_INT64"); + default: errx(1, "Invalid integer bit size"); + } + break; + } + case BoolType: return Text("NONE_BOOL"); + case ByteType: return Text("NONE_BYTE"); + case ListType: return Text("NONE_LIST"); + case TableType: return Text("NONE_TABLE"); + case SetType: return Text("NONE_TABLE"); + case TextType: return Text("NONE_TEXT"); + case CStringType: return Text("NULL"); + case PointerType: return Texts("((", compile_type(t), ")NULL)"); + case ClosureType: return Text("NONE_CLOSURE"); + case NumType: return Text("nan(\"none\")"); + case StructType: return Texts("((", compile_type(Type(OptionalType, .type = t)), "){.is_none=true})"); + case EnumType: { + env_t *enum_env = Match(t, EnumType)->env; + return Texts("((", compile_type(t), "){", namespace_name(enum_env, enum_env->namespace, Text("none")), "})"); + } + default: compiler_err(NULL, NULL, NULL, "none isn't implemented for this type: ", type_to_str(t)); + } + return EMPTY_TEXT; +} |
