Change how types handle metamethods
This commit is contained in:
parent
0b0e0a0a1d
commit
4b5e4cd1f2
3
Makefile
3
Makefile
@ -32,7 +32,8 @@ LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl
|
|||||||
BUILTIN_OBJS=stdlib/siphash.o stdlib/arrays.o stdlib/bools.o stdlib/bytes.o stdlib/channels.o stdlib/nums.o stdlib/integers.o \
|
BUILTIN_OBJS=stdlib/siphash.o stdlib/arrays.o stdlib/bools.o stdlib/bytes.o stdlib/channels.o stdlib/nums.o stdlib/integers.o \
|
||||||
stdlib/pointers.o stdlib/memory.o stdlib/text.o stdlib/threads.o stdlib/c_strings.o stdlib/tables.o \
|
stdlib/pointers.o stdlib/memory.o stdlib/text.o stdlib/threads.o stdlib/c_strings.o stdlib/tables.o \
|
||||||
stdlib/types.o stdlib/util.o stdlib/files.o stdlib/ranges.o stdlib/shell.o stdlib/paths.o stdlib/rng.o \
|
stdlib/types.o stdlib/util.o stdlib/files.o stdlib/ranges.o stdlib/shell.o stdlib/paths.o stdlib/rng.o \
|
||||||
stdlib/optionals.o stdlib/patterns.o stdlib/metamethods.o stdlib/functiontype.o stdlib/stdlib.o stdlib/moments.o
|
stdlib/optionals.o stdlib/patterns.o stdlib/metamethods.o stdlib/functiontype.o stdlib/stdlib.o \
|
||||||
|
stdlib/structs.o stdlib/enums.o stdlib/moments.o
|
||||||
TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm))
|
TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm))
|
||||||
|
|
||||||
all: libtomo.so tomo
|
all: libtomo.so tomo
|
||||||
|
@ -817,7 +817,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
}
|
}
|
||||||
case LangDef: {
|
case LangDef: {
|
||||||
auto def = Match(ast, LangDef);
|
auto def = Match(ast, LangDef);
|
||||||
CORD_appendf(&env->code->typeinfos, "public const TypeInfo_t %r%s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%r}}};\n",
|
CORD_appendf(&env->code->typeinfos, "public const TypeInfo_t %r%s = {%zu, %zu, .metamethods=Text$metamethods, .tag=TextInfo, .TextInfo={%r}};\n",
|
||||||
namespace_prefix(env, env->namespace), def->name, sizeof(Text_t), __alignof__(Text_t),
|
namespace_prefix(env, env->namespace), def->name, sizeof(Text_t), __alignof__(Text_t),
|
||||||
CORD_quoted(def->name));
|
CORD_quoted(def->name));
|
||||||
compile_namespace(env, def->name, def->namespace);
|
compile_namespace(env, def->name, def->namespace);
|
||||||
@ -1507,9 +1507,7 @@ CORD expr_as_text(env_t *env, CORD expr, type_t *t, CORD color)
|
|||||||
CORD name = type_to_cord(t);
|
CORD name = type_to_cord(t);
|
||||||
return CORD_asprintf("%r$as_text(stack(%r), %r, &%r$info)", name, expr, color, name);
|
return CORD_asprintf("%r$as_text(stack(%r), %r, &%r$info)", name, expr, color, name);
|
||||||
}
|
}
|
||||||
case TextType: {
|
case TextType: return CORD_asprintf("Text$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
return CORD_asprintf("Text$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
|
||||||
}
|
|
||||||
case ArrayType: return CORD_asprintf("Array$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case ArrayType: return CORD_asprintf("Array$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
case SetType: return CORD_asprintf("Table$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case SetType: return CORD_asprintf("Table$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
case ChannelType: return CORD_asprintf("Channel$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case ChannelType: return CORD_asprintf("Channel$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
|
2
enums.c
2
enums.c
@ -46,7 +46,7 @@ void compile_enum_def(env_t *env, ast_t *ast)
|
|||||||
num_tags += 1;
|
num_tags += 1;
|
||||||
|
|
||||||
type_t *t = Table$str_get(*env->types, def->name);
|
type_t *t = Table$str_get(*env->types, def->name);
|
||||||
CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r = {%zu, %zu, {.tag=EnumInfo, .EnumInfo={.name=\"%s\", "
|
CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r = {%zu, %zu, .metamethods=Enum$metamethods, {.tag=EnumInfo, .EnumInfo={.name=\"%s\", "
|
||||||
".num_tags=%d, .tags=(NamedType_t[]){",
|
".num_tags=%d, .tags=(NamedType_t[]){",
|
||||||
full_name, type_size(t), type_align(t), def->name, num_tags);
|
full_name, type_size(t), type_align(t), def->name, num_tags);
|
||||||
|
|
||||||
|
10
repl.c
10
repl.c
@ -121,24 +121,20 @@ const TypeInfo_t *type_to_type_info(type_t *t)
|
|||||||
case TextType: return &Text$info;
|
case TextType: return &Text$info;
|
||||||
case ArrayType: {
|
case ArrayType: {
|
||||||
const TypeInfo_t *item_info = type_to_type_info(Match(t, ArrayType)->item_type);
|
const TypeInfo_t *item_info = type_to_type_info(Match(t, ArrayType)->item_type);
|
||||||
const TypeInfo_t array_info = {.size=sizeof(Array_t), .align=__alignof__(Array_t),
|
TypeInfo_t array_info = *Array$info(item_info);
|
||||||
.tag=ArrayInfo, .ArrayInfo.item=item_info};
|
|
||||||
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &array_info, sizeof(TypeInfo_t));
|
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &array_info, sizeof(TypeInfo_t));
|
||||||
}
|
}
|
||||||
case TableType: {
|
case TableType: {
|
||||||
const TypeInfo_t *key_info = type_to_type_info(Match(t, TableType)->key_type);
|
const TypeInfo_t *key_info = type_to_type_info(Match(t, TableType)->key_type);
|
||||||
const TypeInfo_t *value_info = type_to_type_info(Match(t, TableType)->value_type);
|
const TypeInfo_t *value_info = type_to_type_info(Match(t, TableType)->value_type);
|
||||||
const TypeInfo_t table_info = {
|
const TypeInfo_t table_info = *Table$info(key_info, value_info);
|
||||||
.size=sizeof(Table_t), .align=__alignof__(Table_t),
|
|
||||||
.tag=TableInfo, .TableInfo.key=key_info, .TableInfo.value=value_info};
|
|
||||||
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &table_info, sizeof(TypeInfo_t));
|
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &table_info, sizeof(TypeInfo_t));
|
||||||
}
|
}
|
||||||
case PointerType: {
|
case PointerType: {
|
||||||
auto ptr = Match(t, PointerType);
|
auto ptr = Match(t, PointerType);
|
||||||
CORD sigil = ptr->is_view ? "&" : "@";
|
CORD sigil = ptr->is_view ? "&" : "@";
|
||||||
const TypeInfo_t *pointed_info = type_to_type_info(ptr->pointed);
|
const TypeInfo_t *pointed_info = type_to_type_info(ptr->pointed);
|
||||||
const TypeInfo_t pointer_info = {.size=sizeof(void*), .align=__alignof__(void*),
|
const TypeInfo_t pointer_info = *Pointer$info(sigil, pointed_info);
|
||||||
.tag=PointerInfo, .PointerInfo={.sigil=sigil, .pointed=pointed_info}};
|
|
||||||
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &pointer_info, sizeof(TypeInfo_t));
|
return memcpy(GC_MALLOC(sizeof(TypeInfo_t)), &pointer_info, sizeof(TypeInfo_t));
|
||||||
}
|
}
|
||||||
default: errx(1, "Unsupported type: %T", t);
|
default: errx(1, "Unsupported type: %T", t);
|
||||||
|
@ -283,8 +283,7 @@ public void *Array$random(Array_t arr, RNG_t rng)
|
|||||||
public Table_t Array$counts(Array_t arr, const TypeInfo_t *type)
|
public Table_t Array$counts(Array_t arr, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
Table_t counts = {};
|
Table_t counts = {};
|
||||||
const TypeInfo_t count_type = {.size=sizeof(Table_t), .align=__alignof__(Table_t),
|
const TypeInfo_t count_type = *Table$info(type->ArrayInfo.item, &Int$info);
|
||||||
.tag=TableInfo, .TableInfo.key=type->ArrayInfo.item, .TableInfo.value=&Int$info};
|
|
||||||
for (int64_t i = 0; i < arr.length; i++) {
|
for (int64_t i = 0; i < arr.length; i++) {
|
||||||
void *key = arr.data + i*arr.stride;
|
void *key = arr.data + i*arr.stride;
|
||||||
int64_t *count = Table$get(counts, key, &count_type);
|
int64_t *count = Table$get(counts, key, &count_type);
|
||||||
@ -515,14 +514,15 @@ public void Array$clear(Array_t *array)
|
|||||||
*array = (Array_t){.data=0, .length=0};
|
*array = (Array_t){.data=0, .length=0};
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo_t *type)
|
public int32_t Array$compare(const void *vx, const void *vy, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
|
const Array_t *x = (Array_t*)vx, *y = (Array_t*)vy;
|
||||||
// Early out for arrays with the same data, e.g. two copies of the same array:
|
// Early out for arrays with the same data, e.g. two copies of the same array:
|
||||||
if (x->data == y->data && x->stride == y->stride)
|
if (x->data == y->data && x->stride == y->stride)
|
||||||
return (x->length > y->length) - (x->length < y->length);
|
return (x->length > y->length) - (x->length < y->length);
|
||||||
|
|
||||||
const TypeInfo_t *item = type->ArrayInfo.item;
|
const TypeInfo_t *item = type->ArrayInfo.item;
|
||||||
if (item->tag == PointerInfo || (item->tag == CustomInfo && item->CustomInfo.compare == NULL)) { // data comparison
|
if (item->tag == PointerInfo || !item->metamethods.compare) { // data comparison
|
||||||
int64_t item_padded_size = type->ArrayInfo.item->size;
|
int64_t item_padded_size = type->ArrayInfo.item->size;
|
||||||
if (type->ArrayInfo.item->align > 1 && item_padded_size % type->ArrayInfo.item->align)
|
if (type->ArrayInfo.item->align > 1 && item_padded_size % type->ArrayInfo.item->align)
|
||||||
errx(1, "Item size is not padded!");
|
errx(1, "Item size is not padded!");
|
||||||
@ -545,13 +545,14 @@ public int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo_
|
|||||||
return (x->length > y->length) - (x->length < y->length);
|
return (x->length > y->length) - (x->length < y->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Array$equal(const Array_t *x, const Array_t *y, const TypeInfo_t *type)
|
public bool Array$equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
return x == y || (x->length == y->length && Array$compare(x, y, type) == 0);
|
return x == y || (((Array_t*)x)->length == ((Array_t*)y)->length && Array$compare(x, y, type) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Array$as_text(const Array_t *arr, bool colorize, const TypeInfo_t *type)
|
public Text_t Array$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
|
Array_t *arr = (Array_t*)obj;
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return Text$concat(Text("["), generic_as_text(NULL, false, type->ArrayInfo.item), Text("]"));
|
return Text$concat(Text("["), generic_as_text(NULL, false, type->ArrayInfo.item), Text("]"));
|
||||||
|
|
||||||
@ -567,12 +568,13 @@ public Text_t Array$as_text(const Array_t *arr, bool colorize, const TypeInfo_t
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint64_t Array$hash(const Array_t *arr, const TypeInfo_t *type)
|
public uint64_t Array$hash(const void *obj, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
|
const Array_t *arr = (Array_t*)obj;
|
||||||
const TypeInfo_t *item = type->ArrayInfo.item;
|
const TypeInfo_t *item = type->ArrayInfo.item;
|
||||||
siphash sh;
|
siphash sh;
|
||||||
siphashinit(&sh, sizeof(uint64_t[arr->length]));
|
siphashinit(&sh, sizeof(uint64_t[arr->length]));
|
||||||
if (item->tag == PointerInfo || (item->tag == CustomInfo && item->CustomInfo.hash == NULL && item->size == sizeof(void*))) { // Raw data hash
|
if (item->tag == PointerInfo || (!item->metamethods.hash && item->size == sizeof(void*))) { // Raw data hash
|
||||||
for (int64_t i = 0; i < arr->length; i++)
|
for (int64_t i = 0; i < arr->length; i++)
|
||||||
siphashadd64bits(&sh, (uint64_t)(arr->data + i*arr->stride));
|
siphashadd64bits(&sh, (uint64_t)(arr->data + i*arr->stride));
|
||||||
} else {
|
} else {
|
||||||
@ -694,4 +696,9 @@ public Int_t Array$binary_search(Array_t array, void *target, Closure_t comparis
|
|||||||
return I(lo+1); // Return the index where the target would be inserted
|
return I(lo+1); // Return the index where the target would be inserted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PUREFUNC bool Array$is_none(const void *obj, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return ((Array_t*)obj)->length < 0;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -85,10 +85,11 @@ PUREFUNC Array_t Array$to(Array_t array, Int_t last);
|
|||||||
PUREFUNC Array_t Array$by(Array_t array, Int_t stride, int64_t padded_item_size);
|
PUREFUNC Array_t Array$by(Array_t array, Int_t stride, int64_t padded_item_size);
|
||||||
PUREFUNC Array_t Array$reversed(Array_t array, int64_t padded_item_size);
|
PUREFUNC Array_t Array$reversed(Array_t array, int64_t padded_item_size);
|
||||||
Array_t Array$concat(Array_t x, Array_t y, int64_t padded_item_size);
|
Array_t Array$concat(Array_t x, Array_t y, int64_t padded_item_size);
|
||||||
PUREFUNC uint64_t Array$hash(const Array_t *arr, const TypeInfo_t *type);
|
PUREFUNC uint64_t Array$hash(const void *arr, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Array$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Array$equal(const Array_t *x, const Array_t *y, const TypeInfo_t *type);
|
PUREFUNC bool Array$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
Text_t Array$as_text(const Array_t *arr, bool colorize, const TypeInfo_t *type);
|
PUREFUNC bool Array$is_none(const void *obj, const TypeInfo_t*);
|
||||||
|
Text_t Array$as_text(const void *arr, bool colorize, const TypeInfo_t *type);
|
||||||
void Array$heapify(Array_t *heap, Closure_t comparison, int64_t padded_item_size);
|
void Array$heapify(Array_t *heap, Closure_t comparison, int64_t padded_item_size);
|
||||||
void Array$heap_push(Array_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size);
|
void Array$heap_push(Array_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size);
|
||||||
#define Array$heap_push_value(heap, _value, comparison, padded_item_size) ({ __typeof(_value) value = _value; Array$heap_push(heap, &value, comparison, padded_item_size); })
|
#define Array$heap_push_value(heap, _value, comparison, padded_item_size) ({ __typeof(_value) value = _value; Array$heap_push(heap, &value, comparison, padded_item_size); })
|
||||||
@ -100,4 +101,16 @@ Int_t Array$binary_search(Array_t array, void *target, Closure_t comparison);
|
|||||||
#define Array$binary_search_value(array, target, comparison) \
|
#define Array$binary_search_value(array, target, comparison) \
|
||||||
({ __typeof(target) _target = target; Array$binary_search(array, &_target, comparison); })
|
({ __typeof(target) _target = target; Array$binary_search(array, &_target, comparison); })
|
||||||
|
|
||||||
|
#define Array$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Array$as_text, \
|
||||||
|
.compare=Array$compare, \
|
||||||
|
.equal=Array$equal, \
|
||||||
|
.hash=Array$hash, \
|
||||||
|
.is_none=Array$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Array$info(item_info) &((TypeInfo_t){.size=sizeof(Array_t), .align=__alignof__(Array_t), \
|
||||||
|
.tag=ArrayInfo, .ArrayInfo.item=item_info, \
|
||||||
|
.metamethods=Array$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -12,14 +12,13 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
PUREFUNC public Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo_t *type)
|
PUREFUNC public Text_t Bool$as_text(const void *b, bool colorize, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
|
||||||
if (!b) return Text("Bool");
|
if (!b) return Text("Bool");
|
||||||
if (colorize)
|
if (colorize)
|
||||||
return *b ? Text("\x1b[35myes\x1b[m") : Text("\x1b[35mno\x1b[m");
|
return *(Bool_t*)b ? Text("\x1b[35myes\x1b[m") : Text("\x1b[35mno\x1b[m");
|
||||||
else
|
else
|
||||||
return *b ? Text("yes") : Text("no");
|
return *(Bool_t*)b ? Text("yes") : Text("no");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public OptionalBool_t Bool$parse(Text_t text)
|
PUREFUNC public OptionalBool_t Bool$parse(Text_t text)
|
||||||
@ -39,11 +38,20 @@ PUREFUNC public OptionalBool_t Bool$parse(Text_t text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Bool$is_none(const void *b, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(OptionalBool_t*)b == NONE_BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const metamethods_t Bool$metamethods = {
|
||||||
|
.as_text=Bool$as_text,
|
||||||
|
.is_none=Bool$is_none,
|
||||||
|
};
|
||||||
|
|
||||||
public const TypeInfo_t Bool$info = {
|
public const TypeInfo_t Bool$info = {
|
||||||
.size=sizeof(bool),
|
.size=sizeof(bool),
|
||||||
.align=__alignof__(bool),
|
.align=__alignof__(bool),
|
||||||
.tag=CustomInfo,
|
.metamethods=Bool$metamethods,
|
||||||
.CustomInfo={.as_text=(void*)Bool$as_text},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#define yes (Bool_t)true
|
#define yes (Bool_t)true
|
||||||
#define no (Bool_t)false
|
#define no (Bool_t)false
|
||||||
|
|
||||||
PUREFUNC Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo_t *type);
|
PUREFUNC Text_t Bool$as_text(const void *b, bool colorize, const TypeInfo_t *type);
|
||||||
OptionalBool_t Bool$parse(Text_t text);
|
OptionalBool_t Bool$parse(Text_t text);
|
||||||
|
|
||||||
extern const TypeInfo_t Bool$info;
|
extern const TypeInfo_t Bool$info;
|
||||||
|
@ -10,11 +10,10 @@
|
|||||||
public const Byte_t Byte$min = 0;
|
public const Byte_t Byte$min = 0;
|
||||||
public const Byte_t Byte$max = UINT8_MAX;
|
public const Byte_t Byte$max = UINT8_MAX;
|
||||||
|
|
||||||
PUREFUNC public Text_t Byte$as_text(const Byte_t *b, bool colorize, const TypeInfo_t *type)
|
PUREFUNC public Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
|
||||||
if (!b) return Text("Byte");
|
if (!b) return Text("Byte");
|
||||||
return Text$format(colorize ? "\x1b[35m0x%02X\x1b[m" : "0x%02X", *b);
|
return Text$format(colorize ? "\x1b[35m0x%02X\x1b[m" : "0x%02X", *(Byte_t*)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
|
public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
|
||||||
@ -33,8 +32,9 @@ public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
|
|||||||
public const TypeInfo_t Byte$info = {
|
public const TypeInfo_t Byte$info = {
|
||||||
.size=sizeof(Byte_t),
|
.size=sizeof(Byte_t),
|
||||||
.align=__alignof__(Byte_t),
|
.align=__alignof__(Byte_t),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={.as_text=(void*)Byte$as_text},
|
.as_text=Byte$as_text,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#define Byte_t uint8_t
|
#define Byte_t uint8_t
|
||||||
#define Byte(b) ((Byte_t)(b))
|
#define Byte(b) ((Byte_t)(b))
|
||||||
|
|
||||||
PUREFUNC Text_t Byte$as_text(const Byte_t *b, bool colorize, const TypeInfo_t *type);
|
PUREFUNC Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo_t *type);
|
||||||
|
|
||||||
#define Byte_to_Int64(b, _) ((Int64_t)(b))
|
#define Byte_to_Int64(b, _) ((Int64_t)(b))
|
||||||
#define Byte_to_Int32(b, _) ((Int32_t)(b))
|
#define Byte_to_Int32(b, _) ((Int32_t)(b))
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
#include "siphash.h"
|
#include "siphash.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
public Text_t CString$as_text(const char **c_string, bool colorize, const TypeInfo_t *info)
|
public Text_t CString$as_text(const void *c_string, bool colorize, const TypeInfo_t *info)
|
||||||
{
|
{
|
||||||
(void)info;
|
(void)info;
|
||||||
if (!c_string) return Text("CString");
|
if (!c_string) return Text("CString");
|
||||||
Text_t text = Text$from_str(*c_string);
|
Text_t text = Text$from_str(*(char**)c_string);
|
||||||
return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("), Text$quoted(text, colorize), Text(")"));
|
return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("), Text$quoted(text, colorize), Text(")"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,33 +23,43 @@ public Text_t CString$as_text_simple(const char *str)
|
|||||||
return Text$format("%s", str);
|
return Text$format("%s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t CString$compare(const char **x, const char **y)
|
PUREFUNC public int32_t CString$compare(const void *x, const void *y, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
if (x == y)
|
if (x == y)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!*x != !*y)
|
if (!*(char**)x != !*(char**)y)
|
||||||
return (!*y) - (!*x);
|
return (!*(char**)y) - (!*(char**)x);
|
||||||
|
|
||||||
return strcmp(*x, *y);
|
return strcmp(*(char**)x, *(char**)y);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool CString$equal(const char **x, const char **y)
|
PUREFUNC public bool CString$equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
return CString$compare(x, y) == 0;
|
return CString$compare(x, y, type) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public uint64_t CString$hash(const char **c_str)
|
PUREFUNC public uint64_t CString$hash(const void *c_str, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
if (!*c_str) return 0;
|
if (!*(char**)c_str) return 0;
|
||||||
return siphash24((void*)*c_str, strlen(*c_str));
|
return siphash24(*(void**)c_str, strlen(*(char**)c_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool CString$is_none(const void *c_str, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(char**)c_str == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo_t CString$info = {
|
public const TypeInfo_t CString$info = {
|
||||||
.size=sizeof(char*),
|
.size=sizeof(char*),
|
||||||
.align=__alignof__(char*),
|
.align=__alignof__(char*),
|
||||||
.tag=CStringInfo,
|
.metamethods={
|
||||||
.CustomInfo={.as_text=(void*)CString$as_text, .compare=(void*)CString$compare, .equal=(void*)CString$equal, .hash=(void*)CString$hash},
|
.hash=CString$hash,
|
||||||
|
.compare=CString$compare,
|
||||||
|
.equal=CString$equal,
|
||||||
|
.as_text=CString$as_text,
|
||||||
|
.is_none=CString$is_none,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
Text_t CString$as_text(char **str, bool colorize, const TypeInfo_t *info);
|
Text_t CString$as_text(char **str, bool colorize, const TypeInfo_t *info);
|
||||||
Text_t CString$as_text_simple(const char *str);
|
Text_t CString$as_text_simple(const char *str);
|
||||||
PUREFUNC int CString$compare(const char **x, const char **y);
|
PUREFUNC int CString$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool CString$equal(const char **x, const char **y);
|
PUREFUNC bool CString$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC uint64_t CString$hash(const char **str);
|
PUREFUNC uint64_t CString$hash(const void *str, const TypeInfo_t *type);
|
||||||
|
|
||||||
extern const TypeInfo_t CString$info;
|
extern const TypeInfo_t CString$info;
|
||||||
|
|
||||||
|
@ -99,25 +99,23 @@ public void Channel$clear(Channel_t *channel)
|
|||||||
(void)pthread_cond_signal(&channel->cond);
|
(void)pthread_cond_signal(&channel->cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public uint64_t Channel$hash(Channel_t **channel, const TypeInfo_t *type)
|
PUREFUNC public uint64_t Channel$hash(const void *channel, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
(void)type;
|
(void)type;
|
||||||
return siphash24((void*)*channel, sizeof(Channel_t*));
|
return siphash24(*(void**)channel, sizeof(Channel_t*));
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t Channel$compare(Channel_t **x, Channel_t **y, const TypeInfo_t *type)
|
PUREFUNC public int32_t Channel$compare(const void *x, const void *y, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
return (*(Channel_t**)x > *(Channel_t**)y) - (*(Channel_t**)x < *(Channel_t**)y);
|
||||||
return (*x > *y) - (*x < *y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool Channel$equal(Channel_t **x, Channel_t **y, const TypeInfo_t *type)
|
PUREFUNC public bool Channel$equal(const void *x, const void *y, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
return (*(void**)x == *(void**)y);
|
||||||
return (*x == *y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Channel$as_text(Channel_t **channel, bool colorize, const TypeInfo_t *type)
|
public Text_t Channel$as_text(const void *channel, bool colorize, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
const TypeInfo_t *item_type = type->ChannelInfo.item;
|
const TypeInfo_t *item_type = type->ChannelInfo.item;
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
@ -129,9 +127,14 @@ public Text_t Channel$as_text(Channel_t **channel, bool colorize, const TypeInfo
|
|||||||
colorize ? Text("\x1b[34;1m|:") : Text("|:"),
|
colorize ? Text("\x1b[34;1m|:") : Text("|:"),
|
||||||
typename,
|
typename,
|
||||||
Text("|<"),
|
Text("|<"),
|
||||||
Int64$hex((int64_t)(void*)*channel, I_small(0), true, true),
|
Int64$hex(*(int64_t*)channel, I_small(0), true, true),
|
||||||
colorize ? Text(">\x1b[m") : Text(">")
|
colorize ? Text(">\x1b[m") : Text(">")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PUREFUNC bool Channel$is_none(const void *obj, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(void**)obj == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -20,9 +20,22 @@ void Channel$peek(Channel_t *channel, void *out, bool front, int64_t item_size);
|
|||||||
#define Channel$peek_value(channel, front, t) ({ t _val; Channel$peek(channel, &_val, front, sizeof(t)); _val; })
|
#define Channel$peek_value(channel, front, t) ({ t _val; Channel$peek(channel, &_val, front, sizeof(t)); _val; })
|
||||||
void Channel$clear(Channel_t *channel);
|
void Channel$clear(Channel_t *channel);
|
||||||
Array_t Channel$view(Channel_t *channel);
|
Array_t Channel$view(Channel_t *channel);
|
||||||
PUREFUNC uint64_t Channel$hash(Channel_t **channel, const TypeInfo_t *type);
|
PUREFUNC uint64_t Channel$hash(const void *channel, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Channel$compare(Channel_t **x, Channel_t **y, const TypeInfo_t *type);
|
PUREFUNC int32_t Channel$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Channel$equal(Channel_t **x, Channel_t **y, const TypeInfo_t *type);
|
PUREFUNC bool Channel$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
Text_t Channel$as_text(Channel_t **channel, bool colorize, const TypeInfo_t *type);
|
Text_t Channel$as_text(const void *channel, bool colorize, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Channel$is_none(const void *obj, const TypeInfo_t*);
|
||||||
|
|
||||||
|
#define Channel$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Channel$as_text, \
|
||||||
|
.compare=Channel$compare, \
|
||||||
|
.equal=Channel$equal, \
|
||||||
|
.hash=Channel$hash, \
|
||||||
|
.is_none=Channel$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Channel$info(item_info) &((TypeInfo_t){.size=sizeof(Channel_t), .align=__alignof__(Channel_t), \
|
||||||
|
.tag=ChannelInfo, .ChannelInfo.item=item_info, \
|
||||||
|
.metamethods=Channel$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
92
stdlib/enums.c
Normal file
92
stdlib/enums.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// Metamethods for enums
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "arrays.h"
|
||||||
|
#include "bools.h"
|
||||||
|
#include "channels.h"
|
||||||
|
#include "functiontype.h"
|
||||||
|
#include "metamethods.h"
|
||||||
|
#include "optionals.h"
|
||||||
|
#include "pointers.h"
|
||||||
|
#include "siphash.h"
|
||||||
|
#include "tables.h"
|
||||||
|
#include "text.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
PUREFUNC public uint64_t Enum$hash(const void *obj, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
int32_t tag = *(int32_t*)obj;
|
||||||
|
uint32_t components[2] = {(uint32_t)tag, 0};
|
||||||
|
|
||||||
|
const TypeInfo_t *value = type->EnumInfo.tags[tag-1].type;
|
||||||
|
if (value && value->size > 0) {
|
||||||
|
ptrdiff_t byte_offset = sizeof(int32_t);
|
||||||
|
if (value->align && byte_offset % value->align > 0)
|
||||||
|
byte_offset += value->align - (byte_offset % value->align);
|
||||||
|
components[1] = generic_hash(obj + byte_offset, value);
|
||||||
|
}
|
||||||
|
return siphash24((void*)components, sizeof(components));
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public int32_t Enum$compare(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (x == y) return 0;
|
||||||
|
|
||||||
|
int32_t x_tag = *(int32_t*)x;
|
||||||
|
int32_t y_tag = *(int32_t*)y;
|
||||||
|
if (x_tag != y_tag)
|
||||||
|
return x_tag > y_tag ? 1 : -1;
|
||||||
|
|
||||||
|
const TypeInfo_t *value = type->EnumInfo.tags[x_tag-1].type;
|
||||||
|
if (value && value->size > 0) {
|
||||||
|
ptrdiff_t byte_offset = sizeof(int32_t);
|
||||||
|
if (value->align && byte_offset % value->align > 0)
|
||||||
|
byte_offset += value->align - (byte_offset % value->align);
|
||||||
|
return generic_compare(x + byte_offset, y + byte_offset, value);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Enum$equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (x == y) return true;
|
||||||
|
|
||||||
|
int32_t x_tag = *(int32_t*)x;
|
||||||
|
int32_t y_tag = *(int32_t*)y;
|
||||||
|
if (x_tag != y_tag)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const TypeInfo_t *value = type->EnumInfo.tags[x_tag-1].type;
|
||||||
|
if (value && value->size > 0) {
|
||||||
|
ptrdiff_t byte_offset = sizeof(int32_t);
|
||||||
|
if (value->align && byte_offset % value->align > 0)
|
||||||
|
byte_offset += value->align - (byte_offset % value->align);
|
||||||
|
return generic_equal(x + byte_offset, y + byte_offset, value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (!obj) return Text$from_str(type->EnumInfo.name);
|
||||||
|
|
||||||
|
int32_t tag = *(int32_t*)obj;
|
||||||
|
NamedType_t value = type->EnumInfo.tags[tag-1];
|
||||||
|
if (!value.type || value.type->size == 0)
|
||||||
|
return Text$format(colorize ? "\x1b[36;1m%s\x1b[m.\x1b[1m%s\x1b[m" : "%s.%s", type->EnumInfo.name, value.name);
|
||||||
|
|
||||||
|
ptrdiff_t byte_offset = sizeof(int32_t);
|
||||||
|
if (value.type->align && byte_offset % value.type->align > 0)
|
||||||
|
byte_offset += value.type->align - (byte_offset % value.type->align);
|
||||||
|
return Text$concat(Text$format(colorize ? "\x1b[36;1m%s\x1b[m." : "%s.", type->EnumInfo.name),
|
||||||
|
generic_as_text(obj + byte_offset, colorize, value.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Enum$is_none(const void *x, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(int32_t*)x == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
24
stdlib/enums.h
Normal file
24
stdlib/enums.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Metamethods for enums
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
PUREFUNC uint64_t Enum$hash(const void *obj, const TypeInfo_t *type);
|
||||||
|
PUREFUNC int32_t Enum$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Enum$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Enum$is_none(const void *obj, const TypeInfo_t *type);
|
||||||
|
|
||||||
|
#define Enum$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Enum$as_text, \
|
||||||
|
.compare=Enum$compare, \
|
||||||
|
.equal=Enum$equal, \
|
||||||
|
.hash=Enum$hash, \
|
||||||
|
.is_none=Enum$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
@ -1,6 +1,9 @@
|
|||||||
// Logic for handling function type values
|
// Logic for handling function type values
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "functiontype.h"
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -32,4 +35,9 @@ public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(void**)obj == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -1,9 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
// Logic for handling function type values
|
// Logic for handling function type values
|
||||||
|
|
||||||
void register_function(void *fn, Text_t name);
|
void register_function(void *fn, Text_t name);
|
||||||
Text_t *get_function_name(void *fn);
|
Text_t *get_function_name(void *fn);
|
||||||
Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type);
|
Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t*);
|
||||||
|
|
||||||
|
#define Func$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Func$as_text, \
|
||||||
|
.is_none=Func$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Function$info(typestr) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
|
||||||
|
.tag=FunctionInfo, .FunctionInfo.type_str=typestr, \
|
||||||
|
.metamethods=Func$metamethods})
|
||||||
|
#define Closure$info(typestr) &((TypeInfo_t){.size=sizeof(void*[2]), .align=__alignof__(void*), \
|
||||||
|
.tag=FunctionInfo, .FunctionInfo.type_str=typestr, \
|
||||||
|
.metamethods=Func$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -23,17 +23,16 @@ public Text_t Int$value_as_text(Int_t i) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Int$as_text(const Int_t *i, bool colorize, const TypeInfo_t *type) {
|
public Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t*) {
|
||||||
(void)type;
|
|
||||||
if (!i) return Text("Int");
|
if (!i) return Text("Int");
|
||||||
|
Text_t text = Int$value_as_text(*(Int_t*)i);
|
||||||
Text_t text = Int$value_as_text(*i);
|
|
||||||
if (colorize) text = Text$concat(Text("\x1b[35m"), text, Text("\x1b[m"));
|
if (colorize) text = Text$concat(Text("\x1b[35m"), text, Text("\x1b[m"));
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo_t *type) {
|
public PUREFUNC int32_t Int$compare(const void *vx, const void *vy, const TypeInfo_t*) {
|
||||||
(void)type;
|
Int_t *x = (Int_t*)vx;
|
||||||
|
Int_t *y = (Int_t*)vy;
|
||||||
if (__builtin_expect(((x->small | y->small) & 1) == 0, 0))
|
if (__builtin_expect(((x->small | y->small) & 1) == 0, 0))
|
||||||
return x->big == y->big ? 0 : mpz_cmp(*x->big, *y->big);
|
return x->big == y->big ? 0 : mpz_cmp(*x->big, *y->big);
|
||||||
return (x->small > y->small) - (x->small < y->small);
|
return (x->small > y->small) - (x->small < y->small);
|
||||||
@ -45,8 +44,9 @@ public PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) {
|
|||||||
return (x.small > y.small) - (x.small < y.small);
|
return (x.small > y.small) - (x.small < y.small);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo_t *type) {
|
public PUREFUNC bool Int$equal(const void *vx, const void *vy, const TypeInfo_t*) {
|
||||||
(void)type;
|
Int_t *x = (Int_t*)vx;
|
||||||
|
Int_t *y = (Int_t*)vy;
|
||||||
return x->small == y->small || (__builtin_expect(((x->small | y->small) & 1) == 0, 0) && mpz_cmp(*x->big, *y->big) == 0);
|
return x->small == y->small || (__builtin_expect(((x->small | y->small) & 1) == 0, 0) && mpz_cmp(*x->big, *y->big) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +54,8 @@ public PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y) {
|
|||||||
return x.small == y.small || (__builtin_expect(((x.small | y.small) & 1) == 0, 0) && mpz_cmp(*x.big, *y.big) == 0);
|
return x.small == y.small || (__builtin_expect(((x.small | y.small) & 1) == 0, 0) && mpz_cmp(*x.big, *y.big) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC uint64_t Int$hash(const Int_t *x, const TypeInfo_t *type) {
|
public PUREFUNC uint64_t Int$hash(const void *vx, const TypeInfo_t*) {
|
||||||
(void)type;
|
Int_t *x = (Int_t*)vx;
|
||||||
if (__builtin_expect(x->small & 1, 1)) {
|
if (__builtin_expect(x->small & 1, 1)) {
|
||||||
return siphash24((void*)x, sizeof(Int_t));
|
return siphash24((void*)x, sizeof(Int_t));
|
||||||
} else {
|
} else {
|
||||||
@ -362,31 +362,33 @@ public Int_t Int$prev_prime(Int_t x)
|
|||||||
return Int$from_mpz(p);
|
return Int$from_mpz(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Int$is_none(const void *i, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return ((Int_t*)i)->small == 0;
|
||||||
|
}
|
||||||
|
|
||||||
public const TypeInfo_t Int$info = {
|
public const TypeInfo_t Int$info = {
|
||||||
.size=sizeof(Int_t),
|
.size=sizeof(Int_t),
|
||||||
.align=__alignof__(Int_t),
|
.align=__alignof__(Int_t),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={
|
.compare=Int$compare,
|
||||||
.compare=(void*)Int$compare,
|
.equal=Int$equal,
|
||||||
.equal=(void*)Int$equal,
|
.hash=Int$hash,
|
||||||
.hash=(void*)Int$hash,
|
.as_text=Int$as_text,
|
||||||
.as_text=(void*)Int$as_text,
|
.is_none=Int$is_none,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val, to_attr)\
|
#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val, to_attr)\
|
||||||
public Text_t KindOfInt ## $as_text(const c_type *i, bool colorize, const TypeInfo_t *type) { \
|
public Text_t KindOfInt ## $as_text(const void *i, bool colorize, const TypeInfo_t*) { \
|
||||||
(void)type; \
|
|
||||||
if (!i) return Text(#KindOfInt); \
|
if (!i) return Text(#KindOfInt); \
|
||||||
return Text$format(colorize ? "\x1b[35m" fmt "\x1b[m" : fmt, *i); \
|
return Text$format(colorize ? "\x1b[35m" fmt "\x1b[m" : fmt, *(c_type*)i); \
|
||||||
} \
|
} \
|
||||||
public PUREFUNC int32_t KindOfInt ## $compare(const c_type *x, const c_type *y, const TypeInfo_t *type) { \
|
public PUREFUNC int32_t KindOfInt ## $compare(const void *x, const void *y, const TypeInfo_t*) { \
|
||||||
(void)type; \
|
return (*(c_type*)x > *(c_type*)y) - (*(c_type*)x < *(c_type*)y); \
|
||||||
return (*x > *y) - (*x < *y); \
|
|
||||||
} \
|
} \
|
||||||
public PUREFUNC bool KindOfInt ## $equal(const c_type *x, const c_type *y, const TypeInfo_t *type) { \
|
public PUREFUNC bool KindOfInt ## $equal(const void *x, const void *y, const TypeInfo_t*) { \
|
||||||
(void)type; \
|
return *(c_type*)x == *(c_type*)y; \
|
||||||
return *x == *y; \
|
|
||||||
} \
|
} \
|
||||||
public Text_t KindOfInt ## $format(c_type i, Int_t digits_int) { \
|
public Text_t KindOfInt ## $format(c_type i, Int_t digits_int) { \
|
||||||
Int_t as_int = KindOfInt##_to_Int(i); \
|
Int_t as_int = KindOfInt##_to_Int(i); \
|
||||||
@ -428,8 +430,10 @@ public const TypeInfo_t Int$info = {
|
|||||||
public const TypeInfo_t KindOfInt##$info = { \
|
public const TypeInfo_t KindOfInt##$info = { \
|
||||||
.size=sizeof(c_type), \
|
.size=sizeof(c_type), \
|
||||||
.align=__alignof__(c_type), \
|
.align=__alignof__(c_type), \
|
||||||
.tag=CustomInfo, \
|
.metamethods={ \
|
||||||
.CustomInfo={.compare=(void*)KindOfInt##$compare, .as_text=(void*)KindOfInt##$as_text}, \
|
.compare=KindOfInt##$compare, \
|
||||||
|
.as_text=KindOfInt##$as_text, \
|
||||||
|
}, \
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_INT_TYPE(int64_t, Int64, "%ld", INT64_MIN, INT64_MAX, __attribute__(()))
|
DEFINE_INT_TYPE(int64_t, Int64, "%ld", INT64_MIN, INT64_MAX, __attribute__(()))
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
c_type i; \
|
c_type i; \
|
||||||
bool is_null:1; \
|
bool is_null:1; \
|
||||||
} Optional ## type_name ## _t; \
|
} Optional ## type_name ## _t; \
|
||||||
Text_t type_name ## $as_text(const c_type *i, bool colorize, const TypeInfo_t *type); \
|
Text_t type_name ## $as_text(const void *i, bool colorize, const TypeInfo_t *type); \
|
||||||
PUREFUNC int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo_t *type); \
|
PUREFUNC int32_t type_name ## $compare(const void *x, const void *y, const TypeInfo_t *type); \
|
||||||
PUREFUNC bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo_t *type); \
|
PUREFUNC bool type_name ## $equal(const void *x, const void *y, const TypeInfo_t *type); \
|
||||||
Text_t type_name ## $format(c_type i, Int_t digits); \
|
Text_t type_name ## $format(c_type i, Int_t digits); \
|
||||||
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
|
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
|
||||||
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
|
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
|
||||||
@ -85,12 +85,12 @@ DEFINE_INT_TYPE(int8_t, Int8, CONSTFUNC)
|
|||||||
|
|
||||||
#define OptionalInt_t Int_t
|
#define OptionalInt_t Int_t
|
||||||
|
|
||||||
Text_t Int$as_text(const Int_t *i, bool colorize, const TypeInfo_t *type);
|
Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t *type);
|
||||||
Text_t Int$value_as_text(Int_t i);
|
Text_t Int$value_as_text(Int_t i);
|
||||||
PUREFUNC uint64_t Int$hash(const Int_t *x, const TypeInfo_t *type);
|
PUREFUNC uint64_t Int$hash(const void *x, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Int$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y);
|
PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y);
|
||||||
PUREFUNC bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo_t *type);
|
PUREFUNC bool Int$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y);
|
PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y);
|
||||||
Text_t Int$format(Int_t i, Int_t digits);
|
Text_t Int$format(Int_t i, Int_t digits);
|
||||||
Text_t Int$hex(Int_t i, Int_t digits, bool uppercase, bool prefix);
|
Text_t Int$hex(Int_t i, Int_t digits, bool uppercase, bool prefix);
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
public Text_t Memory__as_text(const void *p, bool colorize, const TypeInfo_t *type) {
|
public Text_t Memory$as_text(const void *p, bool colorize, const TypeInfo_t *) {
|
||||||
(void)type;
|
|
||||||
if (!p) return Text("Memory");
|
if (!p) return Text("Memory");
|
||||||
return Text$format(colorize ? "\x1b[0;34;1mMemory<%p>\x1b[m" : "Memory<%p>", p);
|
return Text$format(colorize ? "\x1b[0;34;1mMemory<%p>\x1b[m" : "Memory<%p>", p);
|
||||||
}
|
}
|
||||||
@ -21,8 +20,9 @@ public Text_t Memory__as_text(const void *p, bool colorize, const TypeInfo_t *ty
|
|||||||
public const TypeInfo_t Memory$info = {
|
public const TypeInfo_t Memory$info = {
|
||||||
.size=0,
|
.size=0,
|
||||||
.align=0,
|
.align=0,
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={.as_text=(void*)Memory__as_text},
|
.as_text=Memory$as_text,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -15,247 +15,40 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wstack-protector"
|
|
||||||
PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type)
|
PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
if (type->metamethods.hash)
|
||||||
case TextInfo: return Text$hash((void*)obj);
|
return type->metamethods.hash(obj, type);
|
||||||
case ArrayInfo: return Array$hash(obj, type);
|
|
||||||
case ChannelInfo: return Channel$hash((Channel_t**)obj, type);
|
|
||||||
case TableInfo: return Table$hash(obj, type);
|
|
||||||
case OptionalInfo: return is_null(obj, type->OptionalInfo.type) ? 0 : generic_hash(obj, type->OptionalInfo.type);
|
|
||||||
case StructInfo: {
|
|
||||||
if (type->StructInfo.num_fields == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (type->StructInfo.num_fields == 1) {
|
|
||||||
return generic_hash(obj, type->StructInfo.fields[0].type);
|
|
||||||
} else {
|
|
||||||
uint32_t field_hashes[type->StructInfo.num_fields] = {};
|
|
||||||
ptrdiff_t byte_offset = 0;
|
|
||||||
ptrdiff_t bit_offset = 0;
|
|
||||||
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
|
||||||
NamedType_t field = type->StructInfo.fields[i];
|
|
||||||
if (field.type == &Bool$info) {
|
|
||||||
bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
|
|
||||||
field_hashes[i] = (uint32_t)b;
|
|
||||||
bit_offset += 1;
|
|
||||||
if (bit_offset >= 8) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (bit_offset > 0) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
if (field.type->align && byte_offset % field.type->align > 0)
|
|
||||||
byte_offset += field.type->align - (byte_offset % field.type->align);
|
|
||||||
field_hashes[i] = generic_hash(obj + byte_offset, field.type);
|
|
||||||
byte_offset += field.type->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return siphash24((void*)field_hashes, sizeof(field_hashes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case EnumInfo: {
|
|
||||||
int32_t tag = *(int32_t*)obj;
|
|
||||||
uint32_t components[2] = {(uint32_t)tag, 0};
|
|
||||||
|
|
||||||
const TypeInfo_t *value = type->EnumInfo.tags[tag-1].type;
|
return siphash24((void*)obj, (size_t)(type->size));
|
||||||
if (value && value->size > 0) {
|
|
||||||
ptrdiff_t byte_offset = sizeof(int32_t);
|
|
||||||
if (value->align && byte_offset % value->align > 0)
|
|
||||||
byte_offset += value->align - (byte_offset % value->align);
|
|
||||||
components[1] = generic_hash(obj + byte_offset, value);
|
|
||||||
}
|
|
||||||
return siphash24((void*)components, sizeof(components));
|
|
||||||
|
|
||||||
}
|
|
||||||
case CustomInfo: case CStringInfo: // These all share the same info
|
|
||||||
if (!type->CustomInfo.hash)
|
|
||||||
goto hash_data;
|
|
||||||
return type->CustomInfo.hash(obj, type);
|
|
||||||
case PointerInfo: case FunctionInfo: case TypeInfoInfo: case OpaqueInfo: default: {
|
|
||||||
hash_data:;
|
|
||||||
return siphash24((void*)obj, (size_t)(type->size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo_t *type)
|
PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
if (x == y) return 0;
|
if (x == y) return 0;
|
||||||
|
|
||||||
switch (type->tag) {
|
if (type->metamethods.compare)
|
||||||
case PointerInfo: case FunctionInfo: return Pointer$compare(x, y, type);
|
return type->metamethods.compare(x, y, type);
|
||||||
case TextInfo: return Text$compare(x, y);
|
|
||||||
case ArrayInfo: return Array$compare(x, y, type);
|
|
||||||
case ChannelInfo: return Channel$compare((Channel_t**)x, (Channel_t**)y, type);
|
|
||||||
case TableInfo: return Table$compare(x, y, type);
|
|
||||||
case OptionalInfo: {
|
|
||||||
bool x_is_null = is_null(x, type->OptionalInfo.type);
|
|
||||||
bool y_is_null = is_null(y, type->OptionalInfo.type);
|
|
||||||
if (x_is_null && y_is_null) return 0;
|
|
||||||
else if (x_is_null != y_is_null) return (int32_t)y_is_null - (int32_t)x_is_null;
|
|
||||||
else return generic_compare(x, y, type->OptionalInfo.type);
|
|
||||||
}
|
|
||||||
case StructInfo: {
|
|
||||||
ptrdiff_t byte_offset = 0;
|
|
||||||
ptrdiff_t bit_offset = 0;
|
|
||||||
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
|
||||||
NamedType_t field = type->StructInfo.fields[i];
|
|
||||||
if (field.type == &Bool$info) {
|
|
||||||
bool bx = ((*(char*)(x + byte_offset)) >> bit_offset) & 0x1;
|
|
||||||
bool by = ((*(char*)(y + byte_offset)) >> bit_offset) & 0x1;
|
|
||||||
if (bx != by)
|
|
||||||
return (int32_t)bx - (int32_t)by;
|
|
||||||
bit_offset += 1;
|
|
||||||
if (bit_offset >= 8) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (bit_offset > 0) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
if (field.type->align && byte_offset % field.type->align > 0)
|
|
||||||
byte_offset += field.type->align - (byte_offset % field.type->align);
|
|
||||||
int32_t cmp = generic_compare(x + byte_offset, y + byte_offset, field.type);
|
|
||||||
if (cmp != 0)
|
|
||||||
return cmp;
|
|
||||||
byte_offset += field.type->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case EnumInfo: {
|
|
||||||
int32_t x_tag = *(int32_t*)x;
|
|
||||||
int32_t y_tag = *(int32_t*)y;
|
|
||||||
if (x_tag != y_tag)
|
|
||||||
return x_tag > y_tag ? 1 : -1;
|
|
||||||
|
|
||||||
const TypeInfo_t *value = type->EnumInfo.tags[x_tag-1].type;
|
return (int32_t)memcmp((void*)x, (void*)y, (size_t)(type->size));
|
||||||
if (value && value->size > 0) {
|
|
||||||
ptrdiff_t byte_offset = sizeof(int32_t);
|
|
||||||
if (value->align && byte_offset % value->align > 0)
|
|
||||||
byte_offset += value->align - (byte_offset % value->align);
|
|
||||||
return generic_compare(x + byte_offset, y + byte_offset, value);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case CustomInfo: case CStringInfo: // These all share the same info
|
|
||||||
if (!type->CustomInfo.compare)
|
|
||||||
goto compare_data;
|
|
||||||
return type->CustomInfo.compare(x, y, type);
|
|
||||||
case TypeInfoInfo: case OpaqueInfo: default:
|
|
||||||
compare_data:
|
|
||||||
return (int32_t)memcmp((void*)x, (void*)y, (size_t)(type->size));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo_t *type)
|
PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
if (x == y) return true;
|
if (x == y) return true;
|
||||||
|
|
||||||
switch (type->tag) {
|
if (type->metamethods.equal)
|
||||||
case PointerInfo: case FunctionInfo: return Pointer$equal(x, y, type);
|
return type->metamethods.equal(x, y, type);
|
||||||
case TextInfo: return Text$equal(x, y);
|
|
||||||
case ArrayInfo: return Array$equal(x, y, type);
|
return (generic_compare(x, y, type) == 0);
|
||||||
case ChannelInfo: return Channel$equal((Channel_t**)x, (Channel_t**)y, type);
|
|
||||||
case TableInfo: return Table$equal(x, y, type);
|
|
||||||
case OptionalInfo: {
|
|
||||||
bool x_is_null = is_null(x, type->OptionalInfo.type);
|
|
||||||
bool y_is_null = is_null(y, type->OptionalInfo.type);
|
|
||||||
if (x_is_null && y_is_null) return true;
|
|
||||||
else if (x_is_null != y_is_null) return false;
|
|
||||||
else return generic_equal(x, y, type->OptionalInfo.type);
|
|
||||||
}
|
|
||||||
case StructInfo: case EnumInfo:
|
|
||||||
return (generic_compare(x, y, type) == 0);
|
|
||||||
case CustomInfo: case CStringInfo: // These all share the same info
|
|
||||||
if (!type->CustomInfo.equal)
|
|
||||||
goto use_generic_compare;
|
|
||||||
return type->CustomInfo.equal(x, y, type);
|
|
||||||
case TypeInfoInfo: case OpaqueInfo: default:
|
|
||||||
use_generic_compare:
|
|
||||||
return (generic_compare(x, y, type) == 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
if (!type->metamethods.as_text)
|
||||||
case PointerInfo: return Pointer$as_text(obj, colorize, type);
|
fail("No text metamethod provided for type!");
|
||||||
case FunctionInfo: return Func$as_text(obj, colorize, type);
|
|
||||||
case TextInfo: return Text$as_text(obj, colorize, type);
|
|
||||||
case ArrayInfo: return Array$as_text(obj, colorize, type);
|
|
||||||
case ChannelInfo: return Channel$as_text((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 StructInfo: {
|
|
||||||
if (!obj) return Text$from_str(type->StructInfo.name);
|
|
||||||
|
|
||||||
if (type->StructInfo.is_secret)
|
return type->metamethods.as_text(obj, colorize, type);
|
||||||
return Text$format(colorize ? "\x1b[0;1m%s\x1b[m(...)" : "%s(...)", type->StructInfo.name);
|
|
||||||
|
|
||||||
Text_t text = Text$format(colorize ? "\x1b[0;1m%s\x1b[m(" : "%s(", type->StructInfo.name);
|
|
||||||
ptrdiff_t byte_offset = 0;
|
|
||||||
ptrdiff_t bit_offset = 0;
|
|
||||||
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
|
||||||
NamedType_t field = type->StructInfo.fields[i];
|
|
||||||
if (i > 0)
|
|
||||||
text = Text$concat(text, Text(", "));
|
|
||||||
|
|
||||||
if (type->StructInfo.num_fields > 1)
|
|
||||||
text = Text$concat(text, Text$from_str(field.name), Text("="));
|
|
||||||
|
|
||||||
if (field.type == &Bool$info) {
|
|
||||||
bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
|
|
||||||
text = Text$concat(text, Text$from_str(colorize ? (b ? "\x1b[35myes\x1b[m" : "\x1b[35mno\x1b[m") : (b ? "yes" : "no")));
|
|
||||||
bit_offset += 1;
|
|
||||||
if (bit_offset >= 8) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (bit_offset > 0) {
|
|
||||||
byte_offset += 1;
|
|
||||||
bit_offset = 0;
|
|
||||||
}
|
|
||||||
if (field.type->align && byte_offset % field.type->align > 0)
|
|
||||||
byte_offset += field.type->align - (byte_offset % field.type->align);
|
|
||||||
text = Text$concat(text, generic_as_text(obj + byte_offset, colorize, field.type));
|
|
||||||
byte_offset += field.type->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Text$concat(text, Text(")"));
|
|
||||||
}
|
|
||||||
case EnumInfo: {
|
|
||||||
if (!obj) return Text$from_str(type->EnumInfo.name);
|
|
||||||
|
|
||||||
int32_t tag = *(int32_t*)obj;
|
|
||||||
NamedType_t value = type->EnumInfo.tags[tag-1];
|
|
||||||
if (!value.type || value.type->size == 0)
|
|
||||||
return Text$format(colorize ? "\x1b[36;1m%s\x1b[m.\x1b[1m%s\x1b[m" : "%s.%s", type->EnumInfo.name, value.name);
|
|
||||||
|
|
||||||
ptrdiff_t byte_offset = sizeof(int32_t);
|
|
||||||
if (value.type->align && byte_offset % value.type->align > 0)
|
|
||||||
byte_offset += value.type->align - (byte_offset % value.type->align);
|
|
||||||
return Text$concat(Text$format(colorize ? "\x1b[36;1m%s\x1b[m." : "%s.", type->EnumInfo.name),
|
|
||||||
generic_as_text(obj + byte_offset, colorize, value.type));
|
|
||||||
}
|
|
||||||
case CustomInfo: case CStringInfo: // These all share the same info
|
|
||||||
if (!type->CustomInfo.as_text)
|
|
||||||
fail("No text function provided for type!\n");
|
|
||||||
return type->CustomInfo.as_text(obj, colorize, type);
|
|
||||||
case OpaqueInfo: return Text("???");
|
|
||||||
default: fail("Invalid type tag: %d", type->tag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type)
|
public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
@ -264,5 +57,4 @@ public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type)
|
|||||||
return Text$print(stdout, text) + printf("\n");
|
return Text$print(stdout, text) + printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -25,14 +25,13 @@ static OptionalText_t _local_timezone = NONE_TEXT;
|
|||||||
body; \
|
body; \
|
||||||
}})
|
}})
|
||||||
|
|
||||||
public Text_t Moment$as_text(const Moment_t *moment, bool colorize, const TypeInfo_t *type)
|
public Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
|
||||||
if (!moment)
|
if (!moment)
|
||||||
return Text("Moment");
|
return Text("Moment");
|
||||||
|
|
||||||
struct tm info;
|
struct tm info;
|
||||||
struct tm *final_info = localtime_r(&moment->tv_sec, &info);
|
struct tm *final_info = localtime_r(&((Moment_t*)moment)->tv_sec, &info);
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
size_t len = strftime(buf, sizeof(buf), "%c %Z", final_info);
|
size_t len = strftime(buf, sizeof(buf), "%c %Z", final_info);
|
||||||
Text_t text = Text$format("%.*s", (int)len, buf);
|
Text_t text = Text$format("%.*s", (int)len, buf);
|
||||||
@ -41,9 +40,9 @@ public Text_t Moment$as_text(const Moment_t *moment, bool colorize, const TypeIn
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t Moment$compare(const Moment_t *a, const Moment_t *b, const TypeInfo_t *type)
|
PUREFUNC public int32_t Moment$compare(const void *va, const void *vb, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
Moment_t *a = (Moment_t*)va, *b = (Moment_t*)vb;
|
||||||
if (a->tv_sec != b->tv_sec)
|
if (a->tv_sec != b->tv_sec)
|
||||||
return (a->tv_sec > b->tv_sec) - (a->tv_sec < b->tv_sec);
|
return (a->tv_sec > b->tv_sec) - (a->tv_sec < b->tv_sec);
|
||||||
return (a->tv_usec > b->tv_usec) - (a->tv_usec < b->tv_usec);
|
return (a->tv_usec > b->tv_usec) - (a->tv_usec < b->tv_usec);
|
||||||
@ -307,10 +306,9 @@ public Text_t Moment$get_local_timezone(void)
|
|||||||
public const TypeInfo_t Moment$info = {
|
public const TypeInfo_t Moment$info = {
|
||||||
.size=sizeof(Moment_t),
|
.size=sizeof(Moment_t),
|
||||||
.align=__alignof__(Moment_t),
|
.align=__alignof__(Moment_t),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={
|
.as_text=Moment$as_text,
|
||||||
.as_text=(void*)Moment$as_text,
|
.compare=Moment$compare,
|
||||||
.compare=(void*)Moment$compare,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
Text_t Moment$as_text(const Moment_t *moment, bool colorize, const TypeInfo_t *type);
|
Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Moment$compare(const Moment_t *a, const Moment_t *b, const TypeInfo_t *type);
|
PUREFUNC int32_t Moment$compare(const void *a, const void *b, const TypeInfo_t *type);
|
||||||
Moment_t Moment$now(void);
|
Moment_t Moment$now(void);
|
||||||
Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone);
|
Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone);
|
||||||
Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone);
|
Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone);
|
||||||
|
@ -13,13 +13,12 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
public PUREFUNC Text_t Num$as_text(const double *f, bool colorize, const TypeInfo_t *type) {
|
public PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t*) {
|
||||||
(void)type;
|
|
||||||
if (!f) return Text("Num");
|
if (!f) return Text("Num");
|
||||||
return Text$format(colorize ? "\x1b[35m%.16g\x1b[33;2m\x1b[m" : "%.16g", *f);
|
return Text$format(colorize ? "\x1b[35m%.16g\x1b[33;2m\x1b[m" : "%.16g", *(double*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC int32_t Num$compare(const double *x, const double *y, const TypeInfo_t *) {
|
public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
int64_t rx = *(int64_t*)x,
|
int64_t rx = *(int64_t*)x,
|
||||||
ry = *(int64_t*)y;
|
ry = *(int64_t*)y;
|
||||||
|
|
||||||
@ -31,9 +30,8 @@ public PUREFUNC int32_t Num$compare(const double *x, const double *y, const Type
|
|||||||
return (rx > ry) - (rx < ry);
|
return (rx > ry) - (rx < ry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC bool Num$equal(const double *x, const double *y, const TypeInfo_t *type) {
|
public PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
(void)type;
|
return *(double*)x == *(double*)y;
|
||||||
return *x == *y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
|
public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
|
||||||
@ -78,6 +76,11 @@ public OptionalNum_t Num$parse(Text_t text) {
|
|||||||
return nan("null");
|
return nan("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Num$is_none(const void *n, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return isnan(*(Num_t*)n);
|
||||||
|
}
|
||||||
|
|
||||||
public CONSTFUNC bool Num$isinf(double n) { return (fpclassify(n) == FP_INFINITE); }
|
public CONSTFUNC bool Num$isinf(double n) { return (fpclassify(n) == FP_INFINITE); }
|
||||||
public CONSTFUNC bool Num$finite(double n) { return (fpclassify(n) != FP_INFINITE); }
|
public CONSTFUNC bool Num$finite(double n) { return (fpclassify(n) != FP_INFINITE); }
|
||||||
public CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); }
|
public CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); }
|
||||||
@ -85,28 +88,25 @@ public CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); }
|
|||||||
public const TypeInfo_t Num$info = {
|
public const TypeInfo_t Num$info = {
|
||||||
.size=sizeof(double),
|
.size=sizeof(double),
|
||||||
.align=__alignof__(double),
|
.align=__alignof__(double),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={
|
.compare=Num$compare,
|
||||||
.compare=(void*)Num$compare,
|
.equal=Num$equal,
|
||||||
.equal=(void*)Num$equal,
|
.as_text=Num$as_text,
|
||||||
.as_text=(void*)Num$as_text,
|
.is_none=Num$is_none,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public PUREFUNC Text_t Num32$as_text(const float *f, bool colorize, const TypeInfo_t *type) {
|
public PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t*) {
|
||||||
(void)type;
|
|
||||||
if (!f) return Text("Num32");
|
if (!f) return Text("Num32");
|
||||||
return Text$format(colorize ? "\x1b[35m%.8g\x1b[33;2m\x1b[m" : "%.8g", (double)*f);
|
return Text$format(colorize ? "\x1b[35m%.8g\x1b[33;2m\x1b[m" : "%.8g", (double)*(float*)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC int32_t Num32$compare(const float *x, const float *y, const TypeInfo_t *type) {
|
public PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
(void)type;
|
return (*(float*)x > *(float*)y) - (*(float*)x < *(float*)y);
|
||||||
return (*x > *y) - (*x < *y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PUREFUNC bool Num32$equal(const float *x, const float *y, const TypeInfo_t *type) {
|
public PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
(void)type;
|
return *(float*)x == *(float*)y;
|
||||||
return *x == *y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
|
public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
|
||||||
@ -151,6 +151,11 @@ public OptionalNum32_t Num32$parse(Text_t text) {
|
|||||||
return nan("null");
|
return nan("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Num32$is_none(const void *n, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return isnan(*(Num32_t*)n);
|
||||||
|
}
|
||||||
|
|
||||||
public CONSTFUNC bool Num32$isinf(float n) { return (fpclassify(n) == FP_INFINITE); }
|
public CONSTFUNC bool Num32$isinf(float n) { return (fpclassify(n) == FP_INFINITE); }
|
||||||
public CONSTFUNC bool Num32$finite(float n) { return (fpclassify(n) != FP_INFINITE); }
|
public CONSTFUNC bool Num32$finite(float n) { return (fpclassify(n) != FP_INFINITE); }
|
||||||
public CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); }
|
public CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); }
|
||||||
@ -158,11 +163,11 @@ public CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); }
|
|||||||
public const TypeInfo_t Num32$info = {
|
public const TypeInfo_t Num32$info = {
|
||||||
.size=sizeof(float),
|
.size=sizeof(float),
|
||||||
.align=__alignof__(float),
|
.align=__alignof__(float),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={
|
.compare=Num32$compare,
|
||||||
.compare=(void*)Num32$compare,
|
.equal=Num32$equal,
|
||||||
.equal=(void*)Num32$equal,
|
.as_text=Num32$as_text,
|
||||||
.as_text=(void*)Num32$as_text,
|
.is_none=Num32$is_none,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
#define N32(n) ((float)n)
|
#define N32(n) ((float)n)
|
||||||
#define N64(n) ((double)n)
|
#define N64(n) ((double)n)
|
||||||
|
|
||||||
Text_t Num$as_text(const double *f, bool colorize, const TypeInfo_t *type);
|
Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Num$compare(const double *x, const double *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Num$equal(const double *x, const double *y, const TypeInfo_t *type);
|
PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute);
|
CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute);
|
||||||
Text_t Num$format(double f, Int_t precision);
|
Text_t Num$format(double f, Int_t precision);
|
||||||
Text_t Num$scientific(double f, Int_t precision);
|
Text_t Num$scientific(double f, Int_t precision);
|
||||||
@ -34,9 +34,9 @@ MACROLIKE CONSTFUNC double Num$clamped(double x, double low, double high) {
|
|||||||
}
|
}
|
||||||
extern const TypeInfo_t Num$info;
|
extern const TypeInfo_t Num$info;
|
||||||
|
|
||||||
Text_t Num32$as_text(const float *f, bool colorize, const TypeInfo_t *type);
|
Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Num32$compare(const float *x, const float *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Num32$equal(const float *x, const float *y, const TypeInfo_t *type);
|
PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute);
|
CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute);
|
||||||
Text_t Num32$format(float f, Int_t precision);
|
Text_t Num32$format(float f, Int_t precision);
|
||||||
Text_t Num32$scientific(float f, Int_t precision);
|
Text_t Num32$scientific(float f, Int_t precision);
|
||||||
|
@ -15,55 +15,36 @@
|
|||||||
|
|
||||||
public PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type)
|
public PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type)
|
||||||
{
|
{
|
||||||
if (non_optional_type == &Int$info)
|
if (non_optional_type->metamethods.is_none)
|
||||||
return ((Int_t*)obj)->small == 0;
|
return non_optional_type->metamethods.is_none(obj, non_optional_type);
|
||||||
else if (non_optional_type == &Bool$info)
|
|
||||||
return *((OptionalBool_t*)obj) == NONE_BOOL;
|
|
||||||
else if (non_optional_type == &Num$info)
|
|
||||||
return isnan(*((Num_t*)obj));
|
|
||||||
else if (non_optional_type == &Num32$info)
|
|
||||||
return isnan(*((Num32_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;
|
|
||||||
else if (non_optional_type == &Byte$info)
|
|
||||||
return ((OptionalByte_t*)obj)->is_null;
|
|
||||||
else if (non_optional_type == &Thread$info)
|
|
||||||
return *(pthread_t**)obj == NULL;
|
|
||||||
else if (non_optional_type == &Moment$info)
|
|
||||||
return ((OptionalMoment_t*)obj)->tv_usec < 0;
|
|
||||||
else if (non_optional_type == &Match$info)
|
|
||||||
return ((OptionalMatch_t*)obj)->index.small == 0;
|
|
||||||
|
|
||||||
switch (non_optional_type->tag) {
|
return *(bool*)(obj + non_optional_type->size);
|
||||||
case ChannelInfo: return *(Channel_t**)obj == NULL;
|
}
|
||||||
case PointerInfo: return *(void**)obj == NULL;
|
|
||||||
case TextInfo: return ((Text_t*)obj)->length < 0;
|
PUREFUNC public uint64_t Optional$hash(const void *obj, const TypeInfo_t *type)
|
||||||
case ArrayInfo: return ((Array_t*)obj)->length < 0;
|
{
|
||||||
case TableInfo: return ((Table_t*)obj)->entries.length < 0;
|
return is_null(obj, type->OptionalInfo.type) ? 0 : generic_hash(obj, type->OptionalInfo.type);
|
||||||
case FunctionInfo: return *(void**)obj == NULL;
|
}
|
||||||
case StructInfo: {
|
|
||||||
int64_t offset = 0;
|
PUREFUNC public int32_t Optional$compare(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
for (int i = 0; i < non_optional_type->StructInfo.num_fields; i++) {
|
{
|
||||||
NamedType_t field = non_optional_type->StructInfo.fields[i];
|
if (x == y) return 0;
|
||||||
if (offset > 0 && (offset % field.type->align) > 0)
|
bool x_is_null = is_null(x, type->OptionalInfo.type);
|
||||||
offset += field.type->align - (offset % field.type->align);
|
bool y_is_null = is_null(y, type->OptionalInfo.type);
|
||||||
offset += field.type->size;
|
if (x_is_null && y_is_null) return 0;
|
||||||
}
|
else if (x_is_null != y_is_null) return (int32_t)y_is_null - (int32_t)x_is_null;
|
||||||
return *(bool*)(obj + offset);
|
else return generic_compare(x, y, type->OptionalInfo.type);
|
||||||
}
|
}
|
||||||
case EnumInfo: return (*(int*)obj) == 0; // NULL tag
|
|
||||||
case CStringInfo: return (*(char**)obj) == NULL;
|
PUREFUNC public bool Optional$equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
default: {
|
{
|
||||||
Text_t t = generic_as_text(NULL, false, non_optional_type);
|
if (x == y) return true;
|
||||||
errx(1, "is_null() not implemented for: %k", &t);
|
|
||||||
}
|
bool x_is_null = is_null(x, type->OptionalInfo.type);
|
||||||
}
|
bool y_is_null = is_null(y, type->OptionalInfo.type);
|
||||||
|
if (x_is_null && y_is_null) return true;
|
||||||
|
else if (x_is_null != y_is_null) return false;
|
||||||
|
else return generic_equal(x, y, type->OptionalInfo.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
|
@ -25,6 +25,20 @@
|
|||||||
#define NONE_MOMENT ((OptionalMoment_t){.tv_usec=-1})
|
#define NONE_MOMENT ((OptionalMoment_t){.tv_usec=-1})
|
||||||
|
|
||||||
PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type);
|
PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type);
|
||||||
|
PUREFUNC uint64_t Optional$hash(const void *obj, const TypeInfo_t *type);
|
||||||
|
PUREFUNC int32_t Optional$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Optional$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
|
Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
|
||||||
|
|
||||||
|
#define Optional$metamethods ((metamethods_t){ \
|
||||||
|
.hash=Optional$hash, \
|
||||||
|
.compare=Optional$compare, \
|
||||||
|
.equal=Optional$equal, \
|
||||||
|
.as_text=Optional$as_text, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Optional$info(_size, _align, t) &((TypeInfo_t){.size=_size, .align=_align, \
|
||||||
|
.tag=OptionalInfo, .OptionalInfo.type=t, \
|
||||||
|
.metamethods=Optional$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -89,7 +89,7 @@ public Path_t Path$cleanup(Path_t path)
|
|||||||
} else { // (../..) -> (../..)
|
} else { // (../..) -> (../..)
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
} else if (Text$equal(&component, (Path_t*)(components.data + (i-1)*components.stride))) { // (___/../..) -> (____/../..)
|
} else if (Text$equal(&component, (Path_t*)(components.data + (i-1)*components.stride), &Text$info)) { // (___/../..) -> (____/../..)
|
||||||
i += 1;
|
i += 1;
|
||||||
} else { // (___/foo/..) -> (___)
|
} else { // (___/foo/..) -> (___)
|
||||||
Array$remove_at(&components, I(i), I(2), sizeof(Path_t));
|
Array$remove_at(&components, I(i), I(2), sizeof(Path_t));
|
||||||
@ -569,6 +569,7 @@ public const TypeInfo_t Path$info = {
|
|||||||
.align=__alignof__(Path_t),
|
.align=__alignof__(Path_t),
|
||||||
.tag=TextInfo,
|
.tag=TextInfo,
|
||||||
.TextInfo={.lang="Path"},
|
.TextInfo={.lang="Path"},
|
||||||
|
.metamethods=Text$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "integers.h"
|
#include "integers.h"
|
||||||
#include "optionals.h"
|
#include "optionals.h"
|
||||||
#include "patterns.h"
|
#include "patterns.h"
|
||||||
|
#include "structs.h"
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -1160,6 +1161,7 @@ public const TypeInfo_t Pattern$info = {
|
|||||||
.align=__alignof__(Pattern_t),
|
.align=__alignof__(Pattern_t),
|
||||||
.tag=TextInfo,
|
.tag=TextInfo,
|
||||||
.TextInfo={.lang="Pattern"},
|
.TextInfo={.lang="Pattern"},
|
||||||
|
.metamethods=Text$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
static NamedType_t _match_fields[3] = {
|
static NamedType_t _match_fields[3] = {
|
||||||
@ -1167,6 +1169,12 @@ static NamedType_t _match_fields[3] = {
|
|||||||
{"index", &Int$info},
|
{"index", &Int$info},
|
||||||
{"captures", Array$info(&Text$info)},
|
{"captures", Array$info(&Text$info)},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool Match$is_none(const void *m, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return ((OptionalMatch_t*)m)->index.small == 0;
|
||||||
|
}
|
||||||
|
|
||||||
public const TypeInfo_t Match$info = {
|
public const TypeInfo_t Match$info = {
|
||||||
.size=sizeof(Match_t),
|
.size=sizeof(Match_t),
|
||||||
.align=__alignof__(Match_t),
|
.align=__alignof__(Match_t),
|
||||||
@ -1176,6 +1184,13 @@ public const TypeInfo_t Match$info = {
|
|||||||
.num_fields=3,
|
.num_fields=3,
|
||||||
.fields=_match_fields,
|
.fields=_match_fields,
|
||||||
},
|
},
|
||||||
|
.metamethods={
|
||||||
|
.as_text=Struct$as_text,
|
||||||
|
.hash=Struct$hash,
|
||||||
|
.compare=Struct$compare,
|
||||||
|
.equal=Struct$equal,
|
||||||
|
.is_none=Match$is_none,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -45,8 +45,7 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *ty
|
|||||||
} else if (ptr == root) {
|
} else if (ptr == root) {
|
||||||
return Text$format(colorize ? "\x1b[34;1m%s~1\x1b[m" : "%s~1", ptr_info.sigil);
|
return Text$format(colorize ? "\x1b[34;1m%s~1\x1b[m" : "%s~1", ptr_info.sigil);
|
||||||
} else {
|
} else {
|
||||||
TypeInfo_t rec_table = ((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
|
TypeInfo_t rec_table = *Table$info(type, &Int64$info);
|
||||||
.tag=TableInfo, .TableInfo.key=type, .TableInfo.value=&Int64$info});
|
|
||||||
int64_t *id = Table$get(pending, x, &rec_table);
|
int64_t *id = Table$get(pending, x, &rec_table);
|
||||||
if (id)
|
if (id)
|
||||||
return Text$format(colorize ? "\x1b[34;1m%s~%ld\x1b[m" : "%s~%ld", ptr_info.sigil, *id);
|
return Text$format(colorize ? "\x1b[34;1m%s~%ld\x1b[m" : "%s~%ld", ptr_info.sigil, *id);
|
||||||
@ -69,16 +68,19 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *ty
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *type) {
|
PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
(void)type;
|
|
||||||
const void *xp = *(const void**)x, *yp = *(const void**)y;
|
const void *xp = *(const void**)x, *yp = *(const void**)y;
|
||||||
return (xp > yp) - (xp < yp);
|
return (xp > yp) - (xp < yp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *type) {
|
PUREFUNC public bool Pointer$equal(const void *x, const void *y, const TypeInfo_t*) {
|
||||||
(void)type;
|
|
||||||
const void *xp = *(const void**)x, *yp = *(const void**)y;
|
const void *xp = *(const void**)x, *yp = *(const void**)y;
|
||||||
return xp == yp;
|
return xp == yp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Pointer$is_none(const void *x, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(void**)x == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -11,9 +11,21 @@
|
|||||||
Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type);
|
Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type);
|
||||||
PUREFUNC int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *type);
|
PUREFUNC bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Pointer$is_none(const void *x, const TypeInfo_t*);
|
||||||
|
|
||||||
#define Null(t) (t*)NULL
|
#define Null(t) (t*)NULL
|
||||||
#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo_t){\
|
#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo_t){\
|
||||||
.size=sizeof(void*), .align=alignof(void*), .tag=PointerInfo, .PointerInfo.sigil=_sigil, .PointerInfo.pointed=_pointed})
|
.size=sizeof(void*), .align=alignof(void*), .tag=PointerInfo, .PointerInfo.sigil=_sigil, .PointerInfo.pointed=_pointed})
|
||||||
|
|
||||||
|
#define Pointer$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Pointer$as_text, \
|
||||||
|
.compare=Pointer$compare, \
|
||||||
|
.equal=Pointer$equal, \
|
||||||
|
.is_none=Pointer$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Pointer$info(sigil_expr, pointed_info) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
|
||||||
|
.tag=PointerInfo, .PointerInfo={.sigil=sigil_expr, .pointed=pointed_info}, \
|
||||||
|
.metamethods=Pointer$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
PUREFUNC static int32_t Range$compare(const Range_t *x, const Range_t *y, const TypeInfo_t *type)
|
PUREFUNC static int32_t Range$compare(const void *vx, const void *vy, const TypeInfo_t *)
|
||||||
{
|
{
|
||||||
(void)type;
|
if (vx == vy) return 0;
|
||||||
if (x == y) return 0;
|
Range_t *x = (Range_t*)vx, *y = (Range_t*)vy;
|
||||||
int32_t diff = Int$compare(&x->first, &y->first, &Int$info);
|
int32_t diff = Int$compare(&x->first, &y->first, &Int$info);
|
||||||
if (diff != 0) return diff;
|
if (diff != 0) return diff;
|
||||||
diff = Int$compare(&x->last, &y->last, &Int$info);
|
diff = Int$compare(&x->last, &y->last, &Int$info);
|
||||||
@ -26,18 +26,18 @@ PUREFUNC static int32_t Range$compare(const Range_t *x, const Range_t *y, const
|
|||||||
return Int$compare(&x->step, &y->step, &Int$info);
|
return Int$compare(&x->step, &y->step, &Int$info);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC static bool Range$equal(const Range_t *x, const Range_t *y, const TypeInfo_t *type)
|
PUREFUNC static bool Range$equal(const void *vx, const void *vy, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
if (vx == vy) return true;
|
||||||
if (x == y) return true;
|
Range_t *x = (Range_t*)vx, *y = (Range_t*)vy;
|
||||||
return Int$equal(&x->first, &y->first, &Int$info) && Int$equal(&x->last, &y->last, &Int$info) && Int$equal(&x->step, &y->step, &Int$info);
|
return Int$equal(&x->first, &y->first, &Int$info) && Int$equal(&x->last, &y->last, &Int$info) && Int$equal(&x->step, &y->step, &Int$info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Text_t Range$as_text(const Range_t *r, bool use_color, const TypeInfo_t *type)
|
static Text_t Range$as_text(const void *obj, bool use_color, const TypeInfo_t *)
|
||||||
{
|
{
|
||||||
(void)type;
|
if (!obj) return Text("Range");
|
||||||
if (!r) return Text("Range");
|
|
||||||
|
|
||||||
|
Range_t *r = (Range_t*)obj;
|
||||||
Text_t first = Int$as_text(&r->first, use_color, &Int$info);
|
Text_t first = Int$as_text(&r->first, use_color, &Int$info);
|
||||||
Text_t last = Int$as_text(&r->last, use_color, &Int$info);
|
Text_t last = Int$as_text(&r->last, use_color, &Int$info);
|
||||||
Text_t step = Int$as_text(&r->step, use_color, &Int$info);
|
Text_t step = Int$as_text(&r->step, use_color, &Int$info);
|
||||||
@ -55,10 +55,20 @@ PUREFUNC public Range_t Range$by(Range_t r, Int_t step)
|
|||||||
return (Range_t){r.first, r.last, Int$times(step, r.step)};
|
return (Range_t){r.first, r.last, Int$times(step, r.step)};
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo_t Range$info = {sizeof(Range_t), __alignof(Range_t), {.tag=CustomInfo, .CustomInfo={
|
static bool Range$is_none(const void *obj, const TypeInfo_t*)
|
||||||
.as_text=(void*)Range$as_text,
|
{
|
||||||
.compare=(void*)Range$compare,
|
return ((Range_t*)obj)->step.small == 0x1;
|
||||||
.equal=(void*)Range$equal,
|
}
|
||||||
}}};
|
|
||||||
|
public const TypeInfo_t Range$info = {
|
||||||
|
.size=sizeof(Range_t),
|
||||||
|
.align=__alignof(Range_t),
|
||||||
|
.metamethods={
|
||||||
|
.as_text=Range$as_text,
|
||||||
|
.compare=Range$compare,
|
||||||
|
.equal=Range$equal,
|
||||||
|
.is_none=Range$is_none,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
10
stdlib/rng.c
10
stdlib/rng.c
@ -26,11 +26,10 @@ struct RNGState_t {
|
|||||||
uint8_t random_bytes[1024];
|
uint8_t random_bytes[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
PUREFUNC static Text_t RNG$as_text(const RNG_t *rng, bool colorize, const TypeInfo_t *type)
|
PUREFUNC static Text_t RNG$as_text(const void *rng, bool colorize, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
|
||||||
if (!rng) return Text("RNG");
|
if (!rng) return Text("RNG");
|
||||||
return Text$format(colorize ? "\x1b[34;1mRNG(%p)\x1b[m" : "RNG(%p)", *rng);
|
return Text$format(colorize ? "\x1b[34;1mRNG(%p)\x1b[m" : "RNG(%p)", *(RNG_t**)rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define KEYSZ 32
|
#define KEYSZ 32
|
||||||
@ -259,8 +258,9 @@ public Array_t RNG$bytes(RNG_t rng, Int_t count)
|
|||||||
public const TypeInfo_t RNG$info = {
|
public const TypeInfo_t RNG$info = {
|
||||||
.size=sizeof(void*),
|
.size=sizeof(void*),
|
||||||
.align=__alignof__(void*),
|
.align=__alignof__(void*),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={.as_text=(void*)RNG$as_text},
|
.as_text=RNG$as_text,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -141,6 +141,7 @@ public const TypeInfo_t Shell$info = {
|
|||||||
.align=__alignof__(Shell_t),
|
.align=__alignof__(Shell_t),
|
||||||
.tag=TextInfo,
|
.tag=TextInfo,
|
||||||
.TextInfo={.lang="Shell"},
|
.TextInfo={.lang="Shell"},
|
||||||
|
.metamethods=Text$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -467,12 +467,12 @@ public void end_test(const void *expr, const TypeInfo_t *type, const char *expec
|
|||||||
if (expected && expected[0]) {
|
if (expected && expected[0]) {
|
||||||
Text_t expected_text = Text$from_str(expected);
|
Text_t expected_text = Text$from_str(expected);
|
||||||
Text_t expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_text;
|
Text_t expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_text;
|
||||||
bool success = Text$equal(&expr_plain, &expected_text);
|
bool success = Text$equal(&expr_plain, &expected_text, &Text$info);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
OptionalMatch_t colon = Text$find(expected_text, Text(":"), I_small(1));
|
OptionalMatch_t colon = Text$find(expected_text, Text(":"), I_small(1));
|
||||||
if (colon.index.small) {
|
if (colon.index.small) {
|
||||||
Text_t with_type = Text$concat(expr_plain, Text(" : "), type_name);
|
Text_t with_type = Text$concat(expr_plain, Text(" : "), type_name);
|
||||||
success = Text$equal(&with_type, &expected_text);
|
success = Text$equal(&with_type, &expected_text, &Text$info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
170
stdlib/structs.c
Normal file
170
stdlib/structs.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// Metamethods for structs
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "arrays.h"
|
||||||
|
#include "bools.h"
|
||||||
|
#include "channels.h"
|
||||||
|
#include "functiontype.h"
|
||||||
|
#include "metamethods.h"
|
||||||
|
#include "optionals.h"
|
||||||
|
#include "pointers.h"
|
||||||
|
#include "siphash.h"
|
||||||
|
#include "tables.h"
|
||||||
|
#include "text.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstack-protector"
|
||||||
|
PUREFUNC public uint64_t Struct$hash(const void *obj, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (type->StructInfo.num_fields == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (type->StructInfo.num_fields == 1)
|
||||||
|
return generic_hash(obj, type->StructInfo.fields[0].type);
|
||||||
|
|
||||||
|
uint32_t field_hashes[type->StructInfo.num_fields] = {};
|
||||||
|
ptrdiff_t byte_offset = 0;
|
||||||
|
ptrdiff_t bit_offset = 0;
|
||||||
|
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
||||||
|
NamedType_t field = type->StructInfo.fields[i];
|
||||||
|
if (field.type == &Bool$info) {
|
||||||
|
bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
field_hashes[i] = (uint32_t)b;
|
||||||
|
bit_offset += 1;
|
||||||
|
if (bit_offset >= 8) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bit_offset > 0) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
if (field.type->align && byte_offset % field.type->align > 0)
|
||||||
|
byte_offset += field.type->align - (byte_offset % field.type->align);
|
||||||
|
field_hashes[i] = generic_hash(obj + byte_offset, field.type);
|
||||||
|
byte_offset += field.type->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return siphash24((void*)field_hashes, sizeof(field_hashes));
|
||||||
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
PUREFUNC public int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (x == y)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptrdiff_t byte_offset = 0;
|
||||||
|
ptrdiff_t bit_offset = 0;
|
||||||
|
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
||||||
|
NamedType_t field = type->StructInfo.fields[i];
|
||||||
|
if (field.type == &Bool$info) {
|
||||||
|
bool bx = ((*(char*)(x + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
bool by = ((*(char*)(y + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
if (bx != by)
|
||||||
|
return (int32_t)bx - (int32_t)by;
|
||||||
|
bit_offset += 1;
|
||||||
|
if (bit_offset >= 8) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bit_offset > 0) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
if (field.type->align && byte_offset % field.type->align > 0)
|
||||||
|
byte_offset += field.type->align - (byte_offset % field.type->align);
|
||||||
|
int32_t cmp = generic_compare(x + byte_offset, y + byte_offset, field.type);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
byte_offset += field.type->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (x == y)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ptrdiff_t byte_offset = 0;
|
||||||
|
ptrdiff_t bit_offset = 0;
|
||||||
|
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
||||||
|
NamedType_t field = type->StructInfo.fields[i];
|
||||||
|
if (field.type == &Bool$info) {
|
||||||
|
bool bx = ((*(char*)(x + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
bool by = ((*(char*)(y + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
if (bx != by)
|
||||||
|
return false;
|
||||||
|
bit_offset += 1;
|
||||||
|
if (bit_offset >= 8) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bit_offset > 0) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
if (field.type->align && byte_offset % field.type->align > 0)
|
||||||
|
byte_offset += field.type->align - (byte_offset % field.type->align);
|
||||||
|
if (!generic_equal(x + byte_offset, y + byte_offset, field.type))
|
||||||
|
return false;
|
||||||
|
byte_offset += field.type->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
if (!obj) return Text$from_str(type->StructInfo.name);
|
||||||
|
|
||||||
|
if (type->StructInfo.is_secret)
|
||||||
|
return Text$format(colorize ? "\x1b[0;1m%s\x1b[m(...)" : "%s(...)", type->StructInfo.name);
|
||||||
|
|
||||||
|
Text_t text = Text$format(colorize ? "\x1b[0;1m%s\x1b[m(" : "%s(", type->StructInfo.name);
|
||||||
|
ptrdiff_t byte_offset = 0;
|
||||||
|
ptrdiff_t bit_offset = 0;
|
||||||
|
for (int i = 0; i < type->StructInfo.num_fields; i++) {
|
||||||
|
NamedType_t field = type->StructInfo.fields[i];
|
||||||
|
if (i > 0)
|
||||||
|
text = Text$concat(text, Text(", "));
|
||||||
|
|
||||||
|
if (type->StructInfo.num_fields > 1)
|
||||||
|
text = Text$concat(text, Text$from_str(field.name), Text("="));
|
||||||
|
|
||||||
|
if (field.type == &Bool$info) {
|
||||||
|
bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
|
||||||
|
text = Text$concat(text, Text$from_str(colorize ? (b ? "\x1b[35myes\x1b[m" : "\x1b[35mno\x1b[m") : (b ? "yes" : "no")));
|
||||||
|
bit_offset += 1;
|
||||||
|
if (bit_offset >= 8) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bit_offset > 0) {
|
||||||
|
byte_offset += 1;
|
||||||
|
bit_offset = 0;
|
||||||
|
}
|
||||||
|
if (field.type->align && byte_offset % field.type->align > 0)
|
||||||
|
byte_offset += field.type->align - (byte_offset % field.type->align);
|
||||||
|
text = Text$concat(text, generic_as_text(obj + byte_offset, colorize, field.type));
|
||||||
|
byte_offset += field.type->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Text$concat(text, Text(")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Struct$is_none(const void *obj, const TypeInfo_t *type)
|
||||||
|
{
|
||||||
|
return *(bool*)(obj + type->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
24
stdlib/structs.h
Normal file
24
stdlib/structs.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Metamethods for structs
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
PUREFUNC uint64_t Struct$hash(const void *obj, const TypeInfo_t *type);
|
||||||
|
PUREFUNC int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
|
PUREFUNC Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Struct$is_none(const void *obj, const TypeInfo_t *type);
|
||||||
|
|
||||||
|
#define Struct$metamethods ((metamethods_t){ \
|
||||||
|
.hash=Struct$hash, \
|
||||||
|
.compare=Struct$compare, \
|
||||||
|
.equal=Struct$equal, \
|
||||||
|
.as_text=Struct$as_text, \
|
||||||
|
.is_none=Struct$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
@ -21,6 +21,7 @@
|
|||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "metamethods.h"
|
#include "metamethods.h"
|
||||||
|
#include "pointers.h"
|
||||||
#include "siphash.h"
|
#include "siphash.h"
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
@ -42,7 +43,7 @@
|
|||||||
|
|
||||||
#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
|
#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
|
||||||
|
|
||||||
static const TypeInfo_t MemoryPointer = {
|
static TypeInfo_t MemoryPointer = {
|
||||||
.size=sizeof(void*),
|
.size=sizeof(void*),
|
||||||
.align=__alignof__(void*),
|
.align=__alignof__(void*),
|
||||||
.tag=PointerInfo,
|
.tag=PointerInfo,
|
||||||
@ -50,6 +51,7 @@ static const TypeInfo_t MemoryPointer = {
|
|||||||
.sigil="@",
|
.sigil="@",
|
||||||
.pointed=&Memory$info,
|
.pointed=&Memory$info,
|
||||||
},
|
},
|
||||||
|
.metamethods=Pointer$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TypeInfo_t CStrToVoidStarTable = {
|
const TypeInfo_t CStrToVoidStarTable = {
|
||||||
@ -57,6 +59,7 @@ const TypeInfo_t CStrToVoidStarTable = {
|
|||||||
.align=__alignof__(Table_t),
|
.align=__alignof__(Table_t),
|
||||||
.tag=TableInfo,
|
.tag=TableInfo,
|
||||||
.TableInfo={.key=&CString$info, .value=&MemoryPointer},
|
.TableInfo={.key=&CString$info, .value=&MemoryPointer},
|
||||||
|
.metamethods=Table$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
PUREFUNC static INLINE size_t entry_size(const TypeInfo_t *info)
|
PUREFUNC static INLINE size_t entry_size(const TypeInfo_t *info)
|
||||||
@ -396,9 +399,10 @@ public Table_t Table$sorted(Table_t t, const TypeInfo_t *type)
|
|||||||
return Table$from_entries(entries, type);
|
return Table$from_entries(entries, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo_t *type)
|
PUREFUNC public bool Table$equal(const void *vx, const void *vy, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
if (x == y) return true;
|
if (vx == vy) return true;
|
||||||
|
Table_t *x = (Table_t*)vx, *y = (Table_t*)vy;
|
||||||
|
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
if (Table$length(*x) != Table$length(*y))
|
if (Table$length(*x) != Table$length(*y))
|
||||||
@ -410,10 +414,11 @@ PUREFUNC public bool Table$equal(const Table_t *x, const Table_t *y, const TypeI
|
|||||||
return (Table$compare(x, y, type) == 0);
|
return (Table$compare(x, y, type) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo_t *type)
|
PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
if (x == y) return 0;
|
if (vx == vy) return 0;
|
||||||
|
|
||||||
|
Table_t *x = (Table_t*)vx, *y = (Table_t*)vy;
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
auto table = type->TableInfo;
|
auto table = type->TableInfo;
|
||||||
if (x->entries.length == 0)
|
if (x->entries.length == 0)
|
||||||
@ -441,9 +446,10 @@ PUREFUNC public int32_t Table$compare(const Table_t *x, const Table_t *y, const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public uint64_t Table$hash(const Table_t *t, const TypeInfo_t *type)
|
PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
|
Table_t *t = (Table_t*)obj;
|
||||||
// Table hashes are computed as:
|
// Table hashes are computed as:
|
||||||
// hash(hash(t.keys), hash(t.values), hash(t.fallback), hash(t.default))
|
// hash(hash(t.keys), hash(t.values), hash(t.fallback), hash(t.default))
|
||||||
// Where fallback and default hash to zero if absent
|
// Where fallback and default hash to zero if absent
|
||||||
@ -456,8 +462,9 @@ PUREFUNC public uint64_t Table$hash(const Table_t *t, const TypeInfo_t *type)
|
|||||||
return siphash24((void*)&components, sizeof(components));
|
return siphash24((void*)&components, sizeof(components));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text_t Table$as_text(const Table_t *t, bool colorize, const TypeInfo_t *type)
|
public Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
|
||||||
{
|
{
|
||||||
|
Table_t *t = (Table_t*)obj;
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
auto table = type->TableInfo;
|
auto table = type->TableInfo;
|
||||||
|
|
||||||
@ -635,4 +642,9 @@ CONSTFUNC public void *Table$str_entry(Table_t t, int64_t n)
|
|||||||
return Table$entry(t, n);
|
return Table$entry(t, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Table$is_none(const void *obj, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return ((Table_t*)obj)->entries.length < 0;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||||
|
@ -65,10 +65,11 @@ Table_t Table$sorted(Table_t t, const TypeInfo_t *type);
|
|||||||
void Table$mark_copy_on_write(Table_t *t);
|
void Table$mark_copy_on_write(Table_t *t);
|
||||||
#define TABLE_INCREF(t) ({ ARRAY_INCREF((t).entries); if ((t).bucket_info) (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); })
|
#define TABLE_INCREF(t) ({ ARRAY_INCREF((t).entries); if ((t).bucket_info) (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); })
|
||||||
#define TABLE_COPY(t) ({ TABLE_INCREF(t); t; })
|
#define TABLE_COPY(t) ({ TABLE_INCREF(t); t; })
|
||||||
PUREFUNC int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo_t *type);
|
PUREFUNC int32_t Table$compare(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo_t *type);
|
PUREFUNC bool Table$equal(const void *x, const void *y, const TypeInfo_t *type);
|
||||||
PUREFUNC uint64_t Table$hash(const Table_t *t, const TypeInfo_t *type);
|
PUREFUNC uint64_t Table$hash(const void *t, const TypeInfo_t *type);
|
||||||
Text_t Table$as_text(const Table_t *t, bool colorize, const TypeInfo_t *type);
|
Text_t Table$as_text(const void *t, bool colorize, const TypeInfo_t *type);
|
||||||
|
PUREFUNC bool Table$is_none(const void *obj, const TypeInfo_t*);
|
||||||
|
|
||||||
CONSTFUNC void *Table$str_entry(Table_t t, int64_t n);
|
CONSTFUNC void *Table$str_entry(Table_t t, int64_t n);
|
||||||
PUREFUNC void *Table$str_get(Table_t t, const char *key);
|
PUREFUNC void *Table$str_get(Table_t t, const char *key);
|
||||||
@ -81,4 +82,17 @@ void Table$str_remove(Table_t *t, const char *key);
|
|||||||
|
|
||||||
extern const TypeInfo_t CStrToVoidStarTable;
|
extern const TypeInfo_t CStrToVoidStarTable;
|
||||||
|
|
||||||
|
#define Table$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Table$as_text, \
|
||||||
|
.compare=Table$compare, \
|
||||||
|
.equal=Table$equal, \
|
||||||
|
.hash=Table$hash, \
|
||||||
|
.is_none=Table$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Table$info(key_expr, value_expr) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
|
||||||
|
.tag=TableInfo, .TableInfo.key=key_expr, .TableInfo.value=value_expr, .metamethods=Table$metamethods})
|
||||||
|
#define Set$info(item_info) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
|
||||||
|
.tag=TableInfo, .TableInfo.key=item_info, .TableInfo.value=&Void$info, .metamethods=Table$metamethods})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||||
|
@ -92,28 +92,27 @@ static int32_t num_synthetic_graphemes = 0;
|
|||||||
|
|
||||||
static Text_t text_from_u32(ucs4_t *codepoints, int64_t num_codepoints, bool normalize);
|
static Text_t text_from_u32(ucs4_t *codepoints, int64_t num_codepoints, bool normalize);
|
||||||
|
|
||||||
PUREFUNC static bool graphemes_equal(ucs4_t **a, ucs4_t **b) {
|
PUREFUNC static bool graphemes_equal(const void *va, const void *vb, const TypeInfo_t*) {
|
||||||
if ((*a)[0] != (*b)[0]) return false;
|
ucs4_t *a = *(ucs4_t**)va;
|
||||||
for (int i = 0; i < (int)(*a)[0]; i++)
|
ucs4_t *b = *(ucs4_t**)vb;
|
||||||
if ((*a)[i] != (*b)[i]) return false;
|
if (a[0] != b[0]) return false;
|
||||||
|
for (int i = 0; i < (int)a[0]; i++)
|
||||||
|
if (a[i] != b[i]) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC static uint64_t grapheme_hash(ucs4_t **g) {
|
PUREFUNC static uint64_t grapheme_hash(const void *g, const TypeInfo_t*) {
|
||||||
ucs4_t *cluster = *g;
|
ucs4_t *cluster = *(ucs4_t**)g;
|
||||||
return siphash24((void*)&cluster[1], sizeof(ucs4_t[cluster[0]]));
|
return siphash24((void*)&cluster[1], sizeof(ucs4_t[cluster[0]]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo_t GraphemeClusterInfo = {
|
static const TypeInfo_t GraphemeClusterInfo = {
|
||||||
.size=sizeof(ucs4_t*),
|
.size=sizeof(ucs4_t*),
|
||||||
.align=__alignof__(ucs4_t*),
|
.align=__alignof__(ucs4_t*),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={.equal=(void*)graphemes_equal, .hash=(void*)grapheme_hash},
|
.equal=graphemes_equal,
|
||||||
};
|
.hash=grapheme_hash,
|
||||||
|
},
|
||||||
static const TypeInfo_t GraphemeIDLookupTableInfo = {
|
|
||||||
.size=sizeof(Table_t), .align=__alignof__(Table_t),
|
|
||||||
.tag=TableInfo, .TableInfo={.key=&GraphemeClusterInfo, .value=&Int32$info},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
@ -128,9 +127,10 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
|
|||||||
|
|
||||||
// Optimization for common case of one frequently used synthetic grapheme:
|
// Optimization for common case of one frequently used synthetic grapheme:
|
||||||
static int32_t last_grapheme = 0;
|
static int32_t last_grapheme = 0;
|
||||||
if (last_grapheme != 0 && graphemes_equal(&ptr, &synthetic_graphemes[-last_grapheme-1].utf32_cluster))
|
if (last_grapheme != 0 && graphemes_equal(&ptr, &synthetic_graphemes[-last_grapheme-1].utf32_cluster, NULL))
|
||||||
return last_grapheme;
|
return last_grapheme;
|
||||||
|
|
||||||
|
TypeInfo_t GraphemeIDLookupTableInfo = *Table$info(&GraphemeClusterInfo, &Int32$info);
|
||||||
int32_t *found = Table$get(grapheme_ids_by_codepoints, &ptr, &GraphemeIDLookupTableInfo);
|
int32_t *found = Table$get(grapheme_ids_by_codepoints, &ptr, &GraphemeIDLookupTableInfo);
|
||||||
if (found) return *found;
|
if (found) return *found;
|
||||||
|
|
||||||
@ -765,8 +765,9 @@ public char *Text$as_c_string(Text_t text)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public uint64_t Text$hash(Text_t *text)
|
PUREFUNC public uint64_t Text$hash(const void *obj, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
|
Text_t *text = (Text_t*)obj;
|
||||||
if (text->hash != 0) return text->hash;
|
if (text->hash != 0) return text->hash;
|
||||||
siphash sh;
|
siphash sh;
|
||||||
siphashinit(&sh, sizeof(int32_t[text->length]));
|
siphashinit(&sh, sizeof(int32_t[text->length]));
|
||||||
@ -906,9 +907,11 @@ public uint32_t Text$get_main_grapheme_fast(TextIter_t *state, int64_t index)
|
|||||||
return (g) >= 0 ? (ucs4_t)(g) : synthetic_graphemes[-(g)-1].main_codepoint;
|
return (g) >= 0 ? (ucs4_t)(g) : synthetic_graphemes[-(g)-1].main_codepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public int32_t Text$compare(const Text_t *a, const Text_t *b)
|
PUREFUNC public int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
if (a == b) return 0;
|
if (va == vb) return 0;
|
||||||
|
const Text_t *a = (const Text_t*)va;
|
||||||
|
const Text_t *b = (const Text_t*)vb;
|
||||||
|
|
||||||
int64_t len = MAX(a->length, b->length);
|
int64_t len = MAX(a->length, b->length);
|
||||||
TextIter_t a_state = {*a, 0, 0}, b_state = {*b, 0, 0};
|
TextIter_t a_state = {*a, 0, 0}, b_state = {*b, 0, 0};
|
||||||
@ -981,10 +984,10 @@ PUREFUNC public bool Text$equal_values(Text_t a, Text_t b)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool Text$equal(const Text_t *a, const Text_t *b)
|
PUREFUNC public bool Text$equal(const void *a, const void *b, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
if (a == b) return true;
|
if (a == b) return true;
|
||||||
return Text$equal_values(*a, *b);
|
return Text$equal_values(*(Text_t*)a, *(Text_t*)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b)
|
PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b)
|
||||||
@ -1369,11 +1372,17 @@ public Array_t Text$lines(Text_t text)
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUREFUNC public bool Text$is_none(const void *t, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return ((Text_t*)t)->length < 0;
|
||||||
|
}
|
||||||
|
|
||||||
public const TypeInfo_t Text$info = {
|
public const TypeInfo_t Text$info = {
|
||||||
.size=sizeof(Text_t),
|
.size=sizeof(Text_t),
|
||||||
.align=__alignof__(Text_t),
|
.align=__alignof__(Text_t),
|
||||||
.tag=TextInfo,
|
.tag=TextInfo,
|
||||||
.TextInfo={.lang="Text"},
|
.TextInfo={.lang="Text"},
|
||||||
|
.metamethods=Text$metamethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
public Pattern_t Pattern$escape_text(Text_t text)
|
public Pattern_t Pattern$escape_text(Text_t text)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "integers.h"
|
#include "integers.h"
|
||||||
#include "optionals.h"
|
#include "optionals.h"
|
||||||
|
#include "types.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -31,11 +32,12 @@ Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int);
|
|||||||
Text_t Text$cluster(Text_t text, Int_t index_int);
|
Text_t Text$cluster(Text_t text, Int_t index_int);
|
||||||
OptionalText_t Text$from_str(const char *str);
|
OptionalText_t Text$from_str(const char *str);
|
||||||
OptionalText_t Text$from_strn(const char *str, size_t len);
|
OptionalText_t Text$from_strn(const char *str, size_t len);
|
||||||
PUREFUNC uint64_t Text$hash(Text_t *text);
|
PUREFUNC uint64_t Text$hash(const void *text, const TypeInfo_t*);
|
||||||
PUREFUNC int32_t Text$compare(const Text_t *a, const Text_t *b);
|
PUREFUNC int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t*);
|
||||||
PUREFUNC bool Text$equal(const Text_t *a, const Text_t *b);
|
PUREFUNC bool Text$equal(const void *a, const void *b, const TypeInfo_t*);
|
||||||
PUREFUNC bool Text$equal_values(Text_t a, Text_t b);
|
PUREFUNC bool Text$equal_values(Text_t a, Text_t b);
|
||||||
PUREFUNC bool Text$equal_ignoring_case(Text_t a, Text_t b);
|
PUREFUNC bool Text$equal_ignoring_case(Text_t a, Text_t b);
|
||||||
|
PUREFUNC bool Text$is_none(const void *t, const TypeInfo_t*);
|
||||||
Text_t Text$upper(Text_t text);
|
Text_t Text$upper(Text_t text);
|
||||||
Text_t Text$lower(Text_t text);
|
Text_t Text$lower(Text_t text);
|
||||||
Text_t Text$title(Text_t text);
|
Text_t Text$title(Text_t text);
|
||||||
@ -67,4 +69,12 @@ MACROLIKE int32_t Text$get_grapheme(Text_t text, int64_t index)
|
|||||||
|
|
||||||
extern const TypeInfo_t Text$info;
|
extern const TypeInfo_t Text$info;
|
||||||
|
|
||||||
|
#define Text$metamethods ((metamethods_t){ \
|
||||||
|
.as_text=Text$as_text, \
|
||||||
|
.hash=Text$hash, \
|
||||||
|
.compare=Text$compare, \
|
||||||
|
.equal=Text$equal, \
|
||||||
|
.is_none=Text$is_none, \
|
||||||
|
})
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -53,19 +53,25 @@ public void Thread$detach(Thread_t thread)
|
|||||||
pthread_detach(*thread);
|
pthread_detach(*thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
Text_t Thread$as_text(const Thread_t *thread, bool colorize, const TypeInfo_t *type)
|
Text_t Thread$as_text(const void *thread, bool colorize, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
(void)type;
|
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return colorize ? Text("\x1b[34;1mThread\x1b[m") : Text("Thread");
|
return colorize ? Text("\x1b[34;1mThread\x1b[m") : Text("Thread");
|
||||||
}
|
}
|
||||||
return Text$format(colorize ? "\x1b[34;1mThread(%p)\x1b[m" : "Thread(%p)", *thread);
|
return Text$format(colorize ? "\x1b[34;1mThread(%p)\x1b[m" : "Thread(%p)", *(Thread_t**)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Thread$is_none(const void *obj, const TypeInfo_t*)
|
||||||
|
{
|
||||||
|
return *(Thread_t*)obj == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo_t Thread$info = {
|
public const TypeInfo_t Thread$info = {
|
||||||
.size=sizeof(Thread_t), .align=__alignof(Thread_t),
|
.size=sizeof(Thread_t), .align=__alignof(Thread_t),
|
||||||
.tag=CustomInfo,
|
.metamethods={
|
||||||
.CustomInfo={.as_text=(void*)Thread$as_text},
|
.as_text=Thread$as_text,
|
||||||
|
.is_none=Thread$is_none,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||||
|
@ -15,7 +15,7 @@ Thread_t Thread$new(Closure_t fn);
|
|||||||
void Thread$cancel(Thread_t thread);
|
void Thread$cancel(Thread_t thread);
|
||||||
void Thread$join(Thread_t thread);
|
void Thread$join(Thread_t thread);
|
||||||
void Thread$detach(Thread_t thread);
|
void Thread$detach(Thread_t thread);
|
||||||
Text_t Thread$as_text(const Thread_t *thread, bool colorize, const TypeInfo_t *type);
|
Text_t Thread$as_text(const void *thread, bool colorize, const TypeInfo_t *type);
|
||||||
|
|
||||||
extern const TypeInfo_t Thread$info;
|
extern const TypeInfo_t Thread$info;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "c_strings.h"
|
#include "c_strings.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "enums.h"
|
||||||
#include "functiontype.h"
|
#include "functiontype.h"
|
||||||
#include "integers.h"
|
#include "integers.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "siphash.h"
|
#include "siphash.h"
|
||||||
|
#include "structs.h"
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
|
|
||||||
typedef struct TypeInfo_s TypeInfo_t;
|
typedef struct TypeInfo_s TypeInfo_t;
|
||||||
|
|
||||||
typedef uint64_t (*hash_fn_t)(const void*, const TypeInfo_t*);
|
typedef struct {
|
||||||
typedef int32_t (*compare_fn_t)(const void*, const void*, const TypeInfo_t*);
|
uint64_t (*hash)(const void*, const TypeInfo_t*);
|
||||||
typedef bool (*equal_fn_t)(const void*, const void*, const TypeInfo_t*);
|
int32_t (*compare)(const void*, const void*, const TypeInfo_t*);
|
||||||
typedef Text_t (*text_fn_t)(const void*, bool, const TypeInfo_t*);
|
bool (*equal)(const void*, const void*, const TypeInfo_t*);
|
||||||
|
Text_t (*as_text)(const void*, bool, const TypeInfo_t*);
|
||||||
|
bool (*is_none)(const void*, const TypeInfo_t*);
|
||||||
|
} metamethods_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -21,16 +24,12 @@ typedef struct {
|
|||||||
|
|
||||||
struct TypeInfo_s {
|
struct TypeInfo_s {
|
||||||
int64_t size, align;
|
int64_t size, align;
|
||||||
|
metamethods_t metamethods;
|
||||||
struct { // Anonymous tagged union for convenience
|
struct { // Anonymous tagged union for convenience
|
||||||
enum { Invalid, CustomInfo, StructInfo, EnumInfo, PointerInfo, TextInfo, ArrayInfo, ChannelInfo, TableInfo, FunctionInfo,
|
enum { OpaqueInfo, StructInfo, EnumInfo, PointerInfo, TextInfo, ArrayInfo, ChannelInfo, TableInfo, FunctionInfo,
|
||||||
OptionalInfo, TypeInfoInfo, OpaqueInfo, CStringInfo } tag;
|
OptionalInfo, TypeInfoInfo } tag;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {} OpaqueInfo;
|
||||||
equal_fn_t equal;
|
|
||||||
compare_fn_t compare;
|
|
||||||
hash_fn_t hash;
|
|
||||||
text_fn_t as_text;
|
|
||||||
} CustomInfo;
|
|
||||||
struct {
|
struct {
|
||||||
const char *sigil;
|
const char *sigil;
|
||||||
const TypeInfo_t *pointed;
|
const TypeInfo_t *pointed;
|
||||||
@ -53,7 +52,6 @@ struct TypeInfo_s {
|
|||||||
struct {
|
struct {
|
||||||
const TypeInfo_t *type;
|
const TypeInfo_t *type;
|
||||||
} OptionalInfo;
|
} OptionalInfo;
|
||||||
struct {} OpaqueInfo;
|
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int num_tags;
|
int num_tags;
|
||||||
@ -69,24 +67,8 @@ struct TypeInfo_s {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define Pointer$info(sigil_expr, pointed_info) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
|
|
||||||
.tag=PointerInfo, .PointerInfo={.sigil=sigil_expr, .pointed=pointed_info}})
|
|
||||||
#define Array$info(item_info) &((TypeInfo_t){.size=sizeof(Array_t), .align=__alignof__(Array_t), \
|
|
||||||
.tag=ArrayInfo, .ArrayInfo.item=item_info})
|
|
||||||
#define Set$info(item_info) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
|
|
||||||
.tag=TableInfo, .TableInfo.key=item_info, .TableInfo.value=&Void$info})
|
|
||||||
#define Channel$info(item_info) &((TypeInfo_t){.size=sizeof(Channel_t), .align=__alignof__(Channel_t), \
|
|
||||||
.tag=ChannelInfo, .ChannelInfo.item=item_info})
|
|
||||||
#define Table$info(key_expr, value_expr) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
|
|
||||||
.tag=TableInfo, .TableInfo.key=key_expr, .TableInfo.value=value_expr})
|
|
||||||
#define Function$info(typestr) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
|
|
||||||
.tag=FunctionInfo, .FunctionInfo.type_str=typestr})
|
|
||||||
#define Closure$info(typestr) &((TypeInfo_t){.size=sizeof(void*[2]), .align=__alignof__(void*), \
|
|
||||||
.tag=FunctionInfo, .FunctionInfo.type_str=typestr})
|
|
||||||
#define Type$info(typestr) &((TypeInfo_t){.size=sizeof(TypeInfo_t), .align=__alignof__(TypeInfo_t), \
|
#define Type$info(typestr) &((TypeInfo_t){.size=sizeof(TypeInfo_t), .align=__alignof__(TypeInfo_t), \
|
||||||
.tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr})
|
.tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr})
|
||||||
#define Optional$info(_size, _align, t) &((TypeInfo_t){.size=_size, .align=_align, \
|
|
||||||
.tag=OptionalInfo, .OptionalInfo.type=t})
|
|
||||||
|
|
||||||
extern const TypeInfo_t Void$info;
|
extern const TypeInfo_t Void$info;
|
||||||
extern const TypeInfo_t Abort$info;
|
extern const TypeInfo_t Abort$info;
|
||||||
|
@ -27,7 +27,8 @@ void compile_struct_def(env_t *env, ast_t *ast)
|
|||||||
short_name = strrchr(short_name, '$') + 1;
|
short_name = strrchr(short_name, '$') + 1;
|
||||||
|
|
||||||
env->code->typeinfos = CORD_all("public const TypeInfo_t ", full_name, ";\n", env->code->typeinfos);
|
env->code->typeinfos = CORD_all("public const TypeInfo_t ", full_name, ";\n", env->code->typeinfos);
|
||||||
CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r = {.size=%zu, .align=%zu, .tag=StructInfo, .StructInfo.name=\"%s\"%s, "
|
CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r = {.size=%zu, .align=%zu, .metamethods=Struct$metamethods, "
|
||||||
|
".tag=StructInfo, .StructInfo.name=\"%s\"%s, "
|
||||||
".StructInfo.num_fields=%ld",
|
".StructInfo.num_fields=%ld",
|
||||||
full_name, type_size(t), type_align(t), short_name, def->secret ? ", .StructInfo.is_secret=true" : "",
|
full_name, type_size(t), type_align(t), short_name, def->secret ? ", .StructInfo.is_secret=true" : "",
|
||||||
num_fields);
|
num_fields);
|
||||||
|
Loading…
Reference in New Issue
Block a user