diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-09-11 01:31:31 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-09-11 01:31:31 -0400 |
| commit | 7126755275f12e6278031e78ff33f65801b133dd (patch) | |
| tree | 7f43f3449eb7bb69b0879dd41eb174e89fdc34cc /builtins | |
| parent | 89234e34e292861fccb8e5bdbefc695a7e443eea (diff) | |
Add optional types
Diffstat (limited to 'builtins')
| -rw-r--r-- | builtins/functions.c | 11 | ||||
| -rw-r--r-- | builtins/optionals.c | 49 | ||||
| -rw-r--r-- | builtins/optionals.h | 25 | ||||
| -rw-r--r-- | builtins/pointer.c | 9 | ||||
| -rw-r--r-- | builtins/tomo.h | 1 | ||||
| -rw-r--r-- | builtins/types.c | 1 | ||||
| -rw-r--r-- | builtins/types.h | 13 |
7 files changed, 96 insertions, 13 deletions
diff --git a/builtins/functions.c b/builtins/functions.c index b4e1a5cc..d6778d4c 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -16,6 +16,7 @@ #include "files.h" #include "functions.h" #include "integers.h" +#include "optionals.h" #include "pointer.h" #include "siphash.h" #include "string.h" @@ -113,6 +114,9 @@ PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo *type) case ArrayInfo: return Array$hash(obj, type); case ChannelInfo: return Channel$hash((const channel_t**)obj, type); case TableInfo: return Table$hash(obj, type); + case OptionalInfo: { + errx(1, "Optional hash not implemented"); + } case EmptyStruct: return 0; case CustomInfo: if (!type->CustomInfo.hash) @@ -135,6 +139,9 @@ PUREFUNC public int32_t generic_compare(const void *x, const void *y, const Type case ArrayInfo: return Array$compare(x, y, type); case ChannelInfo: return Channel$compare((const channel_t**)x, (const channel_t**)y, type); case TableInfo: return Table$compare(x, y, type); + case OptionalInfo: { + errx(1, "Optional compare not implemented"); + } case EmptyStruct: return 0; case CustomInfo: if (!type->CustomInfo.compare) @@ -157,6 +164,9 @@ PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo case ChannelInfo: return Channel$equal((const channel_t**)x, (const channel_t**)y, type); case TableInfo: return Table$equal(x, y, type); case EmptyStruct: return true; + case OptionalInfo: { + errx(1, "Optional equal not implemented"); + } case CustomInfo: if (!type->CustomInfo.equal) goto use_generic_compare; @@ -177,6 +187,7 @@ public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo *ty case ChannelInfo: return Channel$as_text((const channel_t**)obj, colorize, type); case TableInfo: return Table$as_text(obj, colorize, type); case TypeInfoInfo: return Type$as_text(obj, colorize, type); + case OptionalInfo: return Optional$as_text(obj, colorize, type); case EmptyStruct: return colorize ? Text$concat(Text("\x1b[0;1m"), Text$from_str(type->EmptyStruct.name), Text("\x1b[m()")) : Text$concat(Text$from_str(type->EmptyStruct.name), Text("()")); diff --git a/builtins/optionals.c b/builtins/optionals.c new file mode 100644 index 00000000..869ee4cd --- /dev/null +++ b/builtins/optionals.c @@ -0,0 +1,49 @@ +// Optional types + +#include "bool.h" +#include "datatypes.h" +#include "text.h" +#include "util.h" + +public const Array_t NULL_ARRAY = {.length=-1}; +public const Bool_t NULL_BOOL = -1; +public const Int_t NULL_INT = {.small=0}; +public const Table_t NULL_TABLE = {.entries.length=-1}; +public const closure_t NULL_CLOSURE = {.fn=NULL}; +public const Text_t NULL_TEXT = {.length=-1}; + +static inline bool is_null(const void *obj, const TypeInfo *non_optional_type) +{ + if (non_optional_type == &Int$info) + return ((Int_t*)obj)->small == 0; + else if (non_optional_type == &Bool$info) + return *((Bool_t*)obj) == NULL_BOOL; + else if (non_optional_type == &Num$info) + return isnan(*((Num_t*)obj)); + + switch (non_optional_type->tag) { + case PointerInfo: return *(void**)obj == NULL; + case TextInfo: return ((Text_t*)obj)->length < 0; + case ArrayInfo: return ((Array_t*)obj)->length < 0; + case TableInfo: return ((Table_t*)obj)->entries.length < 0; + case FunctionInfo: return *(void**)obj == NULL; + default: { + Text_t t = generic_as_text(NULL, false, non_optional_type); + errx(1, "is_null() not implemented for: %k", &t); + } + } +} + +#pragma GCC diagnostic ignored "-Wstack-protector" +public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo *type) +{ + if (!obj) + return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?")); + + if (is_null(obj, type->OptionalInfo.type)) + return Text$concat(colorize ? Text("\x1b[31m!") : Text("!"), generic_as_text(NULL, false, type->OptionalInfo.type), + colorize ? Text("\x1b[m") : Text("")); + return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), colorize ? Text("\x1b[33m?\x1b[m") : Text("?")); +} + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1 diff --git a/builtins/optionals.h b/builtins/optionals.h new file mode 100644 index 00000000..a0b9b0e0 --- /dev/null +++ b/builtins/optionals.h @@ -0,0 +1,25 @@ +#pragma once + +// Optional types + +#include <gc/cord.h> +#include <stdbool.h> +#include <stdint.h> + +#include "types.h" +#include "util.h" + +#define Bool_t bool +#define yes (Bool_t)true +#define no (Bool_t)false + +extern const Bool_t NULL_BOOL; +extern const Table_t NULL_TABLE; +extern const Array_t NULL_ARRAY; +extern const Int_t NULL_INT; +extern const closure_t NULL_CLOSURE; +extern const Text_t NULL_TEXT; + +Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo *type); + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/pointer.c b/builtins/pointer.c index 0d89e8a6..9067ebd7 100644 --- a/builtins/pointer.c +++ b/builtins/pointer.c @@ -27,10 +27,6 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo *type text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), typename, Text("\x1b[m")); else text = Text$concat(Text$from_str(ptr_info.sigil), typename); - - if (ptr_info.is_optional) - text = Text$concat(text, Text("?")); - return text; } const void *ptr = *(const void**)x; @@ -55,8 +51,6 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo *type Text(".."), Int32$as_text(&depth, false, &Int32$info), colorize ? Text("\x1b[m") : Text("")); - if (ptr_info.is_optional) - text = Text$concat(text, colorize ? Text("\x1b[34;1m?\x1b[m") : Text("?")); return text; } } @@ -73,9 +67,6 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo *type text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), Text("\x1b[m"), pointed); else text = Text$concat(Text$from_str(ptr_info.sigil), pointed); - - if (ptr_info.is_optional) - text = Text$concat(text, Text("?")); return text; } diff --git a/builtins/tomo.h b/builtins/tomo.h index 29f71f71..4a52da7c 100644 --- a/builtins/tomo.h +++ b/builtins/tomo.h @@ -21,6 +21,7 @@ #include "macros.h" #include "memory.h" #include "nums.h" +#include "optionals.h" #include "path.h" #include "pointer.h" #include "range.h" diff --git a/builtins/types.c b/builtins/types.c index 6d9e2408..79f65f71 100644 --- a/builtins/types.c +++ b/builtins/types.c @@ -39,6 +39,7 @@ public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo *type) { (void)fn; Text_t text = Text$from_str(type->FunctionInfo.type_str); + if (fn) text = Text$concat(text, Text(": ...")); if (fn && colorize) text = Text$concat(Text("\x1b[32;1m"), text, Text("\x1b[m")); return text; diff --git a/builtins/types.h b/builtins/types.h index f06730a7..a6cc40c6 100644 --- a/builtins/types.h +++ b/builtins/types.h @@ -17,7 +17,8 @@ typedef Text_t (*text_fn_t)(const void*, bool, const struct TypeInfo*); typedef struct TypeInfo { int64_t size, align; struct { // Anonymous tagged union for convenience - enum { CustomInfo, PointerInfo, TextInfo, ArrayInfo, ChannelInfo, TableInfo, FunctionInfo, TypeInfoInfo, OpaqueInfo, EmptyStruct } tag; + enum { CustomInfo, PointerInfo, TextInfo, ArrayInfo, ChannelInfo, TableInfo, FunctionInfo, + OptionalInfo, TypeInfoInfo, OpaqueInfo, EmptyStruct } tag; union { struct { equal_fn_t equal; @@ -27,7 +28,6 @@ typedef struct TypeInfo { } CustomInfo; struct { const char *sigil; - bool is_optional; const struct TypeInfo *pointed; } PointerInfo; struct { @@ -45,6 +45,9 @@ typedef struct TypeInfo { struct { const char *type_str; } TypeInfoInfo; + struct { + const struct TypeInfo *type; + } OptionalInfo; #pragma GCC diagnostic ignored "-Wpedantic" struct {} OpaqueInfo; struct { @@ -54,8 +57,8 @@ typedef struct TypeInfo { }; } TypeInfo; -#define Pointer$info(sigil_expr, pointed_info, opt) &((TypeInfo){.size=sizeof(void*), .align=__alignof__(void*), \ - .tag=PointerInfo, .PointerInfo={.sigil=sigil_expr, .pointed=pointed_info, .is_optional=opt}}) +#define Pointer$info(sigil_expr, pointed_info) &((TypeInfo){.size=sizeof(void*), .align=__alignof__(void*), \ + .tag=PointerInfo, .PointerInfo={.sigil=sigil_expr, .pointed=pointed_info}}) #define Array$info(item_info) &((TypeInfo){.size=sizeof(Array_t), .align=__alignof__(Array_t), \ .tag=ArrayInfo, .ArrayInfo.item=item_info}) #define Set$info(item_info) &((TypeInfo){.size=sizeof(Table_t), .align=__alignof__(Table_t), \ @@ -70,6 +73,8 @@ typedef struct TypeInfo { .tag=FunctionInfo, .FunctionInfo.type_str=typestr}) #define TypeInfo$info(typestr) &((TypeInfo){.size=sizeof(TypeInfo), .align=__alignof__(TypeInfo), \ .tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr}) +#define Optional$info(t) &((TypeInfo){.size=(t)->size, .align=(t)->align, \ + .tag=OptionalInfo, .OptionalInfo.type=t}) extern const TypeInfo TypeInfo$info; extern const TypeInfo Void$info; |
