diff options
| -rw-r--r-- | builtins/integers.h | 19 | ||||
| -rw-r--r-- | builtins/optionals.c | 9 | ||||
| -rw-r--r-- | compile.c | 42 | ||||
| -rw-r--r-- | types.c | 21 |
4 files changed, 70 insertions, 21 deletions
diff --git a/builtins/integers.h b/builtins/integers.h index e69914c8..22dc4f7c 100644 --- a/builtins/integers.h +++ b/builtins/integers.h @@ -23,7 +23,11 @@ #define I16(x) ((int16_t)x) #define I8(x) ((int8_t)x) -#define DEFINE_INT_TYPE(c_type, type_name) \ +#define DEFINE_INT_TYPE(c_type, type_name, bits) \ + typedef struct { \ + c_type i:bits; \ + bool is_null:1; \ + } Optional ## type_name ## _t; \ Text_t type_name ## $as_text(const c_type *i, bool colorize, const TypeInfo *type); \ PUREFUNC int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo *type); \ PUREFUNC bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo *type); \ @@ -59,12 +63,17 @@ return type_name ## $modulo(D-1, d) + 1; \ } -DEFINE_INT_TYPE(int64_t, Int64) -DEFINE_INT_TYPE(int32_t, Int32) -DEFINE_INT_TYPE(int16_t, Int16) -DEFINE_INT_TYPE(int8_t, Int8) +DEFINE_INT_TYPE(int64_t, Int64, 64) +DEFINE_INT_TYPE(int32_t, Int32, 32) +DEFINE_INT_TYPE(int16_t, Int16, 16) +DEFINE_INT_TYPE(int8_t, Int8, 8) #undef DEFINE_INT_TYPE +#define NULL_INT64 ((OptionalInt64_t){.is_null=true}) +#define NULL_INT32 ((OptionalInt32_t){.is_null=true}) +#define NULL_INT16 ((OptionalInt16_t){.is_null=true}) +#define NULL_INT8 ((OptionalInt8_t){.is_null=true}) + #define Int64$abs(...) I64(labs(__VA_ARGS__)) #define Int32$abs(...) I32(abs(__VA_ARGS__)) #define Int16$abs(...) I16(abs(__VA_ARGS__)) diff --git a/builtins/optionals.c b/builtins/optionals.c index 869ee4cd..27ab8ec6 100644 --- a/builtins/optionals.c +++ b/builtins/optionals.c @@ -2,6 +2,7 @@ #include "bool.h" #include "datatypes.h" +#include "integers.h" #include "text.h" #include "util.h" @@ -20,6 +21,14 @@ static inline bool is_null(const void *obj, const TypeInfo *non_optional_type) return *((Bool_t*)obj) == NULL_BOOL; else if (non_optional_type == &Num$info) return isnan(*((Num_t*)obj)); + else if (non_optional_type == &Int64$info) + return ((OptionalInt64_t*)obj)->is_null; + else if (non_optional_type == &Int32$info) + return ((OptionalInt32_t*)obj)->is_null; + else if (non_optional_type == &Int16$info) + return ((OptionalInt16_t*)obj)->is_null; + else if (non_optional_type == &Int8$info) + return ((OptionalInt8_t*)obj)->is_null; switch (non_optional_type->tag) { case PointerInfo: return *(void**)obj == NULL; @@ -200,6 +200,8 @@ CORD compile_type(type_t *t) } case OptionalType: { type_t *nonnull = Match(t, OptionalType)->type; + if (nonnull->tag == IntType) + return CORD_all("Optional", compile_type(nonnull)); if (!supports_optionals(nonnull)) compiler_err(NULL, NULL, NULL, "Optional types are not supported for: %T", t); return compile_type(nonnull); @@ -280,11 +282,14 @@ static CORD compile_inline_block(env_t *env, ast_t *ast) return code; } -static CORD compile_optional_into_nonnull(env_t *env, binding_t *b) +static CORD optional_var_into_nonnull(binding_t *b) { - (void)env; - // TODO: implement - return (b->code); + switch (b->type->tag) { + case IntType: + return CORD_all(b->code, ".i"); + default: + return b->code; + } } static CORD compile_optional_check(env_t *env, ast_t *ast) @@ -307,6 +312,8 @@ static CORD compile_optional_check(env_t *env, ast_t *ast) return CORD_all("((", compile(env, ast), ") != NULL_BOOL)"); else if (t->tag == TextType) return CORD_all("((", compile(env, ast), ").length >= 0)"); + else if (t->tag == IntType) + return CORD_all("!(", compile(env, ast), ").is_null"); errx(1, "Optional check not implemented for: %T", t); } @@ -1225,7 +1232,7 @@ CORD compile_statement(env_t *env, ast_t *ast) binding_t *nonnull_b = new(binding_t); *nonnull_b = *b; nonnull_b->type = Match(cond_t, OptionalType)->type; - nonnull_b->code = compile_optional_into_nonnull(env, b); + nonnull_b->code = optional_var_into_nonnull(b); set_binding(truthy_scope, varname, nonnull_b); } condition_code = compile_optional_check(env, condition); @@ -1647,6 +1654,16 @@ CORD compile(env_t *env, ast_t *ast) type_t *t = parse_type_ast(env, Match(ast, Nil)->type); switch (t->tag) { case BigIntType: return "NULL_INT"; + case IntType: { + switch (Match(t, IntType)->bits) { + case TYPE_IBITS8: return "NULL_INT8"; + case TYPE_IBITS16: return "NULL_INT16"; + case TYPE_IBITS32: return "NULL_INT32"; + case TYPE_IBITS64: return "NULL_INT64"; + default: errx(1, "Invalid integer bit size"); + } + break; + } case BoolType: return "NULL_BOOL"; case ArrayType: return "NULL_ARRAY"; case TableType: return "NULL_TABLE"; @@ -1760,7 +1777,20 @@ CORD compile(env_t *env, ast_t *ast) code_err(subject, "This subject can't be mutated!"); } case Optional: { - return compile(env, Match(ast, Optional)->value); + ast_t *value = Match(ast, Optional)->value; + CORD value_code = compile(env, value); + type_t *t = get_type(env, value); + if (t->tag == IntType) { + switch (Match(t, IntType)->bits) { + case TYPE_IBITS8: return CORD_all("((OptionalInt8_t){.i=", value_code, "})"); + case TYPE_IBITS16: return CORD_all("((OptionalInt16_t){.i=", value_code, "})"); + case TYPE_IBITS32: return CORD_all("((OptionalInt32_t){.i=", value_code, "})"); + case TYPE_IBITS64: return CORD_all("((OptionalInt64_t){.i=", value_code, "})"); + default: errx(1, "Unsupported in type: %T", t); + } + } else { + return value_code; + } } case BinaryOp: { auto binop = Match(ast, BinaryOp); @@ -5,9 +5,10 @@ #include <limits.h> #include <math.h> +#include "builtins/integers.h" #include "builtins/table.h" -#include "types.h" #include "builtins/util.h" +#include "types.h" CORD type_to_cord(type_t *t) { switch (t->tag) { @@ -373,7 +374,7 @@ PUREFUNC bool supports_optionals(type_t *t) switch (t->tag) { case BoolType: case CStringType: case BigIntType: case NumType: case TextType: case ArrayType: case SetType: case TableType: case FunctionType: case ClosureType: - case PointerType: + case PointerType: case IntType: return true; default: return false; } @@ -411,10 +412,10 @@ PUREFUNC size_t type_size(type_t *t) switch (nonnull->tag) { case IntType: switch (Match(t, IntType)->bits) { - case TYPE_IBITS64: return sizeof(struct { int64_t x; bool is_null; }); - case TYPE_IBITS32: return sizeof(int64_t); - case TYPE_IBITS16: return sizeof(int32_t); - case TYPE_IBITS8: return sizeof(int16_t); + case TYPE_IBITS64: return sizeof(OptionalInt64_t); + case TYPE_IBITS32: return sizeof(OptionalInt32_t); + case TYPE_IBITS16: return sizeof(OptionalInt16_t); + case TYPE_IBITS8: return sizeof(OptionalInt8_t); default: errx(1, "Invalid integer bit size"); } default: return type_size(nonnull); @@ -488,10 +489,10 @@ PUREFUNC size_t type_align(type_t *t) switch (nonnull->tag) { case IntType: switch (Match(t, IntType)->bits) { - case TYPE_IBITS64: return __alignof__(struct { int64_t x; bool is_null; }); - case TYPE_IBITS32: return __alignof__(int64_t); - case TYPE_IBITS16: return __alignof__(int32_t); - case TYPE_IBITS8: return __alignof__(int16_t); + case TYPE_IBITS64: return __alignof__(OptionalInt64_t); + case TYPE_IBITS32: return __alignof__(OptionalInt32_t); + case TYPE_IBITS16: return __alignof__(OptionalInt16_t); + case TYPE_IBITS8: return __alignof__(OptionalInt8_t); default: errx(1, "Invalid integer bit size"); } default: return type_align(nonnull); |
