aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/integers.h19
-rw-r--r--builtins/optionals.c9
-rw-r--r--compile.c42
-rw-r--r--types.c21
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;
diff --git a/compile.c b/compile.c
index af1a32ac..04ae8606 100644
--- a/compile.c
+++ b/compile.c
@@ -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);
diff --git a/types.c b/types.c
index c91e6eb2..daa1026f 100644
--- a/types.c
+++ b/types.c
@@ -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);