Change array API to take a padded item size instead of a type info in
most cases
This commit is contained in:
parent
16c2e3f590
commit
167634eaa4
@ -46,14 +46,13 @@ public void Array$compact(array_t *arr, int64_t padded_item_size)
|
||||
};
|
||||
}
|
||||
|
||||
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, int64_t padded_item_size)
|
||||
{
|
||||
if (index <= 0) index = arr->length + index + 1;
|
||||
|
||||
if (index < 1) index = 1;
|
||||
else if (index > (int64_t)arr->length + 1) index = (int64_t)arr->length + 1;
|
||||
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
if (!arr->data) {
|
||||
arr->free = 4;
|
||||
arr->data = arr->atomic ? GC_MALLOC_ATOMIC(arr->free * padded_item_size) : GC_MALLOC(arr->free * padded_item_size);
|
||||
@ -78,14 +77,13 @@ public void Array$insert(array_t *arr, const void *item, int64_t index, const Ty
|
||||
memcpy((void*)arr->data + (index-1)*padded_item_size, item, padded_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, int64_t padded_item_size)
|
||||
{
|
||||
if (index < 1) index = arr->length + index + 1;
|
||||
|
||||
if (index < 1) index = 1;
|
||||
else if (index > (int64_t)arr->length + 1) index = (int64_t)arr->length + 1;
|
||||
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
if (!arr->data) {
|
||||
arr->free = to_insert.length;
|
||||
arr->data = arr->atomic ? GC_MALLOC_ATOMIC(padded_item_size*arr->free) : GC_MALLOC(padded_item_size*arr->free);
|
||||
@ -108,7 +106,7 @@ public void Array$insert_all(array_t *arr, array_t to_insert, int64_t index, con
|
||||
memcpy((void*)arr->data + (index-1 + i)*padded_item_size, to_insert.data + i*to_insert.stride, padded_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, int64_t padded_item_size)
|
||||
{
|
||||
if (index < 1) index = arr->length + index + 1;
|
||||
|
||||
@ -119,7 +117,6 @@ public void Array$remove(array_t *arr, int64_t index, int64_t count, const TypeI
|
||||
|
||||
// TODO: optimize arr.remove(1) by just updating the .data and .length values
|
||||
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
if (index + count > arr->length) {
|
||||
if (arr->free >= 0)
|
||||
arr->free += count;
|
||||
@ -141,25 +138,23 @@ public void Array$remove(array_t *arr, int64_t index, int64_t count, const TypeI
|
||||
arr->length -= count;
|
||||
}
|
||||
|
||||
public void Array$sort(array_t *arr, closure_t comparison, const TypeInfo *type)
|
||||
public void Array$sort(array_t *arr, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
if (arr->data_refcount || (int64_t)arr->stride != padded_item_size)
|
||||
Array$compact(arr, padded_item_size);
|
||||
|
||||
qsort_r(arr->data, arr->length, padded_item_size, comparison.fn, comparison.userdata);
|
||||
}
|
||||
|
||||
public array_t Array$sorted(array_t arr, closure_t comparison, const TypeInfo *type)
|
||||
public array_t Array$sorted(array_t arr, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
arr.data_refcount = 3;
|
||||
Array$sort(&arr, comparison, type);
|
||||
Array$sort(&arr, comparison, padded_item_size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public void Array$shuffle(array_t *arr, const TypeInfo *type)
|
||||
public void Array$shuffle(array_t *arr, int64_t padded_item_size)
|
||||
{
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
if (arr->data_refcount || (int64_t)arr->stride != padded_item_size)
|
||||
Array$compact(arr, padded_item_size);
|
||||
|
||||
@ -180,12 +175,11 @@ public void *Array$random(array_t arr)
|
||||
return arr.data + arr.stride*index;
|
||||
}
|
||||
|
||||
public array_t Array$sample(array_t arr, int64_t n, array_t weights, const TypeInfo *type)
|
||||
public array_t Array$sample(array_t arr, int64_t n, array_t weights, int64_t padded_item_size)
|
||||
{
|
||||
if (arr.length == 0 || n <= 0)
|
||||
return (array_t){};
|
||||
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
array_t selected = {
|
||||
.data=arr.atomic ? GC_MALLOC_ATOMIC(n * padded_item_size) : GC_MALLOC(n * padded_item_size),
|
||||
.length=n,
|
||||
@ -296,13 +290,12 @@ public array_t Array$to(array_t array, int64_t last)
|
||||
};
|
||||
}
|
||||
|
||||
public array_t Array$by(array_t array, int64_t stride, const TypeInfo *type)
|
||||
public array_t Array$by(array_t array, int64_t stride, int64_t padded_item_size)
|
||||
{
|
||||
// In the unlikely event that the stride value would be too large to fit in
|
||||
// a 15-bit integer, fall back to creating a copy of the array:
|
||||
if (__builtin_expect(array.stride*stride < MIN_STRIDE || array.stride*stride > MAX_STRIDE, 0)) {
|
||||
void *copy = NULL;
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
int64_t len = (stride < 0 ? array.length / -stride : array.length / stride) + ((array.length % stride) != 0);
|
||||
if (len > 0) {
|
||||
copy = array.atomic ? GC_MALLOC_ATOMIC(len * padded_item_size) : GC_MALLOC(len * padded_item_size);
|
||||
@ -330,14 +323,14 @@ public array_t Array$by(array_t array, int64_t stride, const TypeInfo *type)
|
||||
};
|
||||
}
|
||||
|
||||
public array_t Array$reversed(array_t array, const TypeInfo *type)
|
||||
public array_t Array$reversed(array_t array, int64_t padded_item_size)
|
||||
{
|
||||
// Just in case negating the stride gives a value that doesn't fit into a
|
||||
// 15-bit integer, fall back to Array$by()'s more general method of copying
|
||||
// the array. This should only happen if array.stride is MIN_STRIDE to
|
||||
// begin with (very unlikely).
|
||||
if (__builtin_expect(-array.stride < MIN_STRIDE || -array.stride > MAX_STRIDE, 0))
|
||||
return Array$by(array, -1, type);
|
||||
return Array$by(array, -1, padded_item_size);
|
||||
|
||||
array_t reversed = array;
|
||||
reversed.stride = -array.stride;
|
||||
@ -345,9 +338,8 @@ public array_t Array$reversed(array_t array, const TypeInfo *type)
|
||||
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, int64_t padded_item_size)
|
||||
{
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
void *data = x.atomic ? GC_MALLOC_ATOMIC(padded_item_size*(x.length + y.length)) : GC_MALLOC(padded_item_size*(x.length + y.length));
|
||||
if (x.stride == padded_item_size) {
|
||||
memcpy(data, x.data, padded_item_size*x.length);
|
||||
@ -393,7 +385,10 @@ public int32_t Array$compare(const array_t *x, const array_t *y, const TypeInfo
|
||||
|
||||
const TypeInfo *item = type->ArrayInfo.item;
|
||||
if (item->tag == PointerInfo || (item->tag == CustomInfo && item->CustomInfo.compare == NULL)) { // data comparison
|
||||
int64_t item_padded_size = get_padded_item_size(type);
|
||||
int64_t item_padded_size = type->ArrayInfo.item->size;
|
||||
if (type->ArrayInfo.item->align > 1 && item_padded_size % type->ArrayInfo.item->align)
|
||||
item_padded_size += type->ArrayInfo.item->align - (item_padded_size % type->ArrayInfo.item->align); // padding
|
||||
|
||||
if ((int64_t)x->stride == item_padded_size && (int64_t)y->stride == item_padded_size && item->size == item_padded_size) {
|
||||
int32_t cmp = (int32_t)memcmp(x->data, y->data, MIN(x->length, y->length)*item_padded_size);
|
||||
if (cmp != 0) return cmp;
|
||||
@ -480,10 +475,9 @@ public uint32_t Array$hash(const array_t *arr, const TypeInfo *type)
|
||||
}
|
||||
}
|
||||
|
||||
static void siftdown(array_t *heap, int64_t startpos, int64_t pos, closure_t comparison, const TypeInfo *type)
|
||||
static void siftdown(array_t *heap, int64_t startpos, int64_t pos, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
assert(pos > 0 && pos < heap->length);
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
char newitem[padded_item_size];
|
||||
memcpy(newitem, heap->data + heap->stride*pos, padded_item_size);
|
||||
while (pos > startpos) {
|
||||
@ -499,13 +493,12 @@ static void siftdown(array_t *heap, int64_t startpos, int64_t pos, closure_t com
|
||||
memcpy(heap->data + heap->stride*pos, newitem, padded_item_size);
|
||||
}
|
||||
|
||||
static void siftup(array_t *heap, int64_t pos, closure_t comparison, const TypeInfo *type)
|
||||
static void siftup(array_t *heap, int64_t pos, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
int64_t endpos = heap->length;
|
||||
int64_t startpos = pos;
|
||||
assert(pos < endpos);
|
||||
|
||||
int64_t padded_item_size = get_padded_item_size(type);
|
||||
char old_top[padded_item_size];
|
||||
memcpy(old_top, heap->data + heap->stride*pos, padded_item_size);
|
||||
// Bubble up the smallest leaf node
|
||||
@ -527,27 +520,25 @@ static void siftup(array_t *heap, int64_t pos, closure_t comparison, const TypeI
|
||||
}
|
||||
memcpy(heap->data + heap->stride*pos, old_top, padded_item_size);
|
||||
// Shift the node's parents down:
|
||||
siftdown(heap, startpos, pos, comparison, type);
|
||||
siftdown(heap, startpos, pos, comparison, padded_item_size);
|
||||
}
|
||||
|
||||
public void Array$heap_push(array_t *heap, const void *item, closure_t comparison, const TypeInfo *type)
|
||||
public void Array$heap_push(array_t *heap, const void *item, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
Array$insert(heap, item, 0, type);
|
||||
Array$insert(heap, item, 0, padded_item_size);
|
||||
|
||||
if (heap->length > 1) {
|
||||
if (heap->data_refcount > 0)
|
||||
Array$compact(heap, get_padded_item_size(type));
|
||||
siftdown(heap, 0, heap->length-1, comparison, type);
|
||||
Array$compact(heap, padded_item_size);
|
||||
siftdown(heap, 0, heap->length-1, comparison, padded_item_size);
|
||||
}
|
||||
}
|
||||
|
||||
public void Array$heap_pop(array_t *heap, void *out, closure_t comparison, const TypeInfo *type)
|
||||
public void Array$heap_pop(array_t *heap, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
if (heap->length == 0)
|
||||
fail("Attempt to pop from an empty array");
|
||||
|
||||
int64_t item_size = type->ArrayInfo.item->size;
|
||||
memcpy(out, heap->data, item_size);
|
||||
if (heap->length == 1) {
|
||||
*heap = (array_t){};
|
||||
} else if (heap->length == 2) {
|
||||
@ -555,22 +546,22 @@ public void Array$heap_pop(array_t *heap, void *out, closure_t comparison, const
|
||||
--heap->length;
|
||||
} else {
|
||||
if (heap->data_refcount > 0)
|
||||
Array$compact(heap, get_padded_item_size(type));
|
||||
memcpy(heap->data, heap->data + heap->stride*(heap->length-1), item_size);
|
||||
Array$compact(heap, padded_item_size);
|
||||
memcpy(heap->data, heap->data + heap->stride*(heap->length-1), padded_item_size);
|
||||
--heap->length;
|
||||
siftup(heap, 0, comparison, type);
|
||||
siftup(heap, 0, comparison, padded_item_size);
|
||||
}
|
||||
}
|
||||
|
||||
public void Array$heapify(array_t *heap, closure_t comparison, const TypeInfo *type)
|
||||
public void Array$heapify(array_t *heap, closure_t comparison, int64_t padded_item_size)
|
||||
{
|
||||
if (heap->data_refcount > 0)
|
||||
Array$compact(heap, get_padded_item_size(type));
|
||||
Array$compact(heap, padded_item_size);
|
||||
|
||||
ARRAY_INCREF(*heap);
|
||||
int64_t i, n = heap->length;
|
||||
for (i = (n >> 1) - 1 ; i >= 0 ; i--)
|
||||
siftup(heap, i, comparison, type);
|
||||
siftup(heap, i, comparison, padded_item_size);
|
||||
ARRAY_DECREF(*heap);
|
||||
}
|
||||
|
||||
|
@ -52,31 +52,31 @@
|
||||
#define ARRAY_INCREF(arr) (arr).data_refcount |= ((arr).data_refcount << 1) | 1
|
||||
#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); })
|
||||
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$remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type);
|
||||
void Array$sort(array_t *arr, closure_t comparison, const TypeInfo *type);
|
||||
array_t Array$sorted(array_t arr, closure_t comparison, const TypeInfo *type);
|
||||
void Array$shuffle(array_t *arr, const TypeInfo *type);
|
||||
#define Array$insert_value(arr, item_expr, index, padded_item_size) ({ __typeof(item_expr) item = item_expr; Array$insert(arr, &item, index, padded_item_size); })
|
||||
void Array$insert(array_t *arr, const void *item, int64_t index, int64_t padded_item_size);
|
||||
void Array$insert_all(array_t *arr, array_t to_insert, int64_t index, int64_t padded_item_size);
|
||||
void Array$remove(array_t *arr, int64_t index, int64_t count, int64_t padded_item_size);
|
||||
void Array$sort(array_t *arr, closure_t comparison, int64_t padded_item_size);
|
||||
array_t Array$sorted(array_t arr, closure_t comparison, int64_t padded_item_size);
|
||||
void Array$shuffle(array_t *arr, int64_t padded_item_size);
|
||||
void *Array$random(array_t arr);
|
||||
array_t Array$sample(array_t arr, int64_t n, array_t weights, const TypeInfo *type);
|
||||
array_t Array$sample(array_t arr, int64_t n, array_t weights, int64_t padded_item_size);
|
||||
void Array$clear(array_t *array);
|
||||
void Array$compact(array_t *arr, int64_t padded_item_size);
|
||||
bool Array$contains(array_t array, void *item, const TypeInfo *type);
|
||||
array_t Array$from(array_t array, int64_t first);
|
||||
array_t Array$to(array_t array, int64_t last);
|
||||
array_t Array$by(array_t array, int64_t stride, const TypeInfo *type);
|
||||
array_t Array$reversed(array_t array, const TypeInfo *type);
|
||||
array_t Array$concat(array_t x, array_t y, const TypeInfo *type);
|
||||
array_t Array$by(array_t array, int64_t stride, int64_t padded_item_size);
|
||||
array_t Array$reversed(array_t array, int64_t padded_item_size);
|
||||
array_t Array$concat(array_t x, array_t y, int64_t padded_item_size);
|
||||
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);
|
||||
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);
|
||||
void Array$heapify(array_t *heap, closure_t comparison, const TypeInfo *type);
|
||||
void Array$heap_push(array_t *heap, const void *item, closure_t comparison, const TypeInfo *type);
|
||||
#define Array$heap_push_value(heap, _value, comparison, typeinfo) ({ __typeof(_value) value = _value; Array$heap_push(heap, &value, comparison, typeinfo); })
|
||||
void Array$heap_pop(array_t *heap, void *out, closure_t comparison, const TypeInfo *type);
|
||||
#define Array$heap_pop_value(heap, comparison, typeinfo, type) ({ type value; Array$heap_pop(heap, &value, comparison, typeinfo); value; })
|
||||
void Array$heapify(array_t *heap, closure_t comparison, int64_t padded_item_size);
|
||||
void Array$heap_push(array_t *heap, const void *item, closure_t comparison, int64_t padded_item_size);
|
||||
#define Array$heap_push_value(heap, _value, comparison, padded_item_size) ({ __typeof(_value) value = _value; Array$heap_push(heap, &value, comparison, padded_item_size); })
|
||||
void Array$heap_pop(array_t *heap, closure_t comparison, int64_t padded_item_size);
|
||||
#define Array$heap_pop_value(heap, comparison, padded_item_size, type) ({ array_t *_heap = heap; type value = *(type*)_heap->data; Array$heap_pop(_heap, comparison, padded_item_size); value; })
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
@ -275,7 +275,7 @@ public void *Table$reserve(table_t *t, const void *key, const void *value, const
|
||||
memcpy(buf + value_offset(type), value, value_size);
|
||||
else
|
||||
memset(buf + value_offset(type), 0, value_size);
|
||||
Array$insert(&t->entries, buf, 0, ENTRIES_TYPE(type));
|
||||
Array$insert(&t->entries, buf, 0, entry_size(type));
|
||||
|
||||
int64_t entry_index = t->entries.length-1;
|
||||
void *entry = GET_ENTRY(*t, entry_index);
|
||||
@ -361,7 +361,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:
|
||||
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, entry_size(type));
|
||||
|
||||
int64_t bucket_to_clear;
|
||||
if (prev) { // Middle (or end) of a chain
|
||||
@ -439,9 +439,9 @@ public int32_t Table$compare(const table_t *x, const table_t *y, const TypeInfo
|
||||
else if (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$sort(&x_entries, (closure_t){.fn=generic_compare, .userdata=(void*)table.key}, table.key);
|
||||
Array$sort(&y_entries, (closure_t){.fn=generic_compare, .userdata=(void*)table.key}, table.key);
|
||||
closure_t cmp = (closure_t){.fn=generic_compare, .userdata=(void*)table.key};
|
||||
array_t x_entries = Array$sorted(x->entries, cmp, entry_size(type));
|
||||
array_t y_entries = Array$sorted(y->entries, cmp, entry_size(type));
|
||||
for (int64_t i = 0; i < x_entries.length; i++) {
|
||||
void *x_key = x_entries.data + x_entries.stride * i;
|
||||
void *y_key = y_entries.data + y_entries.stride * i;
|
||||
|
@ -309,7 +309,7 @@ public array_t Text$clusters(CORD text)
|
||||
char cluster_buf[len+1];
|
||||
strlcpy(cluster_buf, (char*)pos, len+1);
|
||||
CORD cluster = CORD_from_char_star(cluster_buf);
|
||||
Array$insert(&clusters, &cluster, 0, $ArrayInfo(&$Text));
|
||||
Array$insert(&clusters, &cluster, 0, sizeof(CORD));
|
||||
pos = next;
|
||||
}
|
||||
|
||||
|
35
compile.c
35
compile.c
@ -525,18 +525,19 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
||||
if (operand_t->tag == TextType) {
|
||||
return CORD_all(lhs, " = CORD_cat(", lhs, ", ", rhs, ");");
|
||||
} else if (operand_t->tag == ArrayType) {
|
||||
CORD padded_item_size = CORD_asprintf("%ld", padded_type_size(Match(operand_t, ArrayType)->item_type));
|
||||
if (promote(env, &rhs, rhs_t, Match(lhs_t, ArrayType)->item_type)) {
|
||||
// arr ++= item
|
||||
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, ", padded_item_size, ");");
|
||||
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, "), ", padded_item_size, ");");
|
||||
} else {
|
||||
// arr ++= [...]
|
||||
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, ", padded_item_size, ");");
|
||||
else
|
||||
return CORD_all(lhs, "Array$concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ");");
|
||||
return CORD_all(lhs, "Array$concat(", lhs, ", ", rhs, ", ", padded_item_size, ");");
|
||||
}
|
||||
} else {
|
||||
code_err(ast, "'++=' is not implemented for %T types", operand_t);
|
||||
@ -1481,7 +1482,8 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
return CORD_all("CORD_cat(", lhs, ", ", rhs, ")");
|
||||
}
|
||||
case ArrayType: {
|
||||
return CORD_all("Array$concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ")");
|
||||
CORD padded_item_size = CORD_asprintf("%ld", padded_type_size(Match(operand_t, ArrayType)->item_type));
|
||||
return CORD_all("Array$concat(", lhs, ", ", rhs, ", ", padded_item_size, ")");
|
||||
}
|
||||
default:
|
||||
code_err(ast, "Concatenation isn't supported for %T types", operand_t);
|
||||
@ -1833,24 +1835,25 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
case ArrayType: {
|
||||
// TODO: check for readonly
|
||||
type_t *item_t = Match(self_value_t, ArrayType)->item_type;
|
||||
CORD padded_item_size = CORD_asprintf("%ld", padded_type_size(Match(self_value_t, ArrayType)->item_type));
|
||||
if (streq(call->name, "insert")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
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)));
|
||||
return CORD_all("Array$insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||
compile_type_info(env, self_value_t), ")");
|
||||
padded_item_size, ")");
|
||||
} else if (streq(call->name, "insert_all")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
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)));
|
||||
return CORD_all("Array$insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||
compile_type_info(env, self_value_t), ")");
|
||||
padded_item_size, ")");
|
||||
} else if (streq(call->name, "remove")) {
|
||||
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),
|
||||
.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), ", ",
|
||||
compile_type_info(env, self_value_t), ")");
|
||||
padded_item_size, ")");
|
||||
} else if (streq(call->name, "random")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||
(void)compile_arguments(env, ast, NULL, call->args);
|
||||
@ -1861,11 +1864,11 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
.next=new(arg_t, .name="weights", .type=Type(ArrayType, .item_type=Type(NumType, .bits=64)),
|
||||
.default_val=FakeAST(Array, .type=new(type_ast_t, .tag=VarTypeAST, .__data.VarTypeAST.name="Num"))));
|
||||
return CORD_all("Array$sample(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
|
||||
compile_type_info(env, self_value_t), ")");
|
||||
padded_item_size, ")");
|
||||
} else if (streq(call->name, "shuffle")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
(void)compile_arguments(env, ast, NULL, call->args);
|
||||
return CORD_all("Array$shuffle(", self, ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$shuffle(", self, ", ", padded_item_size, ")");
|
||||
} else if (streq(call->name, "sort") || streq(call->name, "sorted")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, streq(call->name, "sort") ? 1 : 0, false);
|
||||
CORD comparison;
|
||||
@ -1878,7 +1881,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
} else {
|
||||
comparison = CORD_all("(closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "}");
|
||||
}
|
||||
return CORD_all("Array$", call->name, "(", self, ", ", comparison, ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$", call->name, "(", self, ", ", comparison, ", ", padded_item_size, ")");
|
||||
} else if (streq(call->name, "heapify")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
CORD comparison;
|
||||
@ -1891,7 +1894,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
} else {
|
||||
comparison = CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})");
|
||||
}
|
||||
return CORD_all("Array$heapify(", self, ", ", comparison, ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$heapify(", self, ", ", comparison, ", ", padded_item_size, ")");
|
||||
} else if (streq(call->name, "heap_push")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
|
||||
@ -1900,7 +1903,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), .type=NewTypeAST(NULL, NULL, NULL, FunctionTypeAST));
|
||||
arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp));
|
||||
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
|
||||
return CORD_all("Array$heap_push_value(", self, ", ", arg_code, ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$heap_push_value(", self, ", ", arg_code, ", ", padded_item_size, ")");
|
||||
} else if (streq(call->name, "heap_pop")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
|
||||
@ -1909,7 +1912,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), .type=NewTypeAST(NULL, NULL, NULL, FunctionTypeAST));
|
||||
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp);
|
||||
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
|
||||
return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", compile_type_info(env, self_value_t), ", ", compile_type(item_t), ")");
|
||||
return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", padded_item_size, ", ", compile_type(item_t), ")");
|
||||
} else if (streq(call->name, "clear")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
|
||||
(void)compile_arguments(env, ast, NULL, call->args);
|
||||
@ -1925,11 +1928,11 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
} else if (streq(call->name, "by")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||
arg_t *arg_spec = new(arg_t, .name="stride", .type=Type(IntType, .bits=64));
|
||||
return CORD_all("Array$by(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$by(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")");
|
||||
} else if (streq(call->name, "reversed")) {
|
||||
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
|
||||
(void)compile_arguments(env, ast, NULL, call->args);
|
||||
return CORD_all("Array$reversed(", self, ", ", compile_type_info(env, self_value_t), ")");
|
||||
return CORD_all("Array$reversed(", self, ", ", padded_item_size, ")");
|
||||
} else code_err(ast, "There is no '%s' method for arrays", call->name);
|
||||
}
|
||||
case TableType: {
|
||||
|
3
repl.c
3
repl.c
@ -482,10 +482,9 @@ void eval(env_t *env, ast_t *ast, void *dest)
|
||||
array_t arr = {};
|
||||
size_t item_size = type_size(Match(t, ArrayType)->item_type);
|
||||
char item_buf[item_size] = {};
|
||||
const TypeInfo *type_info = type_to_type_info(t);
|
||||
for (ast_list_t *item = Match(ast, Array)->items; item; item = item->next) {
|
||||
eval(env, item->ast, item_buf);
|
||||
Array$insert(&arr, item_buf, 0, type_info);
|
||||
Array$insert(&arr, item_buf, 0, padded_type_size(Match(t, ArrayType)->item_type));
|
||||
}
|
||||
memcpy(dest, &arr, sizeof(array_t));
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user