Switch naming convention to use '$' in symbols more
This commit is contained in:
parent
d94053ca77
commit
04d9adc813
2
Makefile
2
Makefile
@ -27,7 +27,7 @@ LDLIBS=-lgc -lcord -lm -lunistring
|
|||||||
BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/color.o builtins/nums.o builtins/functions.o builtins/integers.o \
|
BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/color.o builtins/nums.o builtins/functions.o builtins/integers.o \
|
||||||
builtins/pointer.o builtins/memory.o builtins/text.o builtins/table.o builtins/types.o builtins/util.o builtins/files.o
|
builtins/pointer.o builtins/memory.o builtins/text.o builtins/table.o builtins/types.o builtins/util.o builtins/files.o
|
||||||
|
|
||||||
all: libtomo.so tomo
|
all: libtomo.so tomo repl.o
|
||||||
|
|
||||||
tomo: tomo.c SipHash/halfsiphash.o ast.o parse.o environment.o types.o typecheck.o structs.o enums.o compile.o $(BUILTIN_OBJS)
|
tomo: tomo.c SipHash/halfsiphash.o ast.o parse.o environment.o types.o typecheck.o structs.o enums.o compile.o $(BUILTIN_OBJS)
|
||||||
|
|
||||||
|
6
ast.c
6
ast.c
@ -26,9 +26,9 @@ static CORD optional_tagged_type(const char *tag, type_ast_t *ast);
|
|||||||
|
|
||||||
CORD xml_escape(CORD text)
|
CORD xml_escape(CORD text)
|
||||||
{
|
{
|
||||||
text = Text__replace(text, "&", "&", INT64_MAX);
|
text = Text$replace(text, "&", "&", INT64_MAX);
|
||||||
text = Text__replace(text, "<", "<", INT64_MAX);
|
text = Text$replace(text, "<", "<", INT64_MAX);
|
||||||
text = Text__replace(text, ">", ">", INT64_MAX);
|
text = Text$replace(text, ">", ">", INT64_MAX);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ static inline size_t get_item_size(const TypeInfo *info)
|
|||||||
|
|
||||||
// Replace the array's .data pointer with a new pointer to a copy of the
|
// Replace the array's .data pointer with a new pointer to a copy of the
|
||||||
// data that is compacted and has a stride of exactly `item_size`
|
// data that is compacted and has a stride of exactly `item_size`
|
||||||
public void Array__compact(array_t *arr, const TypeInfo *type)
|
public void Array$compact(array_t *arr, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
void *copy = NULL;
|
void *copy = NULL;
|
||||||
int64_t item_size = get_item_size(type);
|
int64_t item_size = get_item_size(type);
|
||||||
@ -43,7 +43,7 @@ public void Array__compact(array_t *arr, const TypeInfo *type)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type)
|
public void Array$insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (index <= 0) index = arr->length + index + 1;
|
if (index <= 0) index = arr->length + index + 1;
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ public void Array__insert(array_t *arr, const void *item, int64_t index, const T
|
|||||||
memcpy((void*)arr->data + (index-1)*item_size, item, item_size);
|
memcpy((void*)arr->data + (index-1)*item_size, item, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type)
|
public void Array$insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (index < 1) index = arr->length + index + 1;
|
if (index < 1) index = arr->length + index + 1;
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public void Array__insert_all(array_t *arr, array_t to_insert, int64_t index, co
|
|||||||
memcpy((void*)arr->data + (index-1 + i)*item_size, to_insert.data + i*to_insert.stride, item_size);
|
memcpy((void*)arr->data + (index-1 + i)*item_size, to_insert.data + i*to_insert.stride, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type)
|
public void Array$remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (index < 1) index = arr->length + index + 1;
|
if (index < 1) index = arr->length + index + 1;
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ public void Array__remove(array_t *arr, int64_t index, int64_t count, const Type
|
|||||||
arr->length -= count;
|
arr->length -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__sort(array_t *arr, const TypeInfo *type)
|
public void Array$sort(array_t *arr, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
const TypeInfo *item_type = type->ArrayInfo.item;
|
const TypeInfo *item_type = type->ArrayInfo.item;
|
||||||
int64_t item_size = item_type->size;
|
int64_t item_size = item_type->size;
|
||||||
@ -146,16 +146,16 @@ public void Array__sort(array_t *arr, const TypeInfo *type)
|
|||||||
item_size += item_type->align - (item_size % item_type->align); // padding
|
item_size += item_type->align - (item_size % item_type->align); // padding
|
||||||
|
|
||||||
if (arr->data_refcount || (int64_t)arr->stride != item_size)
|
if (arr->data_refcount || (int64_t)arr->stride != item_size)
|
||||||
Array__compact(arr, type);
|
Array$compact(arr, type);
|
||||||
|
|
||||||
qsort_r(arr->data, arr->length, item_size, (void*)generic_compare, (void*)item_type);
|
qsort_r(arr->data, arr->length, item_size, (void*)generic_compare, (void*)item_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__shuffle(array_t *arr, const TypeInfo *type)
|
public void Array$shuffle(array_t *arr, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
int64_t item_size = get_item_size(type);
|
int64_t item_size = get_item_size(type);
|
||||||
if (arr->data_refcount || (int64_t)arr->stride != item_size)
|
if (arr->data_refcount || (int64_t)arr->stride != item_size)
|
||||||
Array__compact(arr, type);
|
Array$compact(arr, type);
|
||||||
|
|
||||||
char tmp[item_size];
|
char tmp[item_size];
|
||||||
for (int64_t i = arr->length-1; i > 1; i--) {
|
for (int64_t i = arr->length-1; i > 1; i--) {
|
||||||
@ -166,7 +166,7 @@ public void Array__shuffle(array_t *arr, const TypeInfo *type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void *Array__random(array_t arr)
|
public void *Array$random(array_t arr)
|
||||||
{
|
{
|
||||||
if (arr.length == 0)
|
if (arr.length == 0)
|
||||||
return NULL; // fail("Cannot get a random item from an empty array!");
|
return NULL; // fail("Cannot get a random item from an empty array!");
|
||||||
@ -174,7 +174,7 @@ public void *Array__random(array_t arr)
|
|||||||
return arr.data + arr.stride*index;
|
return arr.data + arr.stride*index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Array__slice(array_t *array, int64_t first, int64_t length, int64_t stride, const TypeInfo *type)
|
public array_t Array$slice(array_t *array, int64_t first, int64_t length, int64_t stride, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (stride > MAX_STRIDE || stride < MIN_STRIDE)
|
if (stride > MAX_STRIDE || stride < MIN_STRIDE)
|
||||||
fail("Stride is too big: %ld", stride);
|
fail("Stride is too big: %ld", stride);
|
||||||
@ -223,7 +223,7 @@ public array_t Array__slice(array_t *array, int64_t first, int64_t length, int64
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Array__reversed(array_t array)
|
public array_t Array$reversed(array_t array)
|
||||||
{
|
{
|
||||||
array_t reversed = array;
|
array_t reversed = array;
|
||||||
reversed.stride = -array.stride;
|
reversed.stride = -array.stride;
|
||||||
@ -231,7 +231,7 @@ public array_t Array__reversed(array_t array)
|
|||||||
return reversed;
|
return reversed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Array__concat(array_t x, array_t y, const TypeInfo *type)
|
public array_t Array$concat(array_t x, array_t y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
int64_t item_size = get_item_size(type);
|
int64_t item_size = get_item_size(type);
|
||||||
void *data = x.atomic ? GC_MALLOC_ATOMIC(item_size*(x.length + y.length)) : GC_MALLOC(item_size*(x.length + y.length));
|
void *data = x.atomic ? GC_MALLOC_ATOMIC(item_size*(x.length + y.length)) : GC_MALLOC(item_size*(x.length + y.length));
|
||||||
@ -257,7 +257,7 @@ public array_t Array__concat(array_t x, array_t y, const TypeInfo *type)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Array__contains(array_t array, void *item, const TypeInfo *type)
|
public bool Array$contains(array_t array, void *item, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
const TypeInfo *item_type = type->ArrayInfo.item;
|
const TypeInfo *item_type = type->ArrayInfo.item;
|
||||||
for (int64_t i = 0; i < array.length; i++)
|
for (int64_t i = 0; i < array.length; i++)
|
||||||
@ -266,12 +266,12 @@ public bool Array__contains(array_t array, void *item, const TypeInfo *type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Array__clear(array_t *array)
|
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 *type)
|
public int32_t Array$compare(const array_t *x, const array_t *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
// 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)
|
||||||
@ -298,12 +298,12 @@ 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 *type)
|
public bool Array$equal(const array_t *x, const array_t *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
return (Array__compare(x, y, type) == 0);
|
return (Array$compare(x, y, type) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Array__as_text(const array_t *arr, bool colorize, const TypeInfo *type)
|
public CORD Array$as_text(const array_t *arr, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return CORD_all("[", generic_as_text(NULL, false, type->ArrayInfo.item), "]");
|
return CORD_all("[", generic_as_text(NULL, false, type->ArrayInfo.item), "]");
|
||||||
@ -320,7 +320,7 @@ public CORD Array__as_text(const array_t *arr, bool colorize, const TypeInfo *ty
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint32_t Array__hash(const array_t *arr, const TypeInfo *type)
|
public uint32_t Array$hash(const array_t *arr, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
// Array hash is calculated as a rolling, compacting hash of the length of the array, followed by
|
// Array hash is calculated as a rolling, compacting hash of the length of the array, followed by
|
||||||
// the hashes of its items (or the items themselves if they're small plain data)
|
// the hashes of its items (or the items themselves if they're small plain data)
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
const array_t $arr = arr_expr; int64_t $index = (int64_t)(index_expr); \
|
const array_t $arr = arr_expr; int64_t $index = (int64_t)(index_expr); \
|
||||||
int64_t $off = $index + ($index < 0) * ($arr.length + 1) - 1; \
|
int64_t $off = $index + ($index < 0) * ($arr.length + 1) - 1; \
|
||||||
if (__builtin_expect($off < 0 || $off >= $arr.length, 0)) \
|
if (__builtin_expect($off < 0 || $off >= $arr.length, 0)) \
|
||||||
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int__as_text(&$index, USE_COLOR, NULL), $arr.length); \
|
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int$as_text(&$index, USE_COLOR, NULL), $arr.length); \
|
||||||
(item_type*)($arr.data + $arr.stride * $off);})
|
(item_type*)($arr.data + $arr.stride * $off);})
|
||||||
#define $Array_lvalue(item_type, arr_expr, index_expr, typeinfo, filename, start, end) { \
|
#define $Array_lvalue(item_type, arr_expr, index_expr, typeinfo, filename, start, end) { \
|
||||||
array_t *$arr = arr_expr; int64_t $index = (int64_t)(index_expr); \
|
array_t *$arr = arr_expr; int64_t $index = (int64_t)(index_expr); \
|
||||||
int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \
|
int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \
|
||||||
if (__builtin_expect($off < 0 || $off >= $arr->length, 0)) \
|
if (__builtin_expect($off < 0 || $off >= $arr->length, 0)) \
|
||||||
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int__as_text(&$index, USE_COLOR, NULL), $arr->length); \
|
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int$as_text(&$index, USE_COLOR, NULL), $arr->length); \
|
||||||
if ($arr->data_refcount > 0) \
|
if ($arr->data_refcount > 0) \
|
||||||
Array__compact($arr, typeinfo); \
|
Array$compact($arr, typeinfo); \
|
||||||
*(item_type*)($arr->data + $arr->stride * $off); }
|
*(item_type*)($arr->data + $arr->stride * $off); }
|
||||||
#define $Array_set(item_type, arr, index, value, typeinfo, filename, start, end) \
|
#define $Array_set(item_type, arr, index, value, typeinfo, filename, start, end) \
|
||||||
$Array_lvalue(item_type, arr_expr, index, typeinfo, filename, start, end) = value
|
$Array_lvalue(item_type, arr_expr, index, typeinfo, filename, start, end) = value
|
||||||
@ -52,22 +52,22 @@
|
|||||||
#define $ARRAY_INCREF(arr) (arr).data_refcount |= ((arr).data_refcount << 1) | 1
|
#define $ARRAY_INCREF(arr) (arr).data_refcount |= ((arr).data_refcount << 1) | 1
|
||||||
#define $ARRAY_DECREF(arr) (arr).data_refcount &= 2
|
#define $ARRAY_DECREF(arr) (arr).data_refcount &= 2
|
||||||
|
|
||||||
#define Array__insert_value(arr, item_expr, index, type) ({ __typeof(item_expr) $item = item_expr; Array__insert(arr, &$item, index, type); })
|
#define Array$insert_value(arr, item_expr, index, type) ({ __typeof(item_expr) $item = item_expr; Array$insert(arr, &$item, index, type); })
|
||||||
void Array__insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type);
|
void Array$insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type);
|
||||||
void Array__insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type);
|
void Array$insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type);
|
||||||
void Array__remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type);
|
void Array$remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type);
|
||||||
void Array__sort(array_t *arr, const TypeInfo *type);
|
void Array$sort(array_t *arr, const TypeInfo *type);
|
||||||
void Array__shuffle(array_t *arr, const TypeInfo *type);
|
void Array$shuffle(array_t *arr, const TypeInfo *type);
|
||||||
void *Array__random(array_t arr);
|
void *Array$random(array_t arr);
|
||||||
void Array__clear(array_t *array);
|
void Array$clear(array_t *array);
|
||||||
void Array__compact(array_t *arr, const TypeInfo *type);
|
void Array$compact(array_t *arr, const TypeInfo *type);
|
||||||
bool Array__contains(array_t array, void *item, const TypeInfo *type);
|
bool Array$contains(array_t array, void *item, const TypeInfo *type);
|
||||||
array_t Array__slice(array_t *array, int64_t first, int64_t length, int64_t stride, const TypeInfo *type);
|
array_t Array$slice(array_t *array, int64_t first, int64_t length, int64_t stride, const TypeInfo *type);
|
||||||
array_t Array__reversed(array_t array);
|
array_t Array$reversed(array_t array);
|
||||||
array_t Array__concat(array_t x, array_t y, const TypeInfo *type);
|
array_t Array$concat(array_t x, array_t y, const TypeInfo *type);
|
||||||
uint32_t Array__hash(const array_t *arr, const TypeInfo *type);
|
uint32_t Array$hash(const array_t *arr, const TypeInfo *type);
|
||||||
int32_t Array__compare(const array_t *x, const array_t *y, const TypeInfo *type);
|
int32_t Array$compare(const array_t *x, const array_t *y, const TypeInfo *type);
|
||||||
bool Array__equal(const array_t *x, const array_t *y, const TypeInfo *type);
|
bool Array$equal(const array_t *x, const array_t *y, const TypeInfo *type);
|
||||||
CORD Array__as_text(const array_t *arr, bool colorize, const TypeInfo *type);
|
CORD Array$as_text(const array_t *arr, bool colorize, const TypeInfo *type);
|
||||||
|
|
||||||
// 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,7 +12,7 @@
|
|||||||
#include "bool.h"
|
#include "bool.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
public CORD Bool__as_text(const bool *b, bool colorize, const TypeInfo *type)
|
public CORD Bool$as_text(const bool *b, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
(void)type;
|
(void)type;
|
||||||
if (!b) return "Bool";
|
if (!b) return "Bool";
|
||||||
@ -22,11 +22,11 @@ public CORD Bool__as_text(const bool *b, bool colorize, const TypeInfo *type)
|
|||||||
return *b ? "yes" : "no";
|
return *b ? "yes" : "no";
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo Bool = {
|
public const TypeInfo $Bool = {
|
||||||
.size=sizeof(bool),
|
.size=sizeof(bool),
|
||||||
.align=__alignof__(bool),
|
.align=__alignof__(bool),
|
||||||
.tag=CustomInfo,
|
.tag=CustomInfo,
|
||||||
.CustomInfo={.as_text=(void*)Bool__as_text},
|
.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
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#define yes (Bool_t)true
|
#define yes (Bool_t)true
|
||||||
#define no (Bool_t)false
|
#define no (Bool_t)false
|
||||||
|
|
||||||
CORD Bool__as_text(const bool *b, bool colorize, const TypeInfo *type);
|
CORD Bool$as_text(const bool *b, bool colorize, const TypeInfo *type);
|
||||||
|
|
||||||
extern const TypeInfo Bool;
|
extern const TypeInfo $Bool;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -57,10 +57,10 @@ public void fail_source(const char *filename, int64_t start, int64_t end, CORD f
|
|||||||
public uint32_t generic_hash(const void *obj, const TypeInfo *type)
|
public uint32_t generic_hash(const void *obj, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
switch (type->tag) {
|
||||||
case PointerInfo: case FunctionInfo: return Pointer__hash(obj, type);
|
case PointerInfo: case FunctionInfo: return Pointer$hash(obj, type);
|
||||||
case TextInfo: return Text__hash(obj);
|
case TextInfo: return Text$hash(obj);
|
||||||
case ArrayInfo: return Array__hash(obj, type);
|
case ArrayInfo: return Array$hash(obj, type);
|
||||||
case TableInfo: return Table_hash(obj, type);
|
case TableInfo: return Table$hash(obj, type);
|
||||||
case CustomInfo:
|
case CustomInfo:
|
||||||
if (!type->CustomInfo.hash)
|
if (!type->CustomInfo.hash)
|
||||||
goto hash_data;
|
goto hash_data;
|
||||||
@ -77,10 +77,10 @@ public uint32_t generic_hash(const void *obj, const TypeInfo *type)
|
|||||||
public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type)
|
public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
switch (type->tag) {
|
||||||
case PointerInfo: case FunctionInfo: return Pointer__compare(x, y, type);
|
case PointerInfo: case FunctionInfo: return Pointer$compare(x, y, type);
|
||||||
case TextInfo: return Text__compare(x, y);
|
case TextInfo: return Text$compare(x, y);
|
||||||
case ArrayInfo: return Array__compare(x, y, type);
|
case ArrayInfo: return Array$compare(x, y, type);
|
||||||
case TableInfo: return Table_compare(x, y, type);
|
case TableInfo: return Table$compare(x, y, type);
|
||||||
case CustomInfo:
|
case CustomInfo:
|
||||||
if (!type->CustomInfo.compare)
|
if (!type->CustomInfo.compare)
|
||||||
goto compare_data;
|
goto compare_data;
|
||||||
@ -94,10 +94,10 @@ public int32_t generic_compare(const void *x, const void *y, const TypeInfo *typ
|
|||||||
public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
|
public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
switch (type->tag) {
|
||||||
case PointerInfo: case FunctionInfo: return Pointer__equal(x, y, type);
|
case PointerInfo: case FunctionInfo: return Pointer$equal(x, y, type);
|
||||||
case TextInfo: return Text__equal(x, y);
|
case TextInfo: return Text$equal(x, y);
|
||||||
case ArrayInfo: return Array__equal(x, y, type);
|
case ArrayInfo: return Array$equal(x, y, type);
|
||||||
case TableInfo: return Table_equal(x, y, type);
|
case TableInfo: return Table$equal(x, y, type);
|
||||||
case CustomInfo:
|
case CustomInfo:
|
||||||
if (!type->CustomInfo.equal)
|
if (!type->CustomInfo.equal)
|
||||||
goto use_generic_compare;
|
goto use_generic_compare;
|
||||||
@ -111,12 +111,12 @@ public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
|
|||||||
public CORD generic_as_text(const void *obj, bool colorize, const TypeInfo *type)
|
public CORD generic_as_text(const void *obj, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
switch (type->tag) {
|
switch (type->tag) {
|
||||||
case PointerInfo: return Pointer__as_text(obj, colorize, type);
|
case PointerInfo: return Pointer$as_text(obj, colorize, type);
|
||||||
case FunctionInfo: return Func__as_text(obj, colorize, type);
|
case FunctionInfo: return Func$as_text(obj, colorize, type);
|
||||||
case TextInfo: return Text__as_text(obj, colorize, type);
|
case TextInfo: return Text$as_text(obj, colorize, type);
|
||||||
case ArrayInfo: return Array__as_text(obj, colorize, type);
|
case ArrayInfo: return Array$as_text(obj, colorize, type);
|
||||||
case TableInfo: return Table_as_text(obj, colorize, type);
|
case TableInfo: return Table$as_text(obj, colorize, type);
|
||||||
case TypeInfoInfo: return Type__as_text(obj, colorize, type);
|
case TypeInfoInfo: return Type$as_text(obj, colorize, type);
|
||||||
case CustomInfo:
|
case CustomInfo:
|
||||||
if (!type->CustomInfo.as_text)
|
if (!type->CustomInfo.as_text)
|
||||||
fail("No cord function provided for type!\n");
|
fail("No cord function provided for type!\n");
|
||||||
@ -156,10 +156,10 @@ public void $test(void *expr, const TypeInfo *type, CORD expected, const char *f
|
|||||||
CORD_fprintf(stderr, USE_COLOR ? "\x1b[2m=\x1b[0m %r \x1b[2m: %r\x1b[m\n" : "= %r : %r\n", expr_normalized, type_name);
|
CORD_fprintf(stderr, USE_COLOR ? "\x1b[2m=\x1b[0m %r \x1b[2m: %r\x1b[m\n" : "= %r : %r\n", expr_normalized, type_name);
|
||||||
if (expected) {
|
if (expected) {
|
||||||
CORD expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_normalized;
|
CORD expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_normalized;
|
||||||
bool success = Text__equal(&expr_plain, &expected);
|
bool success = Text$equal(&expr_plain, &expected);
|
||||||
if (!success && CORD_chr(expected, 0, ':')) {
|
if (!success && CORD_chr(expected, 0, ':')) {
|
||||||
CORD with_type = CORD_catn(3, expr_plain, " : ", type_name);
|
CORD with_type = CORD_catn(3, expr_plain, " : ", type_name);
|
||||||
success = Text__equal(&with_type, &expected);
|
success = Text$equal(&with_type, &expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#define str(a) #a
|
#define str(a) #a
|
||||||
|
|
||||||
#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val)\
|
#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val)\
|
||||||
public CORD KindOfInt ## __as_text(const c_type *i, bool colorize, const TypeInfo *type) { \
|
public CORD KindOfInt ## $as_text(const c_type *i, bool colorize, const TypeInfo *type) { \
|
||||||
(void)type; \
|
(void)type; \
|
||||||
if (!i) return #KindOfInt; \
|
if (!i) return #KindOfInt; \
|
||||||
CORD c; \
|
CORD c; \
|
||||||
@ -23,26 +23,26 @@
|
|||||||
else CORD_sprintf(&c, "%"fmt, *i); \
|
else CORD_sprintf(&c, "%"fmt, *i); \
|
||||||
return c; \
|
return c; \
|
||||||
} \
|
} \
|
||||||
public int32_t KindOfInt ## __compare(const c_type *x, const c_type *y, const TypeInfo *type) { \
|
public int32_t KindOfInt ## $compare(const c_type *x, const c_type *y, const TypeInfo *type) { \
|
||||||
(void)type; \
|
(void)type; \
|
||||||
return (*x > *y) - (*x < *y); \
|
return (*x > *y) - (*x < *y); \
|
||||||
} \
|
} \
|
||||||
public bool KindOfInt ## __equal(const c_type *x, const c_type *y, const TypeInfo *type) { \
|
public bool KindOfInt ## $equal(const c_type *x, const c_type *y, const TypeInfo *type) { \
|
||||||
(void)type; \
|
(void)type; \
|
||||||
return *x == *y; \
|
return *x == *y; \
|
||||||
} \
|
} \
|
||||||
public CORD KindOfInt ## __format(c_type i, int64_t digits) { \
|
public CORD KindOfInt ## $format(c_type i, int64_t digits) { \
|
||||||
return CORD_asprintf("%0*" fmt, (int)digits, i); \
|
return CORD_asprintf("%0*" fmt, (int)digits, i); \
|
||||||
} \
|
} \
|
||||||
public CORD KindOfInt ## __hex(c_type i, int64_t digits, bool uppercase, bool prefix) { \
|
public CORD KindOfInt ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix) { \
|
||||||
const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); \
|
const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); \
|
||||||
return CORD_asprintf(hex_fmt, (int)digits, (uint64_t)i); \
|
return CORD_asprintf(hex_fmt, (int)digits, (uint64_t)i); \
|
||||||
} \
|
} \
|
||||||
public CORD KindOfInt ## __octal(c_type i, int64_t digits, bool prefix) { \
|
public CORD KindOfInt ## $octal(c_type i, int64_t digits, bool prefix) { \
|
||||||
const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; \
|
const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; \
|
||||||
return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)i); \
|
return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)i); \
|
||||||
} \
|
} \
|
||||||
public array_t KindOfInt ## __bits(c_type x) { \
|
public array_t KindOfInt ## $bits(c_type x) { \
|
||||||
array_t bit_array = (array_t){.data=GC_MALLOC_ATOMIC(sizeof(bool)*8*sizeof(c_type)), .atomic=1, .stride=sizeof(bool), .length=8*sizeof(c_type)}; \
|
array_t bit_array = (array_t){.data=GC_MALLOC_ATOMIC(sizeof(bool)*8*sizeof(c_type)), .atomic=1, .stride=sizeof(bool), .length=8*sizeof(c_type)}; \
|
||||||
bool *bits = bit_array.data + sizeof(c_type)*8; \
|
bool *bits = bit_array.data + sizeof(c_type)*8; \
|
||||||
for (size_t i = 0; i < 8*sizeof(c_type); i++) { \
|
for (size_t i = 0; i < 8*sizeof(c_type); i++) { \
|
||||||
@ -51,7 +51,7 @@
|
|||||||
} \
|
} \
|
||||||
return bit_array; \
|
return bit_array; \
|
||||||
} \
|
} \
|
||||||
public c_type KindOfInt ## __random(int64_t min, int64_t max) { \
|
public c_type KindOfInt ## $random(int64_t min, int64_t max) { \
|
||||||
if (min > max) fail("Random min (%ld) is larger than max (%ld)", min, max); \
|
if (min > max) fail("Random min (%ld) is larger than max (%ld)", min, max); \
|
||||||
if (min < (int64_t)min_val) fail("Random min (%ld) is smaller than the minimum "#KindOfInt" value", min); \
|
if (min < (int64_t)min_val) fail("Random min (%ld) is smaller than the minimum "#KindOfInt" value", min); \
|
||||||
if (max > (int64_t)max_val) fail("Random max (%ld) is smaller than the maximum "#KindOfInt" value", max); \
|
if (max > (int64_t)max_val) fail("Random max (%ld) is smaller than the maximum "#KindOfInt" value", max); \
|
||||||
@ -60,13 +60,13 @@
|
|||||||
uint32_t r = arc4random_uniform((uint32_t)range); \
|
uint32_t r = arc4random_uniform((uint32_t)range); \
|
||||||
return min + (c_type)r; \
|
return min + (c_type)r; \
|
||||||
} \
|
} \
|
||||||
public const c_type KindOfInt##__min = min_val; \
|
public const c_type KindOfInt##$min = min_val; \
|
||||||
public const c_type KindOfInt##__max = max_val; \
|
public const c_type KindOfInt##$max = max_val; \
|
||||||
public const TypeInfo KindOfInt = { \
|
public const TypeInfo $ ## KindOfInt = { \
|
||||||
.size=sizeof(c_type), \
|
.size=sizeof(c_type), \
|
||||||
.align=__alignof__(c_type), \
|
.align=__alignof__(c_type), \
|
||||||
.tag=CustomInfo, \
|
.tag=CustomInfo, \
|
||||||
.CustomInfo={.compare=(void*)KindOfInt##__compare, .as_text=(void*)KindOfInt##__as_text}, \
|
.CustomInfo={.compare=(void*)KindOfInt##$compare, .as_text=(void*)KindOfInt##$as_text}, \
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_INT_TYPE(int64_t, Int, "ld", INT64_MIN, INT64_MAX);
|
DEFINE_INT_TYPE(int64_t, Int, "ld", INT64_MIN, INT64_MAX);
|
||||||
|
@ -19,26 +19,26 @@
|
|||||||
#define I8(x) ((int8_t)x)
|
#define I8(x) ((int8_t)x)
|
||||||
|
|
||||||
#define DEFINE_INT_TYPE(c_type, type_name) \
|
#define DEFINE_INT_TYPE(c_type, type_name) \
|
||||||
CORD type_name ## __as_text(const c_type *i, bool colorize, const TypeInfo *type); \
|
CORD type_name ## $as_text(const c_type *i, bool colorize, const TypeInfo *type); \
|
||||||
int32_t type_name ## __compare(const c_type *x, const c_type *y, const TypeInfo *type); \
|
int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo *type); \
|
||||||
bool type_name ## __equal(const c_type *x, const c_type *y, const TypeInfo *type); \
|
bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo *type); \
|
||||||
CORD type_name ## __format(c_type i, int64_t digits); \
|
CORD type_name ## $format(c_type i, int64_t digits); \
|
||||||
CORD type_name ## __hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
|
CORD type_name ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
|
||||||
CORD type_name ## __octal(c_type i, int64_t digits, bool prefix); \
|
CORD type_name ## $octal(c_type i, int64_t digits, bool prefix); \
|
||||||
array_t type_name ## __bits(c_type x); \
|
array_t type_name ## $bits(c_type x); \
|
||||||
c_type type_name ## __random(int64_t min, int64_t max); \
|
c_type type_name ## $random(int64_t min, int64_t max); \
|
||||||
extern const c_type type_name ## __min, type_name##__max; \
|
extern const c_type type_name ## $min, type_name##$max; \
|
||||||
extern const TypeInfo type_name;
|
extern const TypeInfo $ ## type_name;
|
||||||
|
|
||||||
DEFINE_INT_TYPE(int64_t, Int);
|
DEFINE_INT_TYPE(int64_t, Int);
|
||||||
DEFINE_INT_TYPE(int32_t, Int32);
|
DEFINE_INT_TYPE(int32_t, Int32);
|
||||||
DEFINE_INT_TYPE(int16_t, Int16);
|
DEFINE_INT_TYPE(int16_t, Int16);
|
||||||
DEFINE_INT_TYPE(int8_t, Int8);
|
DEFINE_INT_TYPE(int8_t, Int8);
|
||||||
#undef DEFINE_INT_TYPE
|
#undef DEFINE_INT_TYPE
|
||||||
|
|
||||||
#define Int__abs(...) I64(labs(__VA_ARGS__))
|
#define Int$abs(...) I64(labs(__VA_ARGS__))
|
||||||
#define Int32__abs(...) I32(abs(__VA_ARGS__))
|
#define Int32$abs(...) I32(abs(__VA_ARGS__))
|
||||||
#define Int16__abs(...) I16(abs(__VA_ARGS__))
|
#define Int16$abs(...) I16(abs(__VA_ARGS__))
|
||||||
#define Int8__abs(...) I8(abs(__VA_ARGS__))
|
#define Int8$abs(...) I8(abs(__VA_ARGS__))
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -21,7 +21,7 @@ public CORD Memory__as_text(const void *p, bool colorize, const TypeInfo *type)
|
|||||||
return cord;
|
return cord;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo Memory = {
|
public const TypeInfo $Memory = {
|
||||||
.size=0,
|
.size=0,
|
||||||
.align=0,
|
.align=0,
|
||||||
.tag=CustomInfo,
|
.tag=CustomInfo,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
extern const TypeInfo Memory;
|
extern const TypeInfo $Memory;
|
||||||
CORD Memory__as_text(const void *p, bool colorize, const TypeInfo *type);
|
CORD Memory$as_text(const void *p, bool colorize, const TypeInfo *type);
|
||||||
|
|
||||||
// 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 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
public CORD Num__as_text(const double *f, bool colorize, const TypeInfo *type) {
|
public CORD Num$as_text(const double *f, bool colorize, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
if (!f) return "Num";
|
if (!f) return "Num";
|
||||||
CORD c;
|
CORD c;
|
||||||
@ -22,17 +22,17 @@ public CORD Num__as_text(const double *f, bool colorize, const TypeInfo *type) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32_t Num__compare(const double *x, const double *y, const TypeInfo *type) {
|
public int32_t Num$compare(const double *x, const double *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
return (*x > *y) - (*x < *y);
|
return (*x > *y) - (*x < *y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num__equal(const double *x, const double *y, const TypeInfo *type) {
|
public bool Num$equal(const double *x, const double *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
return *x == *y;
|
return *x == *y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num__near(double a, double b, double ratio, double absolute) {
|
public bool Num$near(double a, double b, double ratio, double absolute) {
|
||||||
if (ratio < 0) ratio = 0;
|
if (ratio < 0) ratio = 0;
|
||||||
else if (ratio > 0) ratio = 1;
|
else if (ratio > 0) ratio = 1;
|
||||||
|
|
||||||
@ -47,43 +47,43 @@ public bool Num__near(double a, double b, double ratio, double absolute) {
|
|||||||
return (diff < epsilon);
|
return (diff < epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Num__format(double f, int64_t precision) {
|
public CORD Num$format(double f, int64_t precision) {
|
||||||
return CORD_asprintf("%.*f", (int)precision, f);
|
return CORD_asprintf("%.*f", (int)precision, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Num__scientific(double f, int64_t precision) {
|
public CORD Num$scientific(double f, int64_t precision) {
|
||||||
return CORD_asprintf("%.*e", (int)precision, f);
|
return CORD_asprintf("%.*e", (int)precision, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Num__mod(double num, double modulus) {
|
public double Num$mod(double num, double modulus) {
|
||||||
double result = fmod(num, modulus);
|
double result = fmod(num, modulus);
|
||||||
return (result < 0) != (modulus < 0) ? result + modulus : result;
|
return (result < 0) != (modulus < 0) ? result + modulus : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Num__random(void) {
|
public double Num$random(void) {
|
||||||
return drand48();
|
return drand48();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Num__nan(CORD tag) {
|
public double Num$nan(CORD tag) {
|
||||||
return nan(CORD_to_const_char_star(tag));
|
return nan(CORD_to_const_char_star(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num__isinf(double n) { return !!isinf(n); }
|
public bool Num$isinf(double n) { return !!isinf(n); }
|
||||||
public bool Num__finite(double n) { return !!finite(n); }
|
public bool Num$finite(double n) { return !!finite(n); }
|
||||||
public bool Num__isnan(double n) { return !!isnan(n); }
|
public bool Num$isnan(double n) { return !!isnan(n); }
|
||||||
|
|
||||||
public const TypeInfo Num = {
|
public const TypeInfo $Num = {
|
||||||
.size=sizeof(double),
|
.size=sizeof(double),
|
||||||
.align=__alignof__(double),
|
.align=__alignof__(double),
|
||||||
.tag=CustomInfo,
|
.tag=CustomInfo,
|
||||||
.CustomInfo={
|
.CustomInfo={
|
||||||
.compare=(void*)Num__compare,
|
.compare=(void*)Num$compare,
|
||||||
.equal=(void*)Num__equal,
|
.equal=(void*)Num$equal,
|
||||||
.as_text=(void*)Num__as_text,
|
.as_text=(void*)Num$as_text,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public CORD Num32__as_text(const float *f, bool colorize, const TypeInfo *type) {
|
public CORD Num32$as_text(const float *f, bool colorize, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
if (!f) return "Num32";
|
if (!f) return "Num32";
|
||||||
CORD c;
|
CORD c;
|
||||||
@ -92,17 +92,17 @@ public CORD Num32__as_text(const float *f, bool colorize, const TypeInfo *type)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type) {
|
public int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
return (*x > *y) - (*x < *y);
|
return (*x > *y) - (*x < *y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num32__equal(const float *x, const float *y, const TypeInfo *type) {
|
public bool Num32$equal(const float *x, const float *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
return *x == *y;
|
return *x == *y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num32__near(float a, float b, float ratio, float absolute) {
|
public bool Num32$near(float a, float b, float ratio, float absolute) {
|
||||||
if (ratio < 0) ratio = 0;
|
if (ratio < 0) ratio = 0;
|
||||||
else if (ratio > 0) ratio = 1;
|
else if (ratio > 0) ratio = 1;
|
||||||
|
|
||||||
@ -117,39 +117,39 @@ public bool Num32__near(float a, float b, float ratio, float absolute) {
|
|||||||
return (diff < epsilon);
|
return (diff < epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Num32__format(float f, int64_t precision) {
|
public CORD Num32$format(float f, int64_t precision) {
|
||||||
return CORD_asprintf("%.*f", (int)precision, f);
|
return CORD_asprintf("%.*f", (int)precision, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Num32__scientific(float f, int64_t precision) {
|
public CORD Num32$scientific(float f, int64_t precision) {
|
||||||
return CORD_asprintf("%.*e", (int)precision, f);
|
return CORD_asprintf("%.*e", (int)precision, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Num32__mod(float num, float modulus) {
|
public float Num32$mod(float num, float modulus) {
|
||||||
float result = fmodf(num, modulus);
|
float result = fmodf(num, modulus);
|
||||||
return (result < 0) != (modulus < 0) ? result + modulus : result;
|
return (result < 0) != (modulus < 0) ? result + modulus : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Num32__random(void) {
|
public float Num32$random(void) {
|
||||||
return (float)drand48();
|
return (float)drand48();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Num32__nan(CORD tag) {
|
public float Num32$nan(CORD tag) {
|
||||||
return nanf(CORD_to_const_char_star(tag));
|
return nanf(CORD_to_const_char_star(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Num32__isinf(float n) { return isinf(n); }
|
public bool Num32$isinf(float n) { return isinf(n); }
|
||||||
public bool Num32__finite(float n) { return finite(n); }
|
public bool Num32$finite(float n) { return finite(n); }
|
||||||
public bool Num32__isnan(float n) { return isnan(n); }
|
public bool Num32$isnan(float n) { return isnan(n); }
|
||||||
|
|
||||||
public const TypeInfo Num32 = {
|
public const TypeInfo $Num32 = {
|
||||||
.size=sizeof(float),
|
.size=sizeof(float),
|
||||||
.align=__alignof__(float),
|
.align=__alignof__(float),
|
||||||
.tag=CustomInfo,
|
.tag=CustomInfo,
|
||||||
.CustomInfo={
|
.CustomInfo={
|
||||||
.compare=(void*)Num32__compare,
|
.compare=(void*)Num32$compare,
|
||||||
.equal=(void*)Num32__equal,
|
.equal=(void*)Num32$equal,
|
||||||
.as_text=(void*)Num32__as_text,
|
.as_text=(void*)Num32$as_text,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,32 +12,32 @@
|
|||||||
#define Num_t double
|
#define Num_t double
|
||||||
#define Num32_t float
|
#define Num32_t float
|
||||||
|
|
||||||
CORD Num__as_text(const double *f, bool colorize, const TypeInfo *type);
|
CORD Num$as_text(const double *f, bool colorize, const TypeInfo *type);
|
||||||
int32_t Num__compare(const double *x, const double *y, const TypeInfo *type);
|
int32_t Num$compare(const double *x, const double *y, const TypeInfo *type);
|
||||||
bool Num__equal(const double *x, const double *y, const TypeInfo *type);
|
bool Num$equal(const double *x, const double *y, const TypeInfo *type);
|
||||||
bool Num__near(double a, double b, double ratio, double absolute);
|
bool Num$near(double a, double b, double ratio, double absolute);
|
||||||
CORD Num__format(double f, int64_t precision);
|
CORD Num$format(double f, int64_t precision);
|
||||||
CORD Num__scientific(double f, int64_t precision);
|
CORD Num$scientific(double f, int64_t precision);
|
||||||
double Num__mod(double num, double modulus);
|
double Num$mod(double num, double modulus);
|
||||||
bool Num__isinf(double n);
|
bool Num$isinf(double n);
|
||||||
bool Num__finite(double n);
|
bool Num$finite(double n);
|
||||||
bool Num__isnan(double n);
|
bool Num$isnan(double n);
|
||||||
double Num__nan(CORD tag);
|
double Num$nan(CORD tag);
|
||||||
double Num__random(void);
|
double Num$random(void);
|
||||||
extern const TypeInfo Num;
|
extern const TypeInfo $Num;
|
||||||
|
|
||||||
CORD Num32__as_text(const float *f, bool colorize, const TypeInfo *type);
|
CORD Num32$as_text(const float *f, bool colorize, const TypeInfo *type);
|
||||||
int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type);
|
int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type);
|
||||||
bool Num32__equal(const float *x, const float *y, const TypeInfo *type);
|
bool Num32$equal(const float *x, const float *y, const TypeInfo *type);
|
||||||
bool Num32__near(float a, float b, float ratio, float absolute);
|
bool Num32$near(float a, float b, float ratio, float absolute);
|
||||||
CORD Num32__format(float f, int64_t precision);
|
CORD Num32$format(float f, int64_t precision);
|
||||||
CORD Num32__scientific(float f, int64_t precision);
|
CORD Num32$scientific(float f, int64_t precision);
|
||||||
float Num32__mod(float num, float modulus);
|
float Num32$mod(float num, float modulus);
|
||||||
bool Num32__isinf(float n);
|
bool Num32$isinf(float n);
|
||||||
bool Num32__finite(float n);
|
bool Num32$finite(float n);
|
||||||
bool Num32__isnan(float n);
|
bool Num32$isnan(float n);
|
||||||
float Num32__random(void);
|
float Num32$random(void);
|
||||||
float Num32__nan(CORD tag);
|
float Num32$nan(CORD tag);
|
||||||
extern const TypeInfo Num32;
|
extern const TypeInfo $Num32;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -18,7 +18,7 @@ typedef struct recursion_s {
|
|||||||
struct recursion_s *next;
|
struct recursion_s *next;
|
||||||
} recursion_t;
|
} recursion_t;
|
||||||
|
|
||||||
public CORD Pointer__as_text(const void *x, bool colorize, const TypeInfo *type) {
|
public CORD Pointer$as_text(const void *x, bool colorize, const TypeInfo *type) {
|
||||||
auto ptr_info = type->PointerInfo;
|
auto ptr_info = type->PointerInfo;
|
||||||
if (!x) {
|
if (!x) {
|
||||||
CORD typename = generic_as_text(NULL, false, ptr_info.pointed);
|
CORD typename = generic_as_text(NULL, false, ptr_info.pointed);
|
||||||
@ -50,19 +50,19 @@ public CORD Pointer__as_text(const void *x, bool colorize, const TypeInfo *type)
|
|||||||
return colorize ? CORD_asprintf("\x1b[34;1m%s\x1b[m%r", ptr_info.sigil, pointed) : CORD_cat(ptr_info.sigil, pointed);
|
return colorize ? CORD_asprintf("\x1b[34;1m%s\x1b[m%r", ptr_info.sigil, pointed) : CORD_cat(ptr_info.sigil, pointed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32_t Pointer__compare(const void *x, const void *y, const TypeInfo *type) {
|
public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Pointer__equal(const void *x, const void *y, const TypeInfo *type) {
|
public bool Pointer$equal(const void *x, const void *y, const TypeInfo *type) {
|
||||||
(void)type;
|
(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint32_t Pointer__hash(const void *x, const TypeInfo *type) {
|
public uint32_t Pointer$hash(const void *x, const TypeInfo *type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
halfsiphash(x, sizeof(void*), SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash));
|
halfsiphash(x, sizeof(void*), SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash));
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
CORD Pointer__as_text(const void *x, bool colorize, const TypeInfo *type);
|
CORD Pointer$as_text(const void *x, bool colorize, const TypeInfo *type);
|
||||||
int32_t Pointer__compare(const void *x, const void *y, const TypeInfo *type);
|
int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type);
|
||||||
bool Pointer__equal(const void *x, const void *y, const TypeInfo *type);
|
bool Pointer$equal(const void *x, const void *y, const TypeInfo *type);
|
||||||
uint32_t Pointer__hash(const void *x, const TypeInfo *type);
|
uint32_t Pointer$hash(const void *x, const TypeInfo *type);
|
||||||
|
|
||||||
#define $Null(t) (t*)NULL
|
#define $Null(t) (t*)NULL
|
||||||
#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo){\
|
#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo){\
|
||||||
|
105
builtins/table.c
105
builtins/table.c
@ -41,13 +41,13 @@
|
|||||||
#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
|
#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
|
||||||
#define ENTRIES_TYPE(type) (&(TypeInfo){.size=sizeof(array_t), .align=__alignof__(array_t), .tag=ArrayInfo, .ArrayInfo.item=(&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo})})
|
#define ENTRIES_TYPE(type) (&(TypeInfo){.size=sizeof(array_t), .align=__alignof__(array_t), .tag=ArrayInfo, .ArrayInfo.item=(&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo})})
|
||||||
|
|
||||||
const TypeInfo MemoryPointer = {
|
static const TypeInfo MemoryPointer = {
|
||||||
.size=sizeof(void*),
|
.size=sizeof(void*),
|
||||||
.align=__alignof__(void*),
|
.align=__alignof__(void*),
|
||||||
.tag=PointerInfo,
|
.tag=PointerInfo,
|
||||||
.PointerInfo={
|
.PointerInfo={
|
||||||
.sigil="@",
|
.sigil="@",
|
||||||
.pointed=&Memory,
|
.pointed=&$Memory,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ const TypeInfo StrToVoidStarTable = {
|
|||||||
.size=sizeof(table_t),
|
.size=sizeof(table_t),
|
||||||
.align=__alignof__(table_t),
|
.align=__alignof__(table_t),
|
||||||
.tag=TableInfo,
|
.tag=TableInfo,
|
||||||
.TableInfo={.key=&Text, .value=&MemoryPointer},
|
.TableInfo={.key=&$Text, .value=&MemoryPointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline size_t entry_size(const TypeInfo *info)
|
static inline size_t entry_size(const TypeInfo *info)
|
||||||
@ -82,7 +82,6 @@ static inline size_t value_offset(const TypeInfo *info)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void hshow(const table_t *t)
|
static inline void hshow(const table_t *t)
|
||||||
{
|
{
|
||||||
hdebug("{");
|
hdebug("{");
|
||||||
@ -99,7 +98,7 @@ static inline void hshow(const table_t *t)
|
|||||||
static void maybe_copy_on_write(table_t *t, const TypeInfo *type)
|
static void maybe_copy_on_write(table_t *t, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (t->entries.data_refcount) {
|
if (t->entries.data_refcount) {
|
||||||
Array__compact(&t->entries, ENTRIES_TYPE(type));
|
Array$compact(&t->entries, ENTRIES_TYPE(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->bucket_info && t->bucket_info->data_refcount) {
|
if (t->bucket_info && t->bucket_info->data_refcount) {
|
||||||
@ -109,14 +108,14 @@ static void maybe_copy_on_write(table_t *t, const TypeInfo *type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Table_mark_copy_on_write(table_t *t)
|
public void Table$mark_copy_on_write(table_t *t)
|
||||||
{
|
{
|
||||||
t->entries.data_refcount = 3;
|
t->entries.data_refcount = 3;
|
||||||
if (t->bucket_info) t->bucket_info->data_refcount = 3;
|
if (t->bucket_info) t->bucket_info->data_refcount = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return address of value or NULL
|
// Return address of value or NULL
|
||||||
public void *Table_get_raw(table_t t, const void *key, const TypeInfo *type)
|
public void *Table$get_raw(table_t t, const void *key, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
if (!key || !t.bucket_info) return NULL;
|
if (!key || !t.bucket_info) return NULL;
|
||||||
@ -138,11 +137,11 @@ public void *Table_get_raw(table_t t, const void *key, const TypeInfo *type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void *Table_get(table_t t, const void *key, const TypeInfo *type)
|
public void *Table$get(table_t t, const void *key, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
for (const table_t *iter = &t; iter; iter = iter->fallback) {
|
for (const table_t *iter = &t; iter; iter = iter->fallback) {
|
||||||
void *ret = Table_get_raw(*iter, key, type);
|
void *ret = Table$get_raw(*iter, key, type);
|
||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
}
|
}
|
||||||
for (const table_t *iter = &t; iter; iter = iter->fallback) {
|
for (const table_t *iter = &t; iter; iter = iter->fallback) {
|
||||||
@ -151,7 +150,7 @@ public void *Table_get(table_t t, const void *key, const TypeInfo *type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Table_set_bucket(table_t *t, const void *entry, int32_t index, const TypeInfo *type)
|
static void Table$set_bucket(table_t *t, const void *entry, int32_t index, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(t->bucket_info);
|
assert(t->bucket_info);
|
||||||
hshow(t);
|
hshow(t);
|
||||||
@ -215,9 +214,9 @@ static void hashmap_resize_buckets(table_t *t, uint32_t new_capacity, const Type
|
|||||||
t->bucket_info->count = new_capacity;
|
t->bucket_info->count = new_capacity;
|
||||||
t->bucket_info->last_free = new_capacity-1;
|
t->bucket_info->last_free = new_capacity-1;
|
||||||
// Rehash:
|
// Rehash:
|
||||||
for (int64_t i = 0; i < Table_length(*t); i++) {
|
for (int64_t i = 0; i < Table$length(*t); i++) {
|
||||||
hdebug("Rehashing %u\n", i);
|
hdebug("Rehashing %u\n", i);
|
||||||
Table_set_bucket(t, GET_ENTRY(*t, i), i, type);
|
Table$set_bucket(t, GET_ENTRY(*t, i), i, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
hshow(t);
|
hshow(t);
|
||||||
@ -225,7 +224,7 @@ static void hashmap_resize_buckets(table_t *t, uint32_t new_capacity, const Type
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return address of value
|
// Return address of value
|
||||||
public void *Table_reserve(table_t *t, const void *key, const void *value, const TypeInfo *type)
|
public void *Table$reserve(table_t *t, const void *key, const void *value, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
if (!t || !key) return NULL;
|
if (!t || !key) return NULL;
|
||||||
@ -237,7 +236,7 @@ public void *Table_reserve(table_t *t, const void *key, const void *value, const
|
|||||||
hashmap_resize_buckets(t, 4, type);
|
hashmap_resize_buckets(t, 4, type);
|
||||||
} else {
|
} else {
|
||||||
// Check if we are clobbering a value:
|
// Check if we are clobbering a value:
|
||||||
void *value_home = Table_get_raw(*t, key, type);
|
void *value_home = Table$get_raw(*t, key, type);
|
||||||
if (value_home) { // Update existing slot
|
if (value_home) { // Update existing slot
|
||||||
// Ensure that `value_home` is still inside t->entries, even if COW occurs
|
// Ensure that `value_home` is still inside t->entries, even if COW occurs
|
||||||
ptrdiff_t offset = value_home - t->entries.data;
|
ptrdiff_t offset = value_home - t->entries.data;
|
||||||
@ -260,7 +259,7 @@ public void *Table_reserve(table_t *t, const void *key, const void *value, const
|
|||||||
|
|
||||||
if (!value && value_size > 0) {
|
if (!value && value_size > 0) {
|
||||||
for (table_t *iter = t->fallback; iter; iter = iter->fallback) {
|
for (table_t *iter = t->fallback; iter; iter = iter->fallback) {
|
||||||
value = Table_get_raw(*iter, key, type);
|
value = Table$get_raw(*iter, key, type);
|
||||||
if (value) break;
|
if (value) break;
|
||||||
}
|
}
|
||||||
for (table_t *iter = t; !value && iter; iter = iter->fallback) {
|
for (table_t *iter = t; !value && iter; iter = iter->fallback) {
|
||||||
@ -277,24 +276,24 @@ public void *Table_reserve(table_t *t, const void *key, const void *value, const
|
|||||||
memcpy(buf + value_offset(type), value, value_size);
|
memcpy(buf + value_offset(type), value, value_size);
|
||||||
else
|
else
|
||||||
memset(buf + value_offset(type), 0, value_size);
|
memset(buf + value_offset(type), 0, value_size);
|
||||||
Array__insert(&t->entries, buf, 0, ENTRIES_TYPE(type));
|
Array$insert(&t->entries, buf, 0, ENTRIES_TYPE(type));
|
||||||
|
|
||||||
int64_t entry_index = t->entries.length-1;
|
int64_t entry_index = t->entries.length-1;
|
||||||
void *entry = GET_ENTRY(*t, entry_index);
|
void *entry = GET_ENTRY(*t, entry_index);
|
||||||
Table_set_bucket(t, entry, entry_index, type);
|
Table$set_bucket(t, entry, entry_index, type);
|
||||||
return entry + value_offset(type);
|
return entry + value_offset(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Table_set(table_t *t, const void *key, const void *value, const TypeInfo *type)
|
public void Table$set(table_t *t, const void *key, const void *value, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
(void)Table_reserve(t, key, value, type);
|
(void)Table$reserve(t, key, value, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Table_remove(table_t *t, const void *key, const TypeInfo *type)
|
public void Table$remove(table_t *t, const void *key, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
if (!t || Table_length(*t) == 0) return;
|
if (!t || Table$length(*t) == 0) return;
|
||||||
|
|
||||||
// TODO: this work doesn't need to be done if the key is already missing
|
// TODO: this work doesn't need to be done if the key is already missing
|
||||||
maybe_copy_on_write(t, type);
|
maybe_copy_on_write(t, type);
|
||||||
@ -363,7 +362,7 @@ public void Table_remove(table_t *t, const void *key, const TypeInfo *type)
|
|||||||
// Last entry is being removed, so clear it out to be safe:
|
// Last entry is being removed, so clear it out to be safe:
|
||||||
memset(GET_ENTRY(*t, last_entry), 0, entry_size(type));
|
memset(GET_ENTRY(*t, last_entry), 0, entry_size(type));
|
||||||
|
|
||||||
Array__remove(&t->entries, t->entries.length, 1, ENTRIES_TYPE(type));
|
Array$remove(&t->entries, t->entries.length, 1, ENTRIES_TYPE(type));
|
||||||
|
|
||||||
int64_t bucket_to_clear;
|
int64_t bucket_to_clear;
|
||||||
if (prev) { // Middle (or end) of a chain
|
if (prev) { // Middle (or end) of a chain
|
||||||
@ -386,22 +385,22 @@ public void Table_remove(table_t *t, const void *key, const TypeInfo *type)
|
|||||||
hshow(t);
|
hshow(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void *Table_entry(table_t t, int64_t n)
|
public void *Table$entry(table_t t, int64_t n)
|
||||||
{
|
{
|
||||||
if (n < 1 || n > Table_length(t))
|
if (n < 1 || n > Table$length(t))
|
||||||
return NULL;
|
return NULL;
|
||||||
return GET_ENTRY(t, n-1);
|
return GET_ENTRY(t, n-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Table_clear(table_t *t)
|
public void Table$clear(table_t *t)
|
||||||
{
|
{
|
||||||
memset(t, 0, sizeof(table_t));
|
memset(t, 0, sizeof(table_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Table_equal(const table_t *x, const table_t *y, const TypeInfo *type)
|
public bool Table$equal(const table_t *x, const table_t *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
if (Table_length(*x) != Table_length(*y))
|
if (Table$length(*x) != Table$length(*y))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((x->default_value != NULL) != (y->default_value != NULL))
|
if ((x->default_value != NULL) != (y->default_value != NULL))
|
||||||
@ -411,10 +410,10 @@ public bool Table_equal(const table_t *x, const table_t *y, const TypeInfo *type
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const TypeInfo *value_type = type->TableInfo.value;
|
const TypeInfo *value_type = type->TableInfo.value;
|
||||||
for (int64_t i = 0, length = Table_length(*x); i < length; i++) {
|
for (int64_t i = 0, length = Table$length(*x); i < length; i++) {
|
||||||
void *x_key = GET_ENTRY(*x, i);
|
void *x_key = GET_ENTRY(*x, i);
|
||||||
void *x_value = x_key + value_offset(type);
|
void *x_value = x_key + value_offset(type);
|
||||||
void *y_value = Table_get_raw(*y, x_key, type);
|
void *y_value = Table$get_raw(*y, x_key, type);
|
||||||
if (!y_value)
|
if (!y_value)
|
||||||
return false;
|
return false;
|
||||||
if (!generic_equal(x_value, y_value, value_type))
|
if (!generic_equal(x_value, y_value, value_type))
|
||||||
@ -426,13 +425,13 @@ public bool Table_equal(const table_t *x, const table_t *y, const TypeInfo *type
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (x->fallback && y->fallback
|
if (x->fallback && y->fallback
|
||||||
&& !Table_equal(x->fallback, y->fallback, type))
|
&& !Table$equal(x->fallback, y->fallback, type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo *type)
|
public int32_t Table$compare(const table_t *x, const table_t *y, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
auto table = type->TableInfo;
|
auto table = type->TableInfo;
|
||||||
@ -442,8 +441,8 @@ public int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo
|
|||||||
return (x->entries.length > y->entries.length) - (x->entries.length < y->entries.length);
|
return (x->entries.length > y->entries.length) - (x->entries.length < y->entries.length);
|
||||||
|
|
||||||
array_t x_entries = x->entries, y_entries = y->entries;
|
array_t x_entries = x->entries, y_entries = y->entries;
|
||||||
Array__sort(&x_entries, table.key);
|
Array$sort(&x_entries, table.key);
|
||||||
Array__sort(&y_entries, table.key);
|
Array$sort(&y_entries, table.key);
|
||||||
for (int64_t i = 0; i < x_entries.length; i++) {
|
for (int64_t i = 0; i < x_entries.length; i++) {
|
||||||
void *x_key = x_entries.data + x_entries.stride * i;
|
void *x_key = x_entries.data + x_entries.stride * i;
|
||||||
void *y_key = y_entries.data + y_entries.stride * i;
|
void *y_key = y_entries.data + y_entries.stride * i;
|
||||||
@ -471,7 +470,7 @@ public int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint32_t Table_hash(const table_t *t, const TypeInfo *type)
|
public uint32_t Table$hash(const table_t *t, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
// Table hashes are computed as:
|
// Table hashes are computed as:
|
||||||
@ -481,20 +480,20 @@ public uint32_t Table_hash(const table_t *t, const TypeInfo *type)
|
|||||||
int64_t val_off = value_offset(type);
|
int64_t val_off = value_offset(type);
|
||||||
|
|
||||||
uint32_t key_hashes = 0, value_hashes = 0, fallback_hash = 0, default_hash = 0;
|
uint32_t key_hashes = 0, value_hashes = 0, fallback_hash = 0, default_hash = 0;
|
||||||
for (int64_t i = 0, length = Table_length(*t); i < length; i++) {
|
for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
|
||||||
void *entry = GET_ENTRY(*t, i);
|
void *entry = GET_ENTRY(*t, i);
|
||||||
key_hashes ^= generic_hash(entry, table.key);
|
key_hashes ^= generic_hash(entry, table.key);
|
||||||
value_hashes ^= generic_hash(entry + val_off, table.value);
|
value_hashes ^= generic_hash(entry + val_off, table.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->fallback)
|
if (t->fallback)
|
||||||
fallback_hash = Table_hash(t->fallback, type);
|
fallback_hash = Table$hash(t->fallback, type);
|
||||||
|
|
||||||
if (t->default_value)
|
if (t->default_value)
|
||||||
default_hash = generic_hash(t->default_value, table.value);
|
default_hash = generic_hash(t->default_value, table.value);
|
||||||
|
|
||||||
struct { int64_t len; uint32_t k, v, f, d; } components = {
|
struct { int64_t len; uint32_t k, v, f, d; } components = {
|
||||||
Table_length(*t),
|
Table$length(*t),
|
||||||
key_hashes,
|
key_hashes,
|
||||||
value_hashes,
|
value_hashes,
|
||||||
fallback_hash,
|
fallback_hash,
|
||||||
@ -505,7 +504,7 @@ public uint32_t Table_hash(const table_t *t, const TypeInfo *type)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Table_as_text(const table_t *t, bool colorize, const TypeInfo *type)
|
public CORD Table$as_text(const table_t *t, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
auto table = type->TableInfo;
|
auto table = type->TableInfo;
|
||||||
@ -515,7 +514,7 @@ public CORD Table_as_text(const table_t *t, bool colorize, const TypeInfo *type)
|
|||||||
|
|
||||||
int64_t val_off = value_offset(type);
|
int64_t val_off = value_offset(type);
|
||||||
CORD c = "{";
|
CORD c = "{";
|
||||||
for (int64_t i = 0, length = Table_length(*t); i < length; i++) {
|
for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
c = CORD_cat(c, ", ");
|
c = CORD_cat(c, ", ");
|
||||||
void *entry = GET_ENTRY(*t, i);
|
void *entry = GET_ENTRY(*t, i);
|
||||||
@ -526,7 +525,7 @@ public CORD Table_as_text(const table_t *t, bool colorize, const TypeInfo *type)
|
|||||||
|
|
||||||
if (t->fallback) {
|
if (t->fallback) {
|
||||||
c = CORD_cat(c, "; fallback=");
|
c = CORD_cat(c, "; fallback=");
|
||||||
c = CORD_cat(c, Table_as_text(t->fallback, colorize, type));
|
c = CORD_cat(c, Table$as_text(t->fallback, colorize, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->default_value) {
|
if (t->default_value) {
|
||||||
@ -538,7 +537,7 @@ public CORD Table_as_text(const table_t *t, bool colorize, const TypeInfo *type)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public table_t Table_from_entries(array_t entries, const TypeInfo *type)
|
public table_t Table$from_entries(array_t entries, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
assert(type->tag == TableInfo);
|
assert(type->tag == TableInfo);
|
||||||
table_t t = {.entries=entries};
|
table_t t = {.entries=entries};
|
||||||
@ -546,36 +545,36 @@ public table_t Table_from_entries(array_t entries, const TypeInfo *type)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Table_str_get(table_t t, const char *key)
|
public void *Table$str_get(table_t t, const char *key)
|
||||||
{
|
{
|
||||||
void **ret = Table_get(t, &key, &StrToVoidStarTable);
|
void **ret = Table$get(t, &key, &StrToVoidStarTable);
|
||||||
return ret ? *ret : NULL;
|
return ret ? *ret : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Table_str_get_raw(table_t t, const char *key)
|
public void *Table$str_get_raw(table_t t, const char *key)
|
||||||
{
|
{
|
||||||
void **ret = Table_get_raw(t, &key, &StrToVoidStarTable);
|
void **ret = Table$get_raw(t, &key, &StrToVoidStarTable);
|
||||||
return ret ? *ret : NULL;
|
return ret ? *ret : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Table_str_reserve(table_t *t, const char *key, const void *value)
|
public void *Table$str_reserve(table_t *t, const char *key, const void *value)
|
||||||
{
|
{
|
||||||
return Table_reserve(t, &key, &value, &StrToVoidStarTable);
|
return Table$reserve(t, &key, &value, &StrToVoidStarTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table_str_set(table_t *t, const char *key, const void *value)
|
public void Table$str_set(table_t *t, const char *key, const void *value)
|
||||||
{
|
{
|
||||||
Table_set(t, &key, &value, &StrToVoidStarTable);
|
Table$set(t, &key, &value, &StrToVoidStarTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table_str_remove(table_t *t, const char *key)
|
public void Table$str_remove(table_t *t, const char *key)
|
||||||
{
|
{
|
||||||
return Table_remove(t, &key, &StrToVoidStarTable);
|
return Table$remove(t, &key, &StrToVoidStarTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Table_str_entry(table_t t, int64_t n)
|
public void *Table$str_entry(table_t t, int64_t n)
|
||||||
{
|
{
|
||||||
return Table_entry(t, n);
|
return Table$entry(t, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#define $Table(key_t, val_t, key_info, value_info, fb, def, N, ...) ({ \
|
#define $Table(key_t, val_t, key_info, value_info, fb, def, N, ...) ({ \
|
||||||
struct { key_t k; val_t v; } $ents[N] = {__VA_ARGS__}; \
|
struct { key_t k; val_t v; } $ents[N] = {__VA_ARGS__}; \
|
||||||
table_t $table = Table_from_entries((array_t){ \
|
table_t $table = Table$from_entries((array_t){ \
|
||||||
.data=memcpy(GC_MALLOC(sizeof($ents)), $ents, sizeof($ents)), \
|
.data=memcpy(GC_MALLOC(sizeof($ents)), $ents, sizeof($ents)), \
|
||||||
.length=sizeof($ents)/sizeof($ents[0]), \
|
.length=sizeof($ents)/sizeof($ents[0]), \
|
||||||
.stride=(void*)&$ents[1] - (void*)&$ents[0], \
|
.stride=(void*)&$ents[1] - (void*)&$ents[0], \
|
||||||
@ -22,36 +22,36 @@
|
|||||||
$table; })
|
$table; })
|
||||||
#define $Table_get(table_expr, key_t, val_t, key_expr, info_expr, filename, start, end) ({ \
|
#define $Table_get(table_expr, key_t, val_t, key_expr, info_expr, filename, start, end) ({ \
|
||||||
const table_t $t = table_expr; key_t $k = key_expr; const TypeInfo* $info = info_expr; \
|
const table_t $t = table_expr; key_t $k = key_expr; const TypeInfo* $info = info_expr; \
|
||||||
const val_t *$v = Table_get($t, &$k, $info); \
|
const val_t *$v = Table$get($t, &$k, $info); \
|
||||||
if (__builtin_expect($v == NULL, 0)) \
|
if (__builtin_expect($v == NULL, 0)) \
|
||||||
fail_source(filename, start, end, "The key %r is not in this table\n", generic_as_text(&$k, USE_COLOR, $info->TableInfo.key)); \
|
fail_source(filename, start, end, "The key %r is not in this table\n", generic_as_text(&$k, USE_COLOR, $info->TableInfo.key)); \
|
||||||
*$v; })
|
*$v; })
|
||||||
|
|
||||||
table_t Table_from_entries(array_t entries, const TypeInfo *type);
|
table_t Table$from_entries(array_t entries, const TypeInfo *type);
|
||||||
void *Table_get(table_t t, const void *key, const TypeInfo *type);
|
void *Table$get(table_t t, const void *key, const TypeInfo *type);
|
||||||
void *Table_get_raw(table_t t, const void *key, const TypeInfo *type);
|
void *Table$get_raw(table_t t, const void *key, const TypeInfo *type);
|
||||||
void *Table_entry(table_t t, int64_t n);
|
void *Table$entry(table_t t, int64_t n);
|
||||||
void *Table_reserve(table_t *t, const void *key, const void *value, const TypeInfo *type);
|
void *Table$reserve(table_t *t, const void *key, const void *value, const TypeInfo *type);
|
||||||
void Table_set(table_t *t, const void *key, const void *value, const TypeInfo *type);
|
void Table$set(table_t *t, const void *key, const void *value, const TypeInfo *type);
|
||||||
#define Table_set_value(t, key_expr, value_expr, type) ({ __typeof(key_expr) $k = key_expr; __typeof(value_expr) $v = value_expr; \
|
#define Table$set_value(t, key_expr, value_expr, type) ({ __typeof(key_expr) $k = key_expr; __typeof(value_expr) $v = value_expr; \
|
||||||
Table_set(t, &$k, &$v, type); })
|
Table$set(t, &$k, &$v, type); })
|
||||||
#define Table_reserve_value(t, key_expr, type) ({ __typeof(key_expr) $k = key_expr; Table_reserve(t, &$k, NULL, type); })
|
#define Table$reserve_value(t, key_expr, type) ({ __typeof(key_expr) $k = key_expr; Table$reserve(t, &$k, NULL, type); })
|
||||||
void Table_remove(table_t *t, const void *key, const TypeInfo *type);
|
void Table$remove(table_t *t, const void *key, const TypeInfo *type);
|
||||||
void Table_clear(table_t *t);
|
void Table$clear(table_t *t);
|
||||||
void Table_mark_copy_on_write(table_t *t);
|
void Table$mark_copy_on_write(table_t *t);
|
||||||
int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo *type);
|
int32_t Table$compare(const table_t *x, const table_t *y, const TypeInfo *type);
|
||||||
bool Table_equal(const table_t *x, const table_t *y, const TypeInfo *type);
|
bool Table$equal(const table_t *x, const table_t *y, const TypeInfo *type);
|
||||||
uint32_t Table_hash(const table_t *t, const TypeInfo *type);
|
uint32_t Table$hash(const table_t *t, const TypeInfo *type);
|
||||||
CORD Table_as_text(const table_t *t, bool colorize, const TypeInfo *type);
|
CORD Table$as_text(const table_t *t, bool colorize, const TypeInfo *type);
|
||||||
|
|
||||||
void *Table_str_entry(table_t t, int64_t n);
|
void *Table$str_entry(table_t t, int64_t n);
|
||||||
void *Table_str_get(table_t t, const char *key);
|
void *Table$str_get(table_t t, const char *key);
|
||||||
void *Table_str_get_raw(table_t t, const char *key);
|
void *Table$str_get_raw(table_t t, const char *key);
|
||||||
void Table_str_set(table_t *t, const char *key, const void *value);
|
void Table$str_set(table_t *t, const char *key, const void *value);
|
||||||
void *Table_str_reserve(table_t *t, const char *key, const void *value);
|
void *Table$str_reserve(table_t *t, const char *key, const void *value);
|
||||||
void Table_str_remove(table_t *t, const char *key);
|
void Table$str_remove(table_t *t, const char *key);
|
||||||
|
|
||||||
#define Table_length(t) ((t).entries.length)
|
#define Table$length(t) ((t).entries.length)
|
||||||
|
|
||||||
extern const TypeInfo StrToVoidStarTable;
|
extern const TypeInfo StrToVoidStarTable;
|
||||||
|
|
||||||
|
@ -24,16 +24,16 @@
|
|||||||
|
|
||||||
#define CLAMP(x, lo, hi) MIN(hi, MAX(x,lo))
|
#define CLAMP(x, lo, hi) MIN(hi, MAX(x,lo))
|
||||||
|
|
||||||
public CORD Text__as_text(const void *text, bool colorize, const TypeInfo *info)
|
public CORD Text$as_text(const void *text, bool colorize, const TypeInfo *info)
|
||||||
{
|
{
|
||||||
if (!text) return info->TextInfo.lang;
|
if (!text) return info->TextInfo.lang;
|
||||||
CORD ret = Text__quoted(*(CORD*)text, colorize);
|
CORD ret = Text$quoted(*(CORD*)text, colorize);
|
||||||
if (!streq(info->TextInfo.lang, "Text"))
|
if (!streq(info->TextInfo.lang, "Text"))
|
||||||
ret = colorize ? CORD_all("\x1b[1m$", info->TextInfo.lang, "\x1b[m", ret) : CORD_all("$", info->TextInfo.lang, ret);
|
ret = colorize ? CORD_all("\x1b[1m$", info->TextInfo.lang, "\x1b[m", ret) : CORD_all("$", info->TextInfo.lang, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__quoted(CORD str, bool colorize)
|
public CORD Text$quoted(CORD str, bool colorize)
|
||||||
{
|
{
|
||||||
// Note: it's important to have unicode strings not get broken up with
|
// Note: it's important to have unicode strings not get broken up with
|
||||||
// escapes, otherwise they won't print right.
|
// escapes, otherwise they won't print right.
|
||||||
@ -92,7 +92,7 @@ public CORD Text__quoted(CORD str, bool colorize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Text__compare(const CORD *x, const CORD *y)
|
public int Text$compare(const CORD *x, const CORD *y)
|
||||||
{
|
{
|
||||||
uint8_t *xx = (uint8_t*)CORD_to_const_char_star(*x);
|
uint8_t *xx = (uint8_t*)CORD_to_const_char_star(*x);
|
||||||
uint8_t *yy = (uint8_t*)CORD_to_const_char_star(*y);
|
uint8_t *yy = (uint8_t*)CORD_to_const_char_star(*y);
|
||||||
@ -102,12 +102,12 @@ public int Text__compare(const CORD *x, const CORD *y)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Text__equal(const CORD *x, const CORD *y)
|
public bool Text$equal(const CORD *x, const CORD *y)
|
||||||
{
|
{
|
||||||
return Text__compare(x, y) == 0;
|
return Text$compare(x, y) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint32_t Text__hash(const CORD *cord)
|
public uint32_t Text$hash(const CORD *cord)
|
||||||
{
|
{
|
||||||
if (!*cord) return 0;
|
if (!*cord) return 0;
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ public uint32_t Text__hash(const CORD *cord)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__upper(CORD str)
|
public CORD Text$upper(CORD str)
|
||||||
{
|
{
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
size_t len = strlen(str) + 1;
|
size_t len = strlen(str) + 1;
|
||||||
@ -133,7 +133,7 @@ public CORD Text__upper(CORD str)
|
|||||||
return (CORD)u8_toupper((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
return (CORD)u8_toupper((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__lower(CORD str)
|
public CORD Text$lower(CORD str)
|
||||||
{
|
{
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
size_t len = strlen(str) + 1;
|
size_t len = strlen(str) + 1;
|
||||||
@ -142,7 +142,7 @@ public CORD Text__lower(CORD str)
|
|||||||
return (CORD)u8_tolower((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
return (CORD)u8_tolower((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__title(CORD str)
|
public CORD Text$title(CORD str)
|
||||||
{
|
{
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
size_t len = strlen(str) + 1;
|
size_t len = strlen(str) + 1;
|
||||||
@ -151,7 +151,7 @@ public CORD Text__title(CORD str)
|
|||||||
return (CORD)u8_totitle((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
return (CORD)u8_totitle((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Text__has(CORD str, CORD target, where_e where)
|
public bool Text$has(CORD str, CORD target, where_e where)
|
||||||
{
|
{
|
||||||
if (!target) return true;
|
if (!target) return true;
|
||||||
if (!str) return false;
|
if (!str) return false;
|
||||||
@ -168,7 +168,7 @@ public bool Text__has(CORD str, CORD target, where_e where)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__without(CORD str, CORD target, where_e where)
|
public CORD Text$without(CORD str, CORD target, where_e where)
|
||||||
{
|
{
|
||||||
if (!str || !target) return str;
|
if (!str || !target) return str;
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ public CORD Text__without(CORD str, CORD target, where_e where)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__trimmed(CORD str, CORD skip, where_e where)
|
public CORD Text$trimmed(CORD str, CORD skip, where_e where)
|
||||||
{
|
{
|
||||||
if (!str || !skip) return str;
|
if (!str || !skip) return str;
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(str);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(str);
|
||||||
@ -213,14 +213,14 @@ public CORD Text__trimmed(CORD str, CORD skip, where_e where)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public find_result_t Text__find(CORD str, CORD pat)
|
public find_result_t Text$find(CORD str, CORD pat)
|
||||||
{
|
{
|
||||||
if (!pat) return (find_result_t){.status=FIND_SUCCESS, .index=1};
|
if (!pat) return (find_result_t){.status=FIND_SUCCESS, .index=1};
|
||||||
size_t pos = CORD_str(str, 0, pat);
|
size_t pos = CORD_str(str, 0, pat);
|
||||||
return (pos == CORD_NOT_FOUND) ? (find_result_t){.status=FIND_FAILURE} : (find_result_t){.status=FIND_SUCCESS, .index=(int32_t)pos};
|
return (pos == CORD_NOT_FOUND) ? (find_result_t){.status=FIND_FAILURE} : (find_result_t){.status=FIND_SUCCESS, .index=(int32_t)pos};
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__replace(CORD text, CORD pat, CORD replacement, int64_t limit)
|
public CORD Text$replace(CORD text, CORD pat, CORD replacement, int64_t limit)
|
||||||
{
|
{
|
||||||
if (!text || !pat) return text;
|
if (!text || !pat) return text;
|
||||||
CORD ret = CORD_EMPTY;
|
CORD ret = CORD_EMPTY;
|
||||||
@ -233,7 +233,7 @@ public CORD Text__replace(CORD text, CORD pat, CORD replacement, int64_t limit)
|
|||||||
return CORD_cat(ret, CORD_substr(text, pos, str_len - pos));
|
return CORD_cat(ret, CORD_substr(text, pos, str_len - pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Text__split(CORD str, CORD split)
|
public array_t Text$split(CORD str, CORD split)
|
||||||
{
|
{
|
||||||
if (!str) return (array_t){.data=GC_MALLOC(sizeof(CORD)), .atomic=1, .length=1, .stride=sizeof(CORD)};
|
if (!str) return (array_t){.data=GC_MALLOC(sizeof(CORD)), .atomic=1, .length=1, .stride=sizeof(CORD)};
|
||||||
array_t strings = {.stride=sizeof(CORD), .atomic=1};
|
array_t strings = {.stride=sizeof(CORD), .atomic=1};
|
||||||
@ -257,7 +257,7 @@ public array_t Text__split(CORD str, CORD split)
|
|||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CORD Text__join(CORD glue, array_t pieces)
|
public CORD Text$join(CORD glue, array_t pieces)
|
||||||
{
|
{
|
||||||
if (pieces.length == 0) return CORD_EMPTY;
|
if (pieces.length == 0) return CORD_EMPTY;
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ public CORD Text__join(CORD glue, array_t pieces)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Text__clusters(CORD text)
|
public array_t Text$clusters(CORD text)
|
||||||
{
|
{
|
||||||
array_t clusters = {.atomic=1};
|
array_t clusters = {.atomic=1};
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
@ -285,7 +285,7 @@ public array_t Text__clusters(CORD text)
|
|||||||
char cluster_buf[len+1];
|
char cluster_buf[len+1];
|
||||||
strlcpy(cluster_buf, (char*)pos, len+1);
|
strlcpy(cluster_buf, (char*)pos, len+1);
|
||||||
CORD cluster = CORD_from_char_star(cluster_buf);
|
CORD cluster = CORD_from_char_star(cluster_buf);
|
||||||
Array__insert(&clusters, &cluster, 0, $ArrayInfo(&Text));
|
Array$insert(&clusters, &cluster, 0, $ArrayInfo(&$Text));
|
||||||
pos = next;
|
pos = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ public array_t Text__clusters(CORD text)
|
|||||||
return clusters;
|
return clusters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Text__codepoints(CORD text)
|
public array_t Text$codepoints(CORD text)
|
||||||
{
|
{
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
uint8_t norm_buf[128] = {0};
|
uint8_t norm_buf[128] = {0};
|
||||||
@ -316,7 +316,7 @@ public array_t Text__codepoints(CORD text)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Text__bytes(CORD text)
|
public array_t Text$bytes(CORD text)
|
||||||
{
|
{
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
uint8_t norm_buf[128] = {0};
|
uint8_t norm_buf[128] = {0};
|
||||||
@ -336,7 +336,7 @@ public array_t Text__bytes(CORD text)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64_t Text__num_clusters(CORD text)
|
public int64_t Text$num_clusters(CORD text)
|
||||||
{
|
{
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
int64_t num_clusters = 0;
|
int64_t num_clusters = 0;
|
||||||
@ -349,7 +349,7 @@ public int64_t Text__num_clusters(CORD text)
|
|||||||
return num_clusters;
|
return num_clusters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64_t Text__num_codepoints(CORD text)
|
public int64_t Text$num_codepoints(CORD text)
|
||||||
{
|
{
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
uint8_t buf[128] = {0};
|
uint8_t buf[128] = {0};
|
||||||
@ -361,7 +361,7 @@ public int64_t Text__num_codepoints(CORD text)
|
|||||||
return num_codepoints;
|
return num_codepoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64_t Text__num_bytes(CORD text)
|
public int64_t Text$num_bytes(CORD text)
|
||||||
{
|
{
|
||||||
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
const uint8_t *ustr = (const uint8_t*)CORD_to_const_char_star(text);
|
||||||
uint8_t norm_buf[128] = {0};
|
uint8_t norm_buf[128] = {0};
|
||||||
@ -373,9 +373,9 @@ public int64_t Text__num_bytes(CORD text)
|
|||||||
return norm_len;
|
return norm_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
public array_t Text__character_names(CORD text)
|
public array_t Text$character_names(CORD text)
|
||||||
{
|
{
|
||||||
array_t codepoints = Text__codepoints(text);
|
array_t codepoints = Text$codepoints(text);
|
||||||
array_t ret = {.length=codepoints.length, .stride=sizeof(CORD), .data=GC_MALLOC(sizeof(CORD)*codepoints.length)};
|
array_t ret = {.length=codepoints.length, .stride=sizeof(CORD), .data=GC_MALLOC(sizeof(CORD)*codepoints.length)};
|
||||||
for (int64_t i = 0; i < codepoints.length; i++) {
|
for (int64_t i = 0; i < codepoints.length; i++) {
|
||||||
char buf[UNINAME_MAX];
|
char buf[UNINAME_MAX];
|
||||||
@ -385,7 +385,7 @@ public array_t Text__character_names(CORD text)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo Text = {
|
public const TypeInfo $Text = {
|
||||||
.size=sizeof(CORD),
|
.size=sizeof(CORD),
|
||||||
.align=__alignof__(CORD),
|
.align=__alignof__(CORD),
|
||||||
.tag=TextInfo,
|
.tag=TextInfo,
|
||||||
|
@ -18,29 +18,29 @@ typedef struct {
|
|||||||
int32_t index;
|
int32_t index;
|
||||||
} find_result_t;
|
} find_result_t;
|
||||||
|
|
||||||
CORD Text__as_text(const void *str, bool colorize, const TypeInfo *info);
|
CORD Text$as_text(const void *str, bool colorize, const TypeInfo *info);
|
||||||
CORD Text__quoted(CORD str, bool colorize);
|
CORD Text$quoted(CORD str, bool colorize);
|
||||||
int Text__compare(const CORD *x, const CORD *y);
|
int Text$compare(const CORD *x, const CORD *y);
|
||||||
bool Text__equal(const CORD *x, const CORD *y);
|
bool Text$equal(const CORD *x, const CORD *y);
|
||||||
uint32_t Text__hash(const CORD *cord);
|
uint32_t Text$hash(const CORD *cord);
|
||||||
CORD Text__upper(CORD str);
|
CORD Text$upper(CORD str);
|
||||||
CORD Text__lower(CORD str);
|
CORD Text$lower(CORD str);
|
||||||
CORD Text__title(CORD str);
|
CORD Text$title(CORD str);
|
||||||
bool Text__has(CORD str, CORD target, where_e where);
|
bool Text$has(CORD str, CORD target, where_e where);
|
||||||
CORD Text__without(CORD str, CORD target, where_e where);
|
CORD Text$without(CORD str, CORD target, where_e where);
|
||||||
CORD Text__trimmed(CORD str, CORD skip, where_e where);
|
CORD Text$trimmed(CORD str, CORD skip, where_e where);
|
||||||
find_result_t Text__find(CORD str, CORD pat);
|
find_result_t Text$find(CORD str, CORD pat);
|
||||||
CORD Text__replace(CORD text, CORD pat, CORD replacement, int64_t limit);
|
CORD Text$replace(CORD text, CORD pat, CORD replacement, int64_t limit);
|
||||||
array_t Text__split(CORD str, CORD split);
|
array_t Text$split(CORD str, CORD split);
|
||||||
CORD Text__join(CORD glue, array_t pieces);
|
CORD Text$join(CORD glue, array_t pieces);
|
||||||
array_t Text__clusters(CORD text);
|
array_t Text$clusters(CORD text);
|
||||||
array_t Text__codepoints(CORD text);
|
array_t Text$codepoints(CORD text);
|
||||||
array_t Text__bytes(CORD text);
|
array_t Text$bytes(CORD text);
|
||||||
int64_t Text__num_clusters(CORD text);
|
int64_t Text$num_clusters(CORD text);
|
||||||
int64_t Text__num_codepoints(CORD text);
|
int64_t Text$num_codepoints(CORD text);
|
||||||
int64_t Text__num_bytes(CORD text);
|
int64_t Text$num_bytes(CORD text);
|
||||||
array_t Text__character_names(CORD text);
|
array_t Text$character_names(CORD text);
|
||||||
|
|
||||||
extern const TypeInfo Text;
|
extern const TypeInfo $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 @@
|
|||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
public CORD Type__as_text(const void *typeinfo, bool colorize, const TypeInfo *type)
|
public CORD Type$as_text(const void *typeinfo, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
if (!typeinfo) return "TypeInfo";
|
if (!typeinfo) return "TypeInfo";
|
||||||
|
|
||||||
@ -22,17 +22,17 @@ public CORD Type__as_text(const void *typeinfo, bool colorize, const TypeInfo *t
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const TypeInfo TypeInfo_info = {
|
public const TypeInfo $TypeInfo = {
|
||||||
.size=sizeof(TypeInfo),
|
.size=sizeof(TypeInfo),
|
||||||
.align=__alignof__(TypeInfo),
|
.align=__alignof__(TypeInfo),
|
||||||
.tag=CustomInfo,
|
.tag=CustomInfo,
|
||||||
.TypeInfoInfo.type_str="TypeInfo",
|
.TypeInfoInfo.type_str="TypeInfo",
|
||||||
};
|
};
|
||||||
|
|
||||||
public const TypeInfo Void = {.size=0, .align=0};
|
public const TypeInfo $Void = {.size=0, .align=0};
|
||||||
public const TypeInfo Abort = {.size=0, .align=0};
|
public const TypeInfo $Abort = {.size=0, .align=0};
|
||||||
|
|
||||||
public CORD Func__as_text(const void *fn, bool colorize, const TypeInfo *type)
|
public CORD Func$as_text(const void *fn, bool colorize, const TypeInfo *type)
|
||||||
{
|
{
|
||||||
(void)fn;
|
(void)fn;
|
||||||
CORD c = type->FunctionInfo.type_str;
|
CORD c = type->FunctionInfo.type_str;
|
||||||
|
@ -63,12 +63,12 @@ typedef struct TypeInfo {
|
|||||||
#define $TypeInfoInfo(typestr) &((TypeInfo){.size=sizeof(TypeInfo), .align=__alignof__(TypeInfo), \
|
#define $TypeInfoInfo(typestr) &((TypeInfo){.size=sizeof(TypeInfo), .align=__alignof__(TypeInfo), \
|
||||||
.tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr})
|
.tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr})
|
||||||
|
|
||||||
extern const TypeInfo TypeInfo_info;
|
extern const TypeInfo $TypeInfo;
|
||||||
extern const TypeInfo Void;
|
extern const TypeInfo $Void;
|
||||||
extern const TypeInfo Abort;
|
extern const TypeInfo $Abort;
|
||||||
#define Void_t void
|
#define Void_t void
|
||||||
|
|
||||||
CORD Type__as_text(const void *typeinfo, bool colorize, const TypeInfo *type);
|
CORD Type$as_text(const void *typeinfo, bool colorize, const TypeInfo *type);
|
||||||
CORD Func__as_text(const void *fn, bool colorize, const TypeInfo *type);
|
CORD Func$as_text(const void *fn, bool colorize, const TypeInfo *type);
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -47,15 +47,15 @@ CORD CORD_asprintf(CORD fmt, ...);
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define LIST_MAP(src, var, ...) ({\
|
#define LIST_MAP(src, var, ...) ({\
|
||||||
__typeof(src) __mapped = NULL; \
|
__typeof(src) $mapped = NULL; \
|
||||||
__typeof(src) *__next = &__mapped; \
|
__typeof(src) *$next = &$mapped; \
|
||||||
for (__typeof(src) var = src; var; var = var->next) { \
|
for (__typeof(src) var = src; var; var = var->next) { \
|
||||||
*__next = GC_MALLOC(sizeof(__typeof(*(src)))); \
|
*$next = GC_MALLOC(sizeof(__typeof(*(src)))); \
|
||||||
**__next = *var; \
|
**$next = *var; \
|
||||||
**__next = (__typeof(*(src))){__VA_ARGS__}; \
|
**$next = (__typeof(*(src))){__VA_ARGS__}; \
|
||||||
__next = &((*__next)->next); \
|
$next = &((*$next)->next); \
|
||||||
} \
|
} \
|
||||||
__mapped; })
|
$mapped; })
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
|
122
compile.c
122
compile.c
@ -137,12 +137,12 @@ static CORD compile_lvalue(env_t *env, ast_t *ast)
|
|||||||
type_t *item_type = Match(container_t, ArrayType)->item_type;
|
type_t *item_type = Match(container_t, ArrayType)->item_type;
|
||||||
return CORD_all("$Array_lvalue(", compile_type(env, item_type), ", ", target_code, ", ",
|
return CORD_all("$Array_lvalue(", compile_type(env, item_type), ", ", target_code, ", ",
|
||||||
compile(env, index->index), ", ", compile_type_info(env, container_t),
|
compile(env, index->index), ", ", compile_type_info(env, container_t),
|
||||||
", ", Text__quoted(ast->file->filename, false), ", ", heap_strf("%ld", ast->start - ast->file->text),
|
", ", Text$quoted(ast->file->filename, false), ", ", heap_strf("%ld", ast->start - ast->file->text),
|
||||||
", ", heap_strf("%ld", ast->end - ast->file->text), ")");
|
", ", heap_strf("%ld", ast->end - ast->file->text), ")");
|
||||||
} else if (container_t->tag == TableType) {
|
} else if (container_t->tag == TableType) {
|
||||||
CORD target_code = compile_to_pointer_depth(env, index->indexed, 1, false);
|
CORD target_code = compile_to_pointer_depth(env, index->indexed, 1, false);
|
||||||
type_t *value_t = Match(container_t, TableType)->value_type;
|
type_t *value_t = Match(container_t, TableType)->value_type;
|
||||||
return CORD_all("*(", compile_type(env, value_t), "*)Table_reserve_value(", target_code, ", ",
|
return CORD_all("*(", compile_type(env, value_t), "*)Table$reserve_value(", target_code, ", ",
|
||||||
compile(env, index->index),", ", compile_type_info(env, container_t), ")");
|
compile(env, index->index),", ", compile_type_info(env, container_t), ")");
|
||||||
} else {
|
} else {
|
||||||
code_err(ast, "I don't know how to assign to this target");
|
code_err(ast, "I don't know how to assign to this target");
|
||||||
@ -376,15 +376,15 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
if (promote(env, &rhs, rhs_t, Match(lhs_t, ArrayType)->item_type)) {
|
if (promote(env, &rhs, rhs_t, Match(lhs_t, ArrayType)->item_type)) {
|
||||||
// arr ++= item
|
// arr ++= item
|
||||||
if (update->lhs->tag == Var)
|
if (update->lhs->tag == Var)
|
||||||
return CORD_all("Array__insert(&", lhs, ", $stack(", rhs, "), 0, ", compile_type_info(env, operand_t), ");");
|
return CORD_all("Array$insert(&", lhs, ", $stack(", rhs, "), 0, ", compile_type_info(env, operand_t), ");");
|
||||||
else
|
else
|
||||||
return CORD_all(lhs, "Array__concat(", lhs, ", $Array(", rhs, "), ", compile_type_info(env, operand_t), ");");
|
return CORD_all(lhs, "Array$concat(", lhs, ", $Array(", rhs, "), ", compile_type_info(env, operand_t), ");");
|
||||||
} else {
|
} else {
|
||||||
// arr ++= [...]
|
// arr ++= [...]
|
||||||
if (update->lhs->tag == Var)
|
if (update->lhs->tag == Var)
|
||||||
return CORD_all("Array__insert_all(&", lhs, ", ", rhs, ", 0, ", compile_type_info(env, operand_t), ");");
|
return CORD_all("Array$insert_all(&", lhs, ", ", rhs, ", 0, ", compile_type_info(env, operand_t), ");");
|
||||||
else
|
else
|
||||||
return CORD_all(lhs, "Array__concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ");");
|
return CORD_all(lhs, "Array$concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ");");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code_err(ast, "'++=' is not implemented for %T types", operand_t);
|
code_err(ast, "'++=' is not implemented for %T types", operand_t);
|
||||||
@ -408,7 +408,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
CORD_appendf(&env->code->typedefs, "extern const TypeInfo %r%s;\n", env->file_prefix, def->name);
|
CORD_appendf(&env->code->typedefs, "extern const TypeInfo %r%s;\n", env->file_prefix, def->name);
|
||||||
CORD_appendf(&env->code->typeinfos, "public const TypeInfo %r%s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%r}}};\n",
|
CORD_appendf(&env->code->typeinfos, "public const TypeInfo %r%s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%r}}};\n",
|
||||||
env->file_prefix, def->name, sizeof(CORD), __alignof__(CORD),
|
env->file_prefix, def->name, sizeof(CORD), __alignof__(CORD),
|
||||||
Text__quoted(def->name, false));
|
Text$quoted(def->name, false));
|
||||||
compile_namespace(env, def->name, def->namespace);
|
compile_namespace(env, def->name, def->namespace);
|
||||||
return CORD_EMPTY;
|
return CORD_EMPTY;
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
ast_t *args_def = FakeAST(StructDef, .name=arg_type_name, .fields=fndef->args);
|
ast_t *args_def = FakeAST(StructDef, .name=arg_type_name, .fields=fndef->args);
|
||||||
bind_statement(env, args_def);
|
bind_statement(env, args_def);
|
||||||
(void)compile_statement(env, args_def);
|
(void)compile_statement(env, args_def);
|
||||||
type_t *args_t = Table_str_get(*env->types, arg_type_name);
|
type_t *args_t = Table$str_get(*env->types, arg_type_name);
|
||||||
assert(args_t);
|
assert(args_t);
|
||||||
|
|
||||||
CORD all_args = CORD_EMPTY;
|
CORD all_args = CORD_EMPTY;
|
||||||
@ -475,8 +475,8 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
|
|
||||||
CORD pop_code = CORD_EMPTY;
|
CORD pop_code = CORD_EMPTY;
|
||||||
if (fndef->cache->tag == Int && Match(fndef->cache, Int)->i < INT64_MAX) {
|
if (fndef->cache->tag == Int && Match(fndef->cache, Int)->i < INT64_MAX) {
|
||||||
pop_code = CORD_all("if (Table_length($cache) > ", compile(body_scope, fndef->cache),
|
pop_code = CORD_all("if (Table$length($cache) > ", compile(body_scope, fndef->cache),
|
||||||
") Table_remove(&$cache, NULL, $table_info);\n");
|
") Table$remove(&$cache, NULL, $table_info);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CORD wrapper = CORD_all(
|
CORD wrapper = CORD_all(
|
||||||
@ -484,11 +484,11 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
"static table_t $cache = {};\n",
|
"static table_t $cache = {};\n",
|
||||||
compile_type(env, args_t), " $args = {", all_args, "};\n"
|
compile_type(env, args_t), " $args = {", all_args, "};\n"
|
||||||
"static const TypeInfo *$table_type = $TableInfo(", compile_type_info(env, args_t), ", ", compile_type_info(env, ret_t), ");\n",
|
"static const TypeInfo *$table_type = $TableInfo(", compile_type_info(env, args_t), ", ", compile_type_info(env, ret_t), ");\n",
|
||||||
ret_type_code, "*$cached = Table_get_raw($cache, &$args, $table_type);\n"
|
ret_type_code, "*$cached = Table$get_raw($cache, &$args, $table_type);\n"
|
||||||
"if ($cached) return *$cached;\n",
|
"if ($cached) return *$cached;\n",
|
||||||
ret_type_code, " $ret = ", name, "$uncached(", all_args, ");\n",
|
ret_type_code, " $ret = ", name, "$uncached(", all_args, ");\n",
|
||||||
pop_code,
|
pop_code,
|
||||||
"Table_set(&$cache, &$args, &$ret, $table_type);\n"
|
"Table$set(&$cache, &$args, &$ret, $table_type);\n"
|
||||||
"return $ret;\n"
|
"return $ret;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
env->code->funcs = CORD_cat(env->code->funcs, wrapper);
|
env->code->funcs = CORD_cat(env->code->funcs, wrapper);
|
||||||
@ -783,24 +783,24 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
CORD expr_as_text(env_t *env, CORD expr, type_t *t, CORD color)
|
CORD expr_as_text(env_t *env, CORD expr, type_t *t, CORD color)
|
||||||
{
|
{
|
||||||
switch (t->tag) {
|
switch (t->tag) {
|
||||||
case MemoryType: return CORD_asprintf("Memory__as_text($stack(%r), %r, &Memory)", expr, color);
|
case MemoryType: return CORD_asprintf("Memory$as_text($stack(%r), %r, &$Memory)", expr, color);
|
||||||
case BoolType: return CORD_asprintf("Bool__as_text($stack(%r), %r, &Bool)", expr, color);
|
case BoolType: return CORD_asprintf("Bool$as_text($stack(%r), %r, &$Bool)", expr, color);
|
||||||
case IntType: {
|
case IntType: {
|
||||||
CORD name = type_to_cord(t);
|
CORD name = type_to_cord(t);
|
||||||
return CORD_asprintf("%r__as_text($stack(%r), %r, &%r)", name, expr, color, name);
|
return CORD_asprintf("%r$as_text($stack(%r), %r, &$%r)", name, expr, color, name);
|
||||||
}
|
}
|
||||||
case NumType: {
|
case NumType: {
|
||||||
CORD name = type_to_cord(t);
|
CORD name = type_to_cord(t);
|
||||||
return CORD_asprintf("%r__as_text($stack(%r), %r, &Num%r)", name, expr, color, name);
|
return CORD_asprintf("%r$as_text($stack(%r), %r, &$Num%r)", name, expr, color, name);
|
||||||
}
|
}
|
||||||
case TextType: {
|
case TextType: {
|
||||||
const char *lang = Match(t, TextType)->lang;
|
const char *lang = Match(t, TextType)->lang;
|
||||||
return CORD_asprintf("Text__as_text($stack(%r), %r, &%s)", expr, color, lang ? lang : "Text");
|
return CORD_asprintf("Text$as_text($stack(%r), %r, &%s)", expr, color, lang ? lang : "$Text");
|
||||||
}
|
}
|
||||||
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 TableType: return CORD_asprintf("Table_as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case TableType: return CORD_asprintf("Table$as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
case FunctionType: return CORD_asprintf("Func__as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case FunctionType: return CORD_asprintf("Func$as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
case PointerType: return CORD_asprintf("Pointer__as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
case PointerType: return CORD_asprintf("Pointer$as_text($stack(%r), %r, %r)", expr, color, compile_type_info(env, t));
|
||||||
case StructType: case EnumType: return CORD_asprintf("(%r)->CustomInfo.as_text($stack(%r), %r, %r)",
|
case StructType: case EnumType: return CORD_asprintf("(%r)->CustomInfo.as_text($stack(%r), %r, %r)",
|
||||||
compile_type_info(env, t), expr, color, compile_type_info(env, t));
|
compile_type_info(env, t), expr, color, compile_type_info(env, t));
|
||||||
default: compiler_err(NULL, NULL, NULL, "Stringifying is not supported for %T", t);
|
default: compiler_err(NULL, NULL, NULL, "Stringifying is not supported for %T", t);
|
||||||
@ -865,7 +865,7 @@ static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg
|
|||||||
CORD value = compile(env, call_arg->value);
|
CORD value = compile(env, call_arg->value);
|
||||||
if (!promote(env, &value, actual_t, spec_arg->type))
|
if (!promote(env, &value, actual_t, spec_arg->type))
|
||||||
code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t);
|
code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t);
|
||||||
Table_str_set(&used_args, call_arg->name, call_arg);
|
Table$str_set(&used_args, call_arg->name, call_arg);
|
||||||
if (code) code = CORD_cat(code, ", ");
|
if (code) code = CORD_cat(code, ", ");
|
||||||
code = CORD_cat(code, value);
|
code = CORD_cat(code, value);
|
||||||
goto found_it;
|
goto found_it;
|
||||||
@ -877,12 +877,12 @@ static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg
|
|||||||
for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) {
|
for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) {
|
||||||
if (call_arg->name) continue;
|
if (call_arg->name) continue;
|
||||||
const char *pseudoname = heap_strf("%ld", i++);
|
const char *pseudoname = heap_strf("%ld", i++);
|
||||||
if (!Table_str_get(used_args, pseudoname)) {
|
if (!Table$str_get(used_args, pseudoname)) {
|
||||||
type_t *actual_t = get_type(env, call_arg->value);
|
type_t *actual_t = get_type(env, call_arg->value);
|
||||||
CORD value = compile(env, call_arg->value);
|
CORD value = compile(env, call_arg->value);
|
||||||
if (!promote(env, &value, actual_t, spec_arg->type))
|
if (!promote(env, &value, actual_t, spec_arg->type))
|
||||||
code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t);
|
code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t);
|
||||||
Table_str_set(&used_args, pseudoname, call_arg);
|
Table$str_set(&used_args, pseudoname, call_arg);
|
||||||
if (code) code = CORD_cat(code, ", ");
|
if (code) code = CORD_cat(code, ", ");
|
||||||
code = CORD_cat(code, value);
|
code = CORD_cat(code, value);
|
||||||
goto found_it;
|
goto found_it;
|
||||||
@ -903,11 +903,11 @@ static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg
|
|||||||
int64_t i = 1;
|
int64_t i = 1;
|
||||||
for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) {
|
for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) {
|
||||||
if (call_arg->name) {
|
if (call_arg->name) {
|
||||||
if (!Table_str_get(used_args, call_arg->name))
|
if (!Table$str_get(used_args, call_arg->name))
|
||||||
code_err(call_arg->value, "There is no argument with the name '%s'", call_arg->name);
|
code_err(call_arg->value, "There is no argument with the name '%s'", call_arg->name);
|
||||||
} else {
|
} else {
|
||||||
const char *pseudoname = heap_strf("%ld", i++);
|
const char *pseudoname = heap_strf("%ld", i++);
|
||||||
if (!Table_str_get(used_args, pseudoname))
|
if (!Table$str_get(used_args, pseudoname))
|
||||||
code_err(call_arg->value, "This is one argument too many!");
|
code_err(call_arg->value, "This is one argument too many!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -939,7 +939,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
switch (value_type(t)->tag) {
|
switch (value_type(t)->tag) {
|
||||||
case TextType: {
|
case TextType: {
|
||||||
CORD str = compile_to_pointer_depth(env, expr, 0, false);
|
CORD str = compile_to_pointer_depth(env, expr, 0, false);
|
||||||
return CORD_all("Text__num_clusters(", str, ")");
|
return CORD_all("Text$num_clusters(", str, ")");
|
||||||
}
|
}
|
||||||
case ArrayType: {
|
case ArrayType: {
|
||||||
if (t->tag == PointerType) {
|
if (t->tag == PointerType) {
|
||||||
@ -1125,7 +1125,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
return CORD_all("CORD_cat(", lhs, ", ", rhs, ")");
|
return CORD_all("CORD_cat(", lhs, ", ", rhs, ")");
|
||||||
}
|
}
|
||||||
case ArrayType: {
|
case ArrayType: {
|
||||||
return CORD_all("Array__concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ")");
|
return CORD_all("Array$concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ")");
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
code_err(ast, "Concatenation isn't supported for %T types", operand_t);
|
code_err(ast, "Concatenation isn't supported for %T types", operand_t);
|
||||||
@ -1165,7 +1165,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
}
|
}
|
||||||
case TextJoin: {
|
case TextJoin: {
|
||||||
const char *lang = Match(ast, TextJoin)->lang;
|
const char *lang = Match(ast, TextJoin)->lang;
|
||||||
type_t *text_t = Table_str_get(*env->types, lang ? lang : "Text");
|
type_t *text_t = Table$str_get(*env->types, lang ? lang : "Text");
|
||||||
if (!text_t || text_t->tag != TextType)
|
if (!text_t || text_t->tag != TextType)
|
||||||
code_err(ast, "%s is not a valid text language name", lang);
|
code_err(ast, "%s is not a valid text language name", lang);
|
||||||
env_t *lang_env = lang ? Match(get_binding(env, lang)->type, TypeInfoType)->env : NULL;
|
env_t *lang_env = lang ? Match(get_binding(env, lang)->type, TypeInfoType)->env : NULL;
|
||||||
@ -1186,8 +1186,8 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
} else if (lang && lang_env) {
|
} else if (lang && lang_env) {
|
||||||
// Get conversion function:
|
// Get conversion function:
|
||||||
chunk_code = compile(env, chunk->ast);
|
chunk_code = compile(env, chunk->ast);
|
||||||
for (int64_t i = 1; i <= Table_length(*lang_env->locals); i++) {
|
for (int64_t i = 1; i <= Table$length(*lang_env->locals); i++) {
|
||||||
struct {const char *name; binding_t *b; } *entry = Table_entry(*lang_env->locals, i);
|
struct {const char *name; binding_t *b; } *entry = Table$entry(*lang_env->locals, i);
|
||||||
if (entry->b->type->tag != FunctionType) continue;
|
if (entry->b->type->tag != FunctionType) continue;
|
||||||
if (!(streq(entry->name, "escape") || strncmp(entry->name, "escape_", strlen("escape_")) == 0))
|
if (!(streq(entry->name, "escape") || strncmp(entry->name, "escape_", strlen("escape_")) == 0))
|
||||||
continue;
|
continue;
|
||||||
@ -1421,14 +1421,14 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
(void)compile_statement(body_scope, stmt->ast);
|
(void)compile_statement(body_scope, stmt->ast);
|
||||||
|
|
||||||
CORD userdata;
|
CORD userdata;
|
||||||
if (Table_length(*fn_ctx.closed_vars) == 0) {
|
if (Table$length(*fn_ctx.closed_vars) == 0) {
|
||||||
code = CORD_cat(code, "void *$userdata)");
|
code = CORD_cat(code, "void *$userdata)");
|
||||||
userdata = "NULL";
|
userdata = "NULL";
|
||||||
} else {
|
} else {
|
||||||
CORD def = "typedef struct {";
|
CORD def = "typedef struct {";
|
||||||
userdata = CORD_all("new(", name, "$userdata_t");
|
userdata = CORD_all("new(", name, "$userdata_t");
|
||||||
for (int64_t i = 1; i <= Table_length(*fn_ctx.closed_vars); i++) {
|
for (int64_t i = 1; i <= Table$length(*fn_ctx.closed_vars); i++) {
|
||||||
struct { const char *name; binding_t *b; } *entry = Table_entry(*fn_ctx.closed_vars, i);
|
struct { const char *name; binding_t *b; } *entry = Table$entry(*fn_ctx.closed_vars, i);
|
||||||
def = CORD_all(def, compile_declaration(env, entry->b->type, entry->name), "; ");
|
def = CORD_all(def, compile_declaration(env, entry->b->type, entry->name), "; ");
|
||||||
userdata = CORD_all(userdata, ", ", entry->b->code);
|
userdata = CORD_all(userdata, ", ", entry->b->code);
|
||||||
}
|
}
|
||||||
@ -1460,42 +1460,42 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="item", .type=item_t,
|
arg_t *arg_spec = new(arg_t, .name="item", .type=item_t,
|
||||||
.next=new(arg_t, .name="at", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=0, .bits=64)));
|
.next=new(arg_t, .name="at", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=0, .bits=64)));
|
||||||
return CORD_all("Array__insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Array$insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "insert_all")) {
|
} else if (streq(call->name, "insert_all")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="items", .type=self_value_t,
|
arg_t *arg_spec = new(arg_t, .name="items", .type=self_value_t,
|
||||||
.next=new(arg_t, .name="at", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=0, .bits=64)));
|
.next=new(arg_t, .name="at", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=0, .bits=64)));
|
||||||
return CORD_all("Array__insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Array$insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "remove")) {
|
} else if (streq(call->name, "remove")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="index", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=-1, .bits=64),
|
arg_t *arg_spec = new(arg_t, .name="index", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=-1, .bits=64),
|
||||||
.next=new(arg_t, .name="count", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64)));
|
.next=new(arg_t, .name="count", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64)));
|
||||||
return CORD_all("Array__remove(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Array$remove(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "random")) {
|
} else if (streq(call->name, "random")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||||
return CORD_all("Array__random(", self, ")");
|
return CORD_all("Array$random(", self, ")");
|
||||||
} else if (streq(call->name, "shuffle")) {
|
} else if (streq(call->name, "shuffle")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
return CORD_all("Array__shuffle(", self, ", ", compile_type_info(env, self_value_t), ")");
|
return CORD_all("Array$shuffle(", self, ", ", compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "sort")) {
|
} else if (streq(call->name, "sort")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
return CORD_all("Array__sort(", self, ", ", compile_type_info(env, self_value_t), ")");
|
return CORD_all("Array$sort(", self, ", ", compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "clear")) {
|
} else if (streq(call->name, "clear")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
return CORD_all("Array__clear(", self, ")");
|
return CORD_all("Array$clear(", self, ")");
|
||||||
} else if (streq(call->name, "slice")) {
|
} else if (streq(call->name, "slice")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="first", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64),
|
arg_t *arg_spec = new(arg_t, .name="first", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64),
|
||||||
.next=new(arg_t, .name="length", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=INT64_MAX, .bits=64),
|
.next=new(arg_t, .name="length", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=INT64_MAX, .bits=64),
|
||||||
.next=new(arg_t, .name="stride", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64))));
|
.next=new(arg_t, .name="stride", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64))));
|
||||||
return CORD_all("Array__slice(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Array$slice(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "reversed")) {
|
} else if (streq(call->name, "reversed")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||||
return CORD_all("Array__reversed(", self, ")");
|
return CORD_all("Array$reversed(", self, ")");
|
||||||
} else code_err(ast, "There is no '%s' method for arrays", call->name);
|
} else code_err(ast, "There is no '%s' method for arrays", call->name);
|
||||||
}
|
}
|
||||||
case TableType: {
|
case TableType: {
|
||||||
@ -1503,22 +1503,22 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
if (streq(call->name, "get")) {
|
if (streq(call->name, "get")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="key", .type=Type(PointerType, .pointed=table->key_type, .is_stack=true, .is_readonly=true));
|
arg_t *arg_spec = new(arg_t, .name="key", .type=Type(PointerType, .pointed=table->key_type, .is_stack=true, .is_readonly=true));
|
||||||
return CORD_all("Table_get(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Table$get(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "set")) {
|
} else if (streq(call->name, "set")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type,
|
arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type,
|
||||||
.next=new(arg_t, .name="value", .type=table->value_type));
|
.next=new(arg_t, .name="value", .type=table->value_type));
|
||||||
return CORD_all("Table_set_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Table$set_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "remove")) {
|
} else if (streq(call->name, "remove")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
arg_t *arg_spec = new(arg_t, .name="key", .type=Type(PointerType, .pointed=table->key_type, .is_stack=true, .is_readonly=true));
|
arg_t *arg_spec = new(arg_t, .name="key", .type=Type(PointerType, .pointed=table->key_type, .is_stack=true, .is_readonly=true));
|
||||||
return CORD_all("Table_remove(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
return CORD_all("Table$remove(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||||
compile_type_info(env, self_value_t), ")");
|
compile_type_info(env, self_value_t), ")");
|
||||||
} else if (streq(call->name, "clear")) {
|
} else if (streq(call->name, "clear")) {
|
||||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||||
return CORD_all("Table_clear(", self, ")");
|
return CORD_all("Table$clear(", self, ")");
|
||||||
} else code_err(ast, "There is no '%s' method for tables", call->name);
|
} else code_err(ast, "There is no '%s' method for tables", call->name);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -1634,7 +1634,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
empty = FakeAST(
|
empty = FakeAST(
|
||||||
InlineCCode,
|
InlineCCode,
|
||||||
CORD_asprintf("fail_source(%r, %ld, %ld, \"This collection was empty!\");\n",
|
CORD_asprintf("fail_source(%r, %ld, %ld, \"This collection was empty!\");\n",
|
||||||
Text__quoted(ast->file->filename, false), (long)(reduction->iter->start - reduction->iter->file->text),
|
Text$quoted(ast->file->filename, false), (long)(reduction->iter->start - reduction->iter->file->text),
|
||||||
(long)(reduction->iter->end - reduction->iter->file->text)));
|
(long)(reduction->iter->end - reduction->iter->file->text)));
|
||||||
}
|
}
|
||||||
ast_t *i = FakeAST(Var, "$i");
|
ast_t *i = FakeAST(Var, "$i");
|
||||||
@ -1705,7 +1705,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
}
|
}
|
||||||
case ModuleType: {
|
case ModuleType: {
|
||||||
const char *name = Match(value_t, ModuleType)->name;
|
const char *name = Match(value_t, ModuleType)->name;
|
||||||
env_t *module_env = Table_str_get(*env->imports, name);
|
env_t *module_env = Table$str_get(*env->imports, name);
|
||||||
return compile(module_env, WrapAST(ast, Var, f->field));
|
return compile(module_env, WrapAST(ast, Var, f->field));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1722,7 +1722,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
if (ptr->pointed->tag == ArrayType) {
|
if (ptr->pointed->tag == ArrayType) {
|
||||||
return CORD_all("({ array_t *$arr = ", compile(env, indexing->indexed), "; $arr->data_refcount = 3; *$arr; })");
|
return CORD_all("({ array_t *$arr = ", compile(env, indexing->indexed), "; $arr->data_refcount = 3; *$arr; })");
|
||||||
} else if (ptr->pointed->tag == TableType) {
|
} else if (ptr->pointed->tag == TableType) {
|
||||||
return CORD_all("({ table_t *$t = ", compile(env, indexing->indexed), "; Table_mark_copy_on_write($t); *$t; })");
|
return CORD_all("({ table_t *$t = ", compile(env, indexing->indexed), "; Table$mark_copy_on_write($t); *$t; })");
|
||||||
} else {
|
} else {
|
||||||
return CORD_all("*(", compile(env, indexing->indexed), ")");
|
return CORD_all("*(", compile(env, indexing->indexed), ")");
|
||||||
}
|
}
|
||||||
@ -1741,7 +1741,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
return CORD_all("$Array_get_unchecked", compile_type(env, item_type), ", ", arr, ", ", index, ")");
|
return CORD_all("$Array_get_unchecked", compile_type(env, item_type), ", ", arr, ", ", index, ")");
|
||||||
else
|
else
|
||||||
return CORD_all("$Array_get(", compile_type(env, item_type), ", ", arr, ", ", index, ", ",
|
return CORD_all("$Array_get(", compile_type(env, item_type), ", ", arr, ", ", index, ", ",
|
||||||
Text__quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ",
|
Text$quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ",
|
||||||
CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)),
|
CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)),
|
||||||
")");
|
")");
|
||||||
}
|
}
|
||||||
@ -1755,7 +1755,7 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
file_t *f = indexing->index->file;
|
file_t *f = indexing->index->file;
|
||||||
return CORD_all("$Table_get(", table, ", ", compile_type(env, key_t), ", ", compile_type(env, value_t), ", ",
|
return CORD_all("$Table_get(", table, ", ", compile_type(env, key_t), ", ", compile_type(env, value_t), ", ",
|
||||||
key, ", ", compile_type_info(env, container_t), ", ",
|
key, ", ", compile_type_info(env, container_t), ", ",
|
||||||
Text__quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ",
|
Text$quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ",
|
||||||
CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)),
|
CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)),
|
||||||
")");
|
")");
|
||||||
}
|
}
|
||||||
@ -1812,10 +1812,10 @@ void compile_namespace(env_t *env, const char *ns_name, ast_t *block)
|
|||||||
CORD compile_type_info(env_t *env, type_t *t)
|
CORD compile_type_info(env_t *env, type_t *t)
|
||||||
{
|
{
|
||||||
switch (t->tag) {
|
switch (t->tag) {
|
||||||
case BoolType: case IntType: case NumType: return CORD_asprintf("&%r", type_to_cord(t));
|
case BoolType: case IntType: case NumType: return CORD_asprintf("&$%r", type_to_cord(t));
|
||||||
case TextType: {
|
case TextType: {
|
||||||
auto text = Match(t, TextType);
|
auto text = Match(t, TextType);
|
||||||
return text->lang ? CORD_all("(&", text->env->file_prefix, text->lang, ")") : "&Text";
|
return text->lang ? CORD_all("(&", text->env->file_prefix, text->lang, ")") : "&$Text";
|
||||||
}
|
}
|
||||||
case StructType: {
|
case StructType: {
|
||||||
auto s = Match(t, StructType);
|
auto s = Match(t, StructType);
|
||||||
@ -1838,15 +1838,15 @@ CORD compile_type_info(env_t *env, type_t *t)
|
|||||||
auto ptr = Match(t, PointerType);
|
auto ptr = Match(t, PointerType);
|
||||||
CORD sigil = ptr->is_stack ? "&" : (ptr->is_optional ? "?" : "@");
|
CORD sigil = ptr->is_stack ? "&" : (ptr->is_optional ? "?" : "@");
|
||||||
if (ptr->is_readonly) sigil = CORD_cat(sigil, "(readonly)");
|
if (ptr->is_readonly) sigil = CORD_cat(sigil, "(readonly)");
|
||||||
return CORD_asprintf("$PointerInfo(%r, %r)", Text__quoted(sigil, false), compile_type_info(env, ptr->pointed));
|
return CORD_asprintf("$PointerInfo(%r, %r)", Text$quoted(sigil, false), compile_type_info(env, ptr->pointed));
|
||||||
}
|
}
|
||||||
case FunctionType: {
|
case FunctionType: {
|
||||||
return CORD_asprintf("$FunctionInfo(%r)", Text__quoted(type_to_cord(t), false));
|
return CORD_asprintf("$FunctionInfo(%r)", Text$quoted(type_to_cord(t), false));
|
||||||
}
|
}
|
||||||
case ClosureType: {
|
case ClosureType: {
|
||||||
return CORD_asprintf("$ClosureInfo(%r)", Text__quoted(type_to_cord(t), false));
|
return CORD_asprintf("$ClosureInfo(%r)", Text$quoted(type_to_cord(t), false));
|
||||||
}
|
}
|
||||||
case TypeInfoType: return "&TypeInfo_info";
|
case TypeInfoType: return "&$TypeInfo";
|
||||||
default:
|
default:
|
||||||
compiler_err(NULL, 0, 0, "I couldn't convert to a type info: %T", t);
|
compiler_err(NULL, 0, 0, "I couldn't convert to a type info: %T", t);
|
||||||
}
|
}
|
||||||
@ -1858,7 +1858,7 @@ module_code_t compile_file(ast_t *ast)
|
|||||||
|
|
||||||
const char *name = file_base_name(ast->file->filename);
|
const char *name = file_base_name(ast->file->filename);
|
||||||
env->file_prefix = heap_strf("%s$", name);
|
env->file_prefix = heap_strf("%s$", name);
|
||||||
Table_str_set(env->imports, name, env);
|
Table$str_set(env->imports, name, env);
|
||||||
|
|
||||||
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
|
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
|
||||||
bind_statement(env, stmt->ast);
|
bind_statement(env, stmt->ast);
|
||||||
@ -1871,7 +1871,7 @@ module_code_t compile_file(ast_t *ast)
|
|||||||
.module_name=name,
|
.module_name=name,
|
||||||
.object_files=env->code->object_files,
|
.object_files=env->code->object_files,
|
||||||
.header=CORD_all(
|
.header=CORD_all(
|
||||||
// CORD_asprintf("#line 0 %r\n", Text__quoted(ast->file->filename, false)),
|
// CORD_asprintf("#line 0 %r\n", Text$quoted(ast->file->filename, false)),
|
||||||
"#include <tomo/tomo.h>\n",
|
"#include <tomo/tomo.h>\n",
|
||||||
env->code->typedefs, "\n",
|
env->code->typedefs, "\n",
|
||||||
env->code->typecode, "\n",
|
env->code->typecode, "\n",
|
||||||
@ -1879,7 +1879,7 @@ module_code_t compile_file(ast_t *ast)
|
|||||||
"public void ", env->file_prefix, "use(void);\n"
|
"public void ", env->file_prefix, "use(void);\n"
|
||||||
),
|
),
|
||||||
.c_file=CORD_all(
|
.c_file=CORD_all(
|
||||||
// CORD_asprintf("#line 0 %r\n", Text__quoted(ast->file->filename, false)),
|
// CORD_asprintf("#line 0 %r\n", Text$quoted(ast->file->filename, false)),
|
||||||
env->code->imports, "\n",
|
env->code->imports, "\n",
|
||||||
env->code->staticdefs, "\n",
|
env->code->staticdefs, "\n",
|
||||||
env->code->funcs, "\n",
|
env->code->funcs, "\n",
|
||||||
|
8
enums.c
8
enums.c
@ -58,7 +58,7 @@ static CORD compile_compare_method(env_t *env, ast_t *ast)
|
|||||||
"switch (x->$tag) {\n");
|
"switch (x->$tag) {\n");
|
||||||
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
||||||
if (tag->fields) {
|
if (tag->fields) {
|
||||||
type_t *tag_type = Table_str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
type_t *tag_type = Table$str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
||||||
cmp_func = CORD_all(cmp_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
cmp_func = CORD_all(cmp_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
||||||
"return generic_compare(&x->", tag->name, ", &y->", tag->name, ", ", compile_type_info(env, tag_type), ");\n");
|
"return generic_compare(&x->", tag->name, ", &y->", tag->name, ", ", compile_type_info(env, tag_type), ");\n");
|
||||||
} else {
|
} else {
|
||||||
@ -80,7 +80,7 @@ static CORD compile_equals_method(env_t *env, ast_t *ast)
|
|||||||
"switch (x->$tag) {\n");
|
"switch (x->$tag) {\n");
|
||||||
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
||||||
if (tag->fields) {
|
if (tag->fields) {
|
||||||
type_t *tag_type = Table_str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
type_t *tag_type = Table$str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
||||||
eq_func = CORD_all(eq_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
eq_func = CORD_all(eq_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
||||||
"return generic_equal(&x->", tag->name, ", &y->", tag->name, ", ", compile_type_info(env, tag_type), ");\n");
|
"return generic_equal(&x->", tag->name, ", &y->", tag->name, ", ", compile_type_info(env, tag_type), ");\n");
|
||||||
} else {
|
} else {
|
||||||
@ -101,7 +101,7 @@ static CORD compile_hash_method(env_t *env, ast_t *ast)
|
|||||||
"switch (obj->$tag) {\n");
|
"switch (obj->$tag) {\n");
|
||||||
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
|
||||||
if (tag->fields) {
|
if (tag->fields) {
|
||||||
type_t *tag_type = Table_str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
type_t *tag_type = Table$str_get(*env->types, CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)));
|
||||||
hash_func = CORD_all(hash_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
hash_func = CORD_all(hash_func, "\tcase $tag$", full_name, "$", tag->name, ": "
|
||||||
"hashes[1] = generic_hash(&obj->", tag->name, ", ", compile_type_info(env, tag_type), ");\n"
|
"hashes[1] = generic_hash(&obj->", tag->name, ", ", compile_type_info(env, tag_type), ");\n"
|
||||||
"break;\n");
|
"break;\n");
|
||||||
@ -163,7 +163,7 @@ void compile_enum_def(env_t *env, ast_t *ast)
|
|||||||
enum_def = CORD_cat(enum_def, "};\n};\n");
|
enum_def = CORD_cat(enum_def, "};\n};\n");
|
||||||
env->code->typecode = CORD_cat(env->code->typecode, enum_def);
|
env->code->typecode = CORD_cat(env->code->typecode, enum_def);
|
||||||
|
|
||||||
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 %s = {%zu, %zu, {.tag=CustomInfo, .CustomInfo={",
|
CORD typeinfo = CORD_asprintf("public const TypeInfo %s = {%zu, %zu, {.tag=CustomInfo, .CustomInfo={",
|
||||||
full_name, type_size(t), type_align(t));
|
full_name, type_size(t), type_align(t));
|
||||||
|
|
||||||
|
159
environment.c
159
environment.c
@ -35,7 +35,7 @@ env_t *new_compilation_unit(void)
|
|||||||
for (size_t i = 0; i < sizeof(global_vars)/sizeof(global_vars[0]); i++) {
|
for (size_t i = 0; i < sizeof(global_vars)/sizeof(global_vars[0]); i++) {
|
||||||
binding_t *b = new(binding_t);
|
binding_t *b = new(binding_t);
|
||||||
*b = global_vars[i].binding;
|
*b = global_vars[i].binding;
|
||||||
Table_str_set(env->globals, global_vars[i].name, b);
|
Table$str_set(env->globals, global_vars[i].name, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -49,63 +49,63 @@ env_t *new_compilation_unit(void)
|
|||||||
CORD struct_val;
|
CORD struct_val;
|
||||||
array_t namespace;
|
array_t namespace;
|
||||||
} global_types[] = {
|
} global_types[] = {
|
||||||
{"Bool", Type(BoolType), "Bool_t", "Bool", {}},
|
{"Bool", Type(BoolType), "Bool_t", "$Bool", {}},
|
||||||
{"Int", Type(IntType, .bits=64), "Int_t", "Int", $TypedArray(ns_entry_t,
|
{"Int", Type(IntType, .bits=64), "Int_t", "$Int", $TypedArray(ns_entry_t,
|
||||||
{"format", "Int__format", "func(i:Int, digits=0)->Text"},
|
{"format", "Int$format", "func(i:Int, digits=0)->Text"},
|
||||||
{"hex", "Int__hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int__octal", "func(i:Int, digits=0, prefix=yes)->Text"},
|
{"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int__random", "func(min=0, max=0xffffffff)->Int"},
|
{"random", "Int$random", "func(min=0, max=0xffffffff)->Int"},
|
||||||
{"bits", "Int__bits", "func(x:Int)->[Bool]"},
|
{"bits", "Int$bits", "func(x:Int)->[Bool]"},
|
||||||
{"abs", "labs", "func(i:Int)->Int"},
|
{"abs", "labs", "func(i:Int)->Int"},
|
||||||
{"min", "Int__min", "Int"},
|
{"min", "Int$min", "Int"},
|
||||||
{"max", "Int__max", "Int"},
|
{"max", "Int$max", "Int"},
|
||||||
)},
|
)},
|
||||||
{"Int32", Type(IntType, .bits=32), "Int32_t", "Int32", $TypedArray(ns_entry_t,
|
{"Int32", Type(IntType, .bits=32), "Int32_t", "$Int32", $TypedArray(ns_entry_t,
|
||||||
{"format", "Int32__format", "func(i:Int32, digits=0)->Text"},
|
{"format", "Int32$format", "func(i:Int32, digits=0)->Text"},
|
||||||
{"hex", "Int32__hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int32__octal", "func(i:Int32, digits=0, prefix=yes)->Text"},
|
{"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int32__random", "func(min=0, max=0xffffffff)->Int32"},
|
{"random", "Int32$random", "func(min=0, max=0xffffffff)->Int32"},
|
||||||
{"bits", "Int32__bits", "func(x:Int32)->[Bool]"},
|
{"bits", "Int32$bits", "func(x:Int32)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int32)->Int32"},
|
{"abs", "abs", "func(i:Int32)->Int32"},
|
||||||
{"min", "Int32__min", "Int32"},
|
{"min", "Int32$min", "Int32"},
|
||||||
{"max", "Int32__max", "Int32"},
|
{"max", "Int32$max", "Int32"},
|
||||||
)},
|
)},
|
||||||
{"Int16", Type(IntType, .bits=16), "Int16_t", "Int16", $TypedArray(ns_entry_t,
|
{"Int16", Type(IntType, .bits=16), "Int16_t", "$Int16", $TypedArray(ns_entry_t,
|
||||||
{"format", "Int16__format", "func(i:Int16, digits=0)->Text"},
|
{"format", "Int16$format", "func(i:Int16, digits=0)->Text"},
|
||||||
{"hex", "Int16__hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int16__octal", "func(i:Int16, digits=0, prefix=yes)->Text"},
|
{"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int16__random", "func(min=0, max=0xffffffff)->Int16"},
|
{"random", "Int16$random", "func(min=0, max=0xffffffff)->Int16"},
|
||||||
{"bits", "Int16__bits", "func(x:Int16)->[Bool]"},
|
{"bits", "Int16$bits", "func(x:Int16)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int16)->Int16"},
|
{"abs", "abs", "func(i:Int16)->Int16"},
|
||||||
{"min", "Int16__min", "Int16"},
|
{"min", "Int16$min", "Int16"},
|
||||||
{"max", "Int16__max", "Int16"},
|
{"max", "Int16$max", "Int16"},
|
||||||
)},
|
)},
|
||||||
{"Int8", Type(IntType, .bits=8), "Int8_t", "Int8", $TypedArray(ns_entry_t,
|
{"Int8", Type(IntType, .bits=8), "Int8_t", "$Int8", $TypedArray(ns_entry_t,
|
||||||
{"format", "Int8__format", "func(i:Int8, digits=0)->Text"},
|
{"format", "Int8$format", "func(i:Int8, digits=0)->Text"},
|
||||||
{"hex", "Int8__hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int8__octal", "func(i:Int8, digits=0, prefix=yes)->Text"},
|
{"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int8__random", "func(min=0, max=0xffffffff)->Int8"},
|
{"random", "Int8$random", "func(min=0, max=0xffffffff)->Int8"},
|
||||||
{"bits", "Int8__bits", "func(x:Int8)->[Bool]"},
|
{"bits", "Int8$bits", "func(x:Int8)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int8)->Int8"},
|
{"abs", "abs", "func(i:Int8)->Int8"},
|
||||||
{"min", "Int8__min", "Int8"},
|
{"min", "Int8$min", "Int8"},
|
||||||
{"max", "Int8__max", "Int8"},
|
{"max", "Int8$max", "Int8"},
|
||||||
)},
|
)},
|
||||||
#define C(name) {#name, "M_"#name, "Num"}
|
#define C(name) {#name, "M_"#name, "Num"}
|
||||||
#define F(name) {#name, #name, "func(n:Num)->Num"}
|
#define F(name) {#name, #name, "func(n:Num)->Num"}
|
||||||
#define F2(name) {#name, #name, "func(x:Num, y:Num)->Num"}
|
#define F2(name) {#name, #name, "func(x:Num, y:Num)->Num"}
|
||||||
{"Num", Type(NumType, .bits=64), "Num_t", "Num", $TypedArray(ns_entry_t,
|
{"Num", Type(NumType, .bits=64), "Num_t", "$Num", $TypedArray(ns_entry_t,
|
||||||
{"near", "Num__near", "func(x:Num, y:Num, ratio=1e-9, min_epsilon=1e-9)->Bool"},
|
{"near", "Num$near", "func(x:Num, y:Num, ratio=1e-9, min_epsilon=1e-9)->Bool"},
|
||||||
{"format", "Num__format", "func(n:Num, precision=0)->Text"},
|
{"format", "Num$format", "func(n:Num, precision=0)->Text"},
|
||||||
{"scientific", "Num__scientific", "func(n:Num, precision=0)->Text"},
|
{"scientific", "Num$scientific", "func(n:Num, precision=0)->Text"},
|
||||||
{"nan", "Num__nan", "func(tag=\"\")->Num"},
|
{"nan", "Num$nan", "func(tag=\"\")->Num"},
|
||||||
{"isinf", "Num__isinf", "func(n:Num)->Bool"},
|
{"isinf", "Num$isinf", "func(n:Num)->Bool"},
|
||||||
{"isfinite", "Num__isfinite", "func(n:Num)->Bool"},
|
{"isfinite", "Num$isfinite", "func(n:Num)->Bool"},
|
||||||
{"isnan", "Num__isnan", "func(n:Num)->Bool"},
|
{"isnan", "Num$isnan", "func(n:Num)->Bool"},
|
||||||
C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E),
|
C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E),
|
||||||
C(PI), C(PI_4), C(SQRT2), C(SQRT1_2),
|
C(PI), C(PI_4), C(SQRT2), C(SQRT1_2),
|
||||||
{"INF", "INFINITY", "Num"},
|
{"INF", "INFINITY", "Num"},
|
||||||
{"TAU", "(2.*M_PI)", "Num"},
|
{"TAU", "(2.*M_PI)", "Num"},
|
||||||
{"random", "Num__random", "func()->Num"},
|
{"random", "Num$random", "func()->Num"},
|
||||||
{"abs", "fabs", "func(n:Num)->Num"},
|
{"abs", "fabs", "func(n:Num)->Num"},
|
||||||
F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc),
|
F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc),
|
||||||
F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb),
|
F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb),
|
||||||
@ -119,19 +119,19 @@ env_t *new_compilation_unit(void)
|
|||||||
#define C(name) {#name, "(Num32_t)(M_"#name")", "Num32"}
|
#define C(name) {#name, "(Num32_t)(M_"#name")", "Num32"}
|
||||||
#define F(name) {#name, #name"f", "func(n:Num32)->Num32"}
|
#define F(name) {#name, #name"f", "func(n:Num32)->Num32"}
|
||||||
#define F2(name) {#name, #name"f", "func(x:Num32, y:Num32)->Num32"}
|
#define F2(name) {#name, #name"f", "func(x:Num32, y:Num32)->Num32"}
|
||||||
{"Num32", Type(NumType, .bits=32), "Num32_t", "Num32", $TypedArray(ns_entry_t,
|
{"Num32", Type(NumType, .bits=32), "Num32_t", "$Num32", $TypedArray(ns_entry_t,
|
||||||
{"near", "Num32__near", "func(x:Num32, y:Num32, ratio=1e-9f32, min_epsilon=1e-9f32)->Bool"},
|
{"near", "Num32$near", "func(x:Num32, y:Num32, ratio=1e-9f32, min_epsilon=1e-9f32)->Bool"},
|
||||||
{"format", "Num32__format", "func(n:Num32, precision=0)->Text"},
|
{"format", "Num32$format", "func(n:Num32, precision=0)->Text"},
|
||||||
{"scientific", "Num32__scientific", "func(n:Num32, precision=0)->Text"},
|
{"scientific", "Num32$scientific", "func(n:Num32, precision=0)->Text"},
|
||||||
{"nan", "Num32__nan", "func(tag=\"\")->Num32"},
|
{"nan", "Num32$nan", "func(tag=\"\")->Num32"},
|
||||||
{"isinf", "Num32__isinf", "func(n:Num32)->Bool"},
|
{"isinf", "Num32$isinf", "func(n:Num32)->Bool"},
|
||||||
{"isfinite", "Num32__isfinite", "func(n:Num32)->Bool"},
|
{"isfinite", "Num32$isfinite", "func(n:Num32)->Bool"},
|
||||||
{"isnan", "Num32__isnan", "func(n:Num32)->Bool"},
|
{"isnan", "Num32$isnan", "func(n:Num32)->Bool"},
|
||||||
C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E),
|
C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E),
|
||||||
C(PI), C(PI_4), C(SQRT2), C(SQRT1_2),
|
C(PI), C(PI_4), C(SQRT2), C(SQRT1_2),
|
||||||
{"INF", "(Num32_t)(INFINITY)", "Num32"},
|
{"INF", "(Num32_t)(INFINITY)", "Num32"},
|
||||||
{"TAU", "(Num32_t)(2.f*M_PI)", "Num32"},
|
{"TAU", "(Num32_t)(2.f*M_PI)", "Num32"},
|
||||||
{"random", "Num32__random", "func()->Num32"},
|
{"random", "Num32$random", "func()->Num32"},
|
||||||
{"abs", "fabsf", "func(n:Num32)->Num32"},
|
{"abs", "fabsf", "func(n:Num32)->Num32"},
|
||||||
F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc),
|
F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc),
|
||||||
F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb),
|
F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb),
|
||||||
@ -142,43 +142,44 @@ env_t *new_compilation_unit(void)
|
|||||||
#undef F2
|
#undef F2
|
||||||
#undef F
|
#undef F
|
||||||
#undef C
|
#undef C
|
||||||
{"Text", TEXT_TYPE, "Text_t", "Text", $TypedArray(ns_entry_t,
|
{"Text", TEXT_TYPE, "Text_t", "$Text", $TypedArray(ns_entry_t,
|
||||||
{"quoted", "Text__quoted", "func(text:Text, color=no)->Text"},
|
{"quoted", "Text$quoted", "func(text:Text, color=no)->Text"},
|
||||||
{"upper", "Text__upper", "func(text:Text)->Text"},
|
{"upper", "Text$upper", "func(text:Text)->Text"},
|
||||||
{"lower", "Text__lower", "func(text:Text)->Text"},
|
{"lower", "Text$lower", "func(text:Text)->Text"},
|
||||||
{"title", "Text__title", "func(text:Text)->Text"},
|
{"title", "Text$title", "func(text:Text)->Text"},
|
||||||
// {"has", "Text__has", "func(text:Text, target:Text, where=ANYWHERE)->Bool"},
|
// {"has", "Text$has", "func(text:Text, target:Text, where=ANYWHERE)->Bool"},
|
||||||
// {"without", "Text__without", "func(text:Text, target:Text, where=ANYWHERE)->Text"},
|
// {"without", "Text$without", "func(text:Text, target:Text, where=ANYWHERE)->Text"},
|
||||||
// {"trimmed", "Text__without", "func(text:Text, skip:Text, where=ANYWHERE)->Text"},
|
// {"trimmed", "Text$without", "func(text:Text, skip:Text, where=ANYWHERE)->Text"},
|
||||||
{"title", "Text__title", "func(text:Text)->Text"},
|
{"title", "Text$title", "func(text:Text)->Text"},
|
||||||
// {"find", "Text__find", "func(text:Text, pattern:Text)->FindResult"},
|
// {"find", "Text$find", "func(text:Text, pattern:Text)->FindResult"},
|
||||||
{"replace", "Text__replace", "func(text:Text, pattern:Text, replacement:Text, limit=Int.max)->Text"},
|
{"replace", "Text$replace", "func(text:Text, pattern:Text, replacement:Text, limit=Int.max)->Text"},
|
||||||
{"split", "Text__split", "func(text:Text, split:Text)->[Text]"},
|
{"split", "Text$split", "func(text:Text, split:Text)->[Text]"},
|
||||||
{"join", "Text__join", "func(glue:Text, pieces:[Text])->Text"},
|
{"join", "Text$join", "func(glue:Text, pieces:[Text])->Text"},
|
||||||
{"clusters", "Text__clusters", "func(text:Text)->[Text]"},
|
{"clusters", "Text$clusters", "func(text:Text)->[Text]"},
|
||||||
{"codepoints", "Text__codepoints", "func(text:Text)->[Int32]"},
|
{"codepoints", "Text$codepoints", "func(text:Text)->[Int32]"},
|
||||||
{"bytes", "Text__bytes", "func(text:Text)->[Int8]"},
|
{"bytes", "Text$bytes", "func(text:Text)->[Int8]"},
|
||||||
{"num_clusters", "Text__num_clusters", "func(text:Text)->Int"},
|
{"num_clusters", "Text$num_clusters", "func(text:Text)->Int"},
|
||||||
{"num_codepoints", "Text__num_codepoints", "func(text:Text)->Int"},
|
{"num_codepoints", "Text$num_codepoints", "func(text:Text)->Int"},
|
||||||
{"num_bytes", "Text__num_bytes", "func(text:Text)->Int"},
|
{"num_bytes", "Text$num_bytes", "func(text:Text)->Int"},
|
||||||
{"character_names", "Text__character_names", "func(text:Text)->[Text]"},
|
{"character_names", "Text$character_names", "func(text:Text)->[Text]"},
|
||||||
)},
|
)},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
|
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
|
||||||
env_t *ns_env = global_types[i].type == TEXT_TYPE ? Match(TEXT_TYPE, TextType)->env : namespace_env(env, global_types[i].name);
|
env_t *ns_env = global_types[i].type == TEXT_TYPE ? Match(TEXT_TYPE, TextType)->env : namespace_env(env, global_types[i].name);
|
||||||
binding_t *binding = new(binding_t, .type=Type(TypeInfoType, .name=global_types[i].name, .type=global_types[i].type, .env=ns_env));
|
binding_t *binding = new(binding_t, .type=Type(TypeInfoType, .name=global_types[i].name, .type=global_types[i].type, .env=ns_env));
|
||||||
Table_str_set(env->globals, global_types[i].name, binding);
|
Table$str_set(env->globals, global_types[i].name, binding);
|
||||||
Table_str_set(env->types, global_types[i].name, global_types[i].type);
|
Table$str_set(env->types, global_types[i].name, global_types[i].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
|
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
|
||||||
binding_t *type_binding = Table_str_get(*env->globals, global_types[i].name);
|
binding_t *type_binding = Table$str_get(*env->globals, global_types[i].name);
|
||||||
assert(type_binding);
|
assert(type_binding);
|
||||||
env_t *ns_env = Match(type_binding->type, TypeInfoType)->env;
|
env_t *ns_env = Match(type_binding->type, TypeInfoType)->env;
|
||||||
for (int64_t j = 0; j < global_types[i].namespace.length; j++) {
|
for (int64_t j = 0; j < global_types[i].namespace.length; j++) {
|
||||||
ns_entry_t *entry = global_types[i].namespace.data + j*global_types[i].namespace.stride;
|
ns_entry_t *entry = global_types[i].namespace.data + j*global_types[i].namespace.stride;
|
||||||
type_t *type = parse_type_string(ns_env, entry->type_str);
|
type_t *type = parse_type_string(ns_env, entry->type_str);
|
||||||
|
if (!type) compiler_err(NULL, NULL, NULL, "Couldn't parse type string: %s", entry->type_str);
|
||||||
if (type->tag == ClosureType) type = Match(type, ClosureType)->fn;
|
if (type->tag == ClosureType) type = Match(type, ClosureType)->fn;
|
||||||
binding_t *b = new(binding_t, .code=entry->code, .type=type);
|
binding_t *b = new(binding_t, .code=entry->code, .type=type);
|
||||||
set_binding(ns_env, entry->name, b);
|
set_binding(ns_env, entry->name, b);
|
||||||
@ -269,11 +270,11 @@ env_t *namespace_env(env_t *env, const char *namespace_name)
|
|||||||
|
|
||||||
binding_t *get_binding(env_t *env, const char *name)
|
binding_t *get_binding(env_t *env, const char *name)
|
||||||
{
|
{
|
||||||
binding_t *b = Table_str_get(*env->locals, name);
|
binding_t *b = Table$str_get(*env->locals, name);
|
||||||
if (!b && env->fn_ctx && env->fn_ctx->closure_scope) {
|
if (!b && env->fn_ctx && env->fn_ctx->closure_scope) {
|
||||||
b = Table_str_get(*env->fn_ctx->closure_scope, name);
|
b = Table$str_get(*env->fn_ctx->closure_scope, name);
|
||||||
if (b) {
|
if (b) {
|
||||||
Table_str_set(env->fn_ctx->closed_vars, name, b);
|
Table$str_set(env->fn_ctx->closed_vars, name, b);
|
||||||
return new(binding_t, .type=b->type, .code=CORD_all("$userdata->", name));
|
return new(binding_t, .type=b->type, .code=CORD_all("$userdata->", name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +325,7 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name)
|
|||||||
void set_binding(env_t *env, const char *name, binding_t *binding)
|
void set_binding(env_t *env, const char *name, binding_t *binding)
|
||||||
{
|
{
|
||||||
if (name && binding)
|
if (name && binding)
|
||||||
Table_str_set(env->locals, name, binding);
|
Table$str_set(env->locals, name, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_err(file_t *f, const char *start, const char *end, const char *fmt, ...)
|
void compiler_err(file_t *f, const char *start, const char *end, const char *fmt, ...)
|
||||||
|
@ -42,8 +42,11 @@ typedef struct env_s {
|
|||||||
} env_t;
|
} env_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CORD code;
|
|
||||||
type_t *type;
|
type_t *type;
|
||||||
|
union {
|
||||||
|
CORD code;
|
||||||
|
char value[0];
|
||||||
|
};
|
||||||
} binding_t;
|
} binding_t;
|
||||||
|
|
||||||
env_t *new_compilation_unit(void);
|
env_t *new_compilation_unit(void);
|
||||||
|
@ -127,7 +127,7 @@ void compile_struct_def(env_t *env, ast_t *ast)
|
|||||||
// Typeinfo:
|
// Typeinfo:
|
||||||
CORD_appendf(&env->code->typedefs, "extern const TypeInfo %r;\n", full_name);
|
CORD_appendf(&env->code->typedefs, "extern const TypeInfo %r;\n", full_name);
|
||||||
|
|
||||||
type_t *t = Table_str_get(*env->types, def->name);
|
type_t *t = Table$str_get(*env->types, def->name);
|
||||||
assert(t && t->tag == StructType);
|
assert(t && t->tag == StructType);
|
||||||
auto struct_ = Match(t, StructType);
|
auto struct_ = Match(t, StructType);
|
||||||
CORD typeinfo = CORD_asprintf("public const TypeInfo %r = {%zu, %zu, {.tag=CustomInfo, .CustomInfo={",
|
CORD typeinfo = CORD_asprintf("public const TypeInfo %r = {%zu, %zu, {.tag=CustomInfo, .CustomInfo={",
|
||||||
@ -140,11 +140,11 @@ void compile_struct_def(env_t *env, ast_t *ast)
|
|||||||
type_t *member_t = struct_->fields->type;
|
type_t *member_t = struct_->fields->type;
|
||||||
switch (member_t->tag) {
|
switch (member_t->tag) {
|
||||||
case TextType:
|
case TextType:
|
||||||
typeinfo = CORD_all(typeinfo, ".hash=(void*)", type_to_cord(member_t), "__hash", ", ");
|
typeinfo = CORD_all(typeinfo, ".hash=(void*)", type_to_cord(member_t), "$hash", ", ");
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case IntType: case NumType:
|
case IntType: case NumType:
|
||||||
typeinfo = CORD_all(typeinfo, ".compare=(void*)", type_to_cord(member_t), "__compare, "
|
typeinfo = CORD_all(typeinfo, ".compare=(void*)", type_to_cord(member_t), "$compare, "
|
||||||
".equal=(void*)", type_to_cord(member_t), "__equal, ");
|
".equal=(void*)", type_to_cord(member_t), "$equal, ");
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case BoolType: goto got_methods;
|
case BoolType: goto got_methods;
|
||||||
default: break;
|
default: break;
|
||||||
|
16
tomo.c
16
tomo.c
@ -123,12 +123,12 @@ static void build_file_dependency_graph(const char *filename, table_t *dependenc
|
|||||||
else
|
else
|
||||||
errx(1, "I don't know how to find object files in: %s", filename);
|
errx(1, "I don't know how to find object files in: %s", filename);
|
||||||
|
|
||||||
if (Table_str_get(*dependencies, base_filename))
|
if (Table$str_get(*dependencies, base_filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
array_t *deps = new(array_t);
|
array_t *deps = new(array_t);
|
||||||
Array__insert(deps, &base_filename, 0, $ArrayInfo(&Text));
|
Array$insert(deps, &base_filename, 0, $ArrayInfo(&$Text));
|
||||||
Table_str_set(dependencies, base_filename, deps);
|
Table$str_set(dependencies, base_filename, deps);
|
||||||
|
|
||||||
transpile(base_filename, false);
|
transpile(base_filename, false);
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ static void build_file_dependency_graph(const char *filename, table_t *dependenc
|
|||||||
char *tmp = realpath(heap_strf("%s/%.*s", file_dir, strcspn(line + strlen(prefix), "\"") - 2, line + strlen(prefix)), NULL);
|
char *tmp = realpath(heap_strf("%s/%.*s", file_dir, strcspn(line + strlen(prefix), "\"") - 2, line + strlen(prefix)), NULL);
|
||||||
const char *resolved_file = heap_str(tmp);
|
const char *resolved_file = heap_str(tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
Array__insert(deps, &resolved_file, 0, $ArrayInfo(&Text));
|
Array$insert(deps, &resolved_file, 0, $ArrayInfo(&$Text));
|
||||||
build_file_dependency_graph(resolved_file, dependencies);
|
build_file_dependency_graph(resolved_file, dependencies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,13 +166,13 @@ array_t get_file_dependencies(const char *filename)
|
|||||||
|
|
||||||
const TypeInfo unit = {.size=0, .align=0, .tag=CustomInfo};
|
const TypeInfo unit = {.size=0, .align=0, .tag=CustomInfo};
|
||||||
const TypeInfo info = {.size=sizeof(table_t), .align=__alignof__(table_t),
|
const TypeInfo info = {.size=sizeof(table_t), .align=__alignof__(table_t),
|
||||||
.tag=TableInfo, .TableInfo.key=&Text, .TableInfo.value=&unit};
|
.tag=TableInfo, .TableInfo.key=&$Text, .TableInfo.value=&unit};
|
||||||
|
|
||||||
for (int64_t i = 1; i <= Table_length(file_dependencies); i++) {
|
for (int64_t i = 1; i <= Table$length(file_dependencies); i++) {
|
||||||
struct { const char *name; array_t *deps; } *entry = Table_entry(file_dependencies, i);
|
struct { const char *name; array_t *deps; } *entry = Table$entry(file_dependencies, i);
|
||||||
for (int64_t j = 0; j < entry->deps->length; j++) {
|
for (int64_t j = 0; j < entry->deps->length; j++) {
|
||||||
const char *dep = *(char**)(entry->deps->data + j*entry->deps->stride);
|
const char *dep = *(char**)(entry->deps->data + j*entry->deps->stride);
|
||||||
Table_set(&dependency_set, &dep, &dep, &info);
|
Table$set(&dependency_set, &dep, &dep, &info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dependency_set.entries;
|
return dependency_set.entries;
|
||||||
|
26
typecheck.c
26
typecheck.c
@ -19,7 +19,7 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast)
|
|||||||
switch (ast->tag) {
|
switch (ast->tag) {
|
||||||
case VarTypeAST: {
|
case VarTypeAST: {
|
||||||
const char *name = Match(ast, VarTypeAST)->name;
|
const char *name = Match(ast, VarTypeAST)->name;
|
||||||
type_t *t = Table_str_get(*env->types, name);
|
type_t *t = Table$str_get(*env->types, name);
|
||||||
if (t) return t;
|
if (t) return t;
|
||||||
code_err(ast, "I don't know a type with the name '%s'", name);
|
code_err(ast, "I don't know a type with the name '%s'", name);
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
|
|
||||||
arg_t *fields = NULL;
|
arg_t *fields = NULL;
|
||||||
type_t *type = Type(StructType, .name=def->name, .fields=fields, .opaque=true, .env=ns_env); // placeholder
|
type_t *type = Type(StructType, .name=def->name, .fields=fields, .opaque=true, .env=ns_env); // placeholder
|
||||||
Table_str_set(env->types, def->name, type);
|
Table$str_set(env->types, def->name, type);
|
||||||
for (arg_ast_t *field_ast = def->fields; field_ast; field_ast = field_ast->next) {
|
for (arg_ast_t *field_ast = def->fields; field_ast; field_ast = field_ast->next) {
|
||||||
type_t *field_t = get_arg_ast_type(env, field_ast);
|
type_t *field_t = get_arg_ast_type(env, field_ast);
|
||||||
if ((field_t->tag == StructType && Match(field_t, StructType)->opaque)
|
if ((field_t->tag == StructType && Match(field_t, StructType)->opaque)
|
||||||
@ -133,7 +133,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
type->__data.StructType.opaque = false;
|
type->__data.StructType.opaque = false;
|
||||||
|
|
||||||
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
||||||
Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name)));
|
Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name)));
|
||||||
|
|
||||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
||||||
bind_statement(ns_env, stmt->ast);
|
bind_statement(ns_env, stmt->ast);
|
||||||
@ -147,7 +147,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
|
|
||||||
tag_t *tags = NULL;
|
tag_t *tags = NULL;
|
||||||
type_t *type = Type(EnumType, .name=def->name, .tags=tags, .opaque=true, .env=ns_env); // placeholder
|
type_t *type = Type(EnumType, .name=def->name, .tags=tags, .opaque=true, .env=ns_env); // placeholder
|
||||||
Table_str_set(env->types, def->name, type);
|
Table$str_set(env->types, def->name, type);
|
||||||
for (tag_ast_t *tag_ast = def->tags; tag_ast; tag_ast = tag_ast->next) {
|
for (tag_ast_t *tag_ast = def->tags; tag_ast; tag_ast = tag_ast->next) {
|
||||||
arg_t *fields = NULL;
|
arg_t *fields = NULL;
|
||||||
for (arg_ast_t *field_ast = tag_ast->fields; field_ast; field_ast = field_ast->next) {
|
for (arg_ast_t *field_ast = tag_ast->fields; field_ast; field_ast = field_ast->next) {
|
||||||
@ -173,11 +173,11 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
} else { // Empty singleton value:
|
} else { // Empty singleton value:
|
||||||
set_binding(ns_env, tag->name, new(binding_t, .type=type, .code=CORD_all(env->file_prefix, def->name, "$tagged$", tag->name)));
|
set_binding(ns_env, tag->name, new(binding_t, .type=type, .code=CORD_all(env->file_prefix, def->name, "$tagged$", tag->name)));
|
||||||
}
|
}
|
||||||
Table_str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type);
|
Table$str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
||||||
Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type));
|
Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type));
|
||||||
|
|
||||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
|
||||||
bind_statement(ns_env, stmt->ast);
|
bind_statement(ns_env, stmt->ast);
|
||||||
@ -189,7 +189,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
|
|
||||||
env_t *ns_env = namespace_env(env, def->name);
|
env_t *ns_env = namespace_env(env, def->name);
|
||||||
type_t *type = Type(TextType, .lang=def->name, .env=ns_env);
|
type_t *type = Type(TextType, .lang=def->name, .env=ns_env);
|
||||||
Table_str_set(env->types, def->name, type);
|
Table$str_set(env->types, def->name, type);
|
||||||
|
|
||||||
set_binding(ns_env, "from_unsafe_text",
|
set_binding(ns_env, "from_unsafe_text",
|
||||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
|
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
|
||||||
@ -199,7 +199,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
.code="(Text_t)"));
|
.code="(Text_t)"));
|
||||||
|
|
||||||
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
|
||||||
Table_str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type));
|
Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type));
|
||||||
|
|
||||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||||
bind_statement(ns_env, stmt->ast);
|
bind_statement(ns_env, stmt->ast);
|
||||||
@ -208,14 +208,14 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
case Use: {
|
case Use: {
|
||||||
auto use = Match(statement, Use);
|
auto use = Match(statement, Use);
|
||||||
const char *name = file_base_name(use->raw_path);
|
const char *name = file_base_name(use->raw_path);
|
||||||
if (Table_str_get(*env->imports, name))
|
if (Table$str_get(*env->imports, name))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
env_t *module_env = new_compilation_unit();
|
env_t *module_env = new_compilation_unit();
|
||||||
module_env->file_prefix = heap_strf("%s$", name);
|
module_env->file_prefix = heap_strf("%s$", name);
|
||||||
Table_str_set(module_env->imports, name, module_env);
|
Table$str_set(module_env->imports, name, module_env);
|
||||||
const char *my_name = heap_strn(CORD_to_const_char_star(env->file_prefix), CORD_len(env->file_prefix)-1);
|
const char *my_name = heap_strn(CORD_to_const_char_star(env->file_prefix), CORD_len(env->file_prefix)-1);
|
||||||
Table_str_set(module_env->imports, my_name, env);
|
Table$str_set(module_env->imports, my_name, env);
|
||||||
|
|
||||||
const char *resolved_path = resolve_path(use->raw_path, statement->file->filename, getenv("USE_PATH"));
|
const char *resolved_path = resolve_path(use->raw_path, statement->file->filename, getenv("USE_PATH"));
|
||||||
if (!resolved_path)
|
if (!resolved_path)
|
||||||
@ -230,7 +230,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
|||||||
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
|
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
|
||||||
bind_statement(module_env, stmt->ast);
|
bind_statement(module_env, stmt->ast);
|
||||||
}
|
}
|
||||||
Table_str_set(env->imports, name, module_env);
|
Table$str_set(env->imports, name, module_env);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Extern: {
|
case Extern: {
|
||||||
@ -432,7 +432,7 @@ type_t *get_type(env_t *env, ast_t *ast)
|
|||||||
type_t *fielded_t = get_type(env, access->fielded);
|
type_t *fielded_t = get_type(env, access->fielded);
|
||||||
if (fielded_t->tag == ModuleType) {
|
if (fielded_t->tag == ModuleType) {
|
||||||
const char *name = Match(fielded_t, ModuleType)->name;
|
const char *name = Match(fielded_t, ModuleType)->name;
|
||||||
env_t *module_env = Table_str_get(*env->imports, name);
|
env_t *module_env = Table$str_get(*env->imports, name);
|
||||||
return get_type(module_env, WrapAST(ast, Var, access->field));
|
return get_type(module_env, WrapAST(ast, Var, access->field));
|
||||||
} else if (fielded_t->tag == TypeInfoType) {
|
} else if (fielded_t->tag == TypeInfoType) {
|
||||||
auto info = Match(fielded_t, TypeInfoType);
|
auto info = Match(fielded_t, TypeInfoType);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
#include "environment.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
type_t *parse_type_ast(env_t *env, type_ast_t *ast);
|
type_t *parse_type_ast(env_t *env, type_ast_t *ast);
|
||||||
|
Loading…
Reference in New Issue
Block a user