aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-23 13:24:06 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-23 13:24:06 -0500
commit9f56266ae4a2d458576821d74906ab5bc4498b5b (patch)
tree19cd055dd1020af788896132e6905bec4b59697f
parent9aec32149fae328d73ee4816bc12e56c65327cbf (diff)
Implement Array__concat and ++=
-rw-r--r--builtins/array.c27
-rw-r--r--builtins/array.h1
-rw-r--r--compile.c12
3 files changed, 37 insertions, 3 deletions
diff --git a/builtins/array.c b/builtins/array.c
index a615a806..4f9070fe 100644
--- a/builtins/array.c
+++ b/builtins/array.c
@@ -228,6 +228,33 @@ public array_t Array__slice(array_t *array, int64_t first, int64_t stride, int64
};
}
+array_t Array__concat(array_t *x, array_t *y, const TypeInfo *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));
+ if (x->stride == item_size) {
+ memcpy(data, x->data, item_size*x->length);
+ } else {
+ for (int64_t i = 0; i < x->length; i++)
+ memcpy(data + i*item_size, x->data + i*item_size, item_size);
+ }
+
+ if (y->stride == item_size) {
+ memcpy(data + item_size*x->length, y->data, item_size*y->length);
+ } else {
+ for (int64_t i = 0; i < x->length; i++)
+ memcpy(data + (x->length + i)*item_size, y->data + i*item_size, item_size);
+ }
+
+ return (array_t){
+ .data=data,
+ .length=x->length + y->length,
+ .stride=item_size,
+ .copy_on_write=0,
+ .atomic=x->atomic,
+ };
+}
+
public bool Array__contains(array_t array, void *item, const TypeInfo *type)
{
TypeInfo *item_type = type->ArrayInfo.item;
diff --git a/builtins/array.h b/builtins/array.h
index 65b7028c..5a4b29ab 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -32,6 +32,7 @@ void Array__clear(array_t *array, const TypeInfo *type);
void Array__compact(array_t *arr, 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 stride, int64_t length, bool readonly, 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);
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);
diff --git a/compile.c b/compile.c
index 8db7240a..06908801 100644
--- a/compile.c
+++ b/compile.c
@@ -314,9 +314,7 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("CORD_cat(", lhs, ", ", rhs, ")");
}
case ArrayType: {
- return CORD_all("({ array_t $joined = ", lhs, ", $rhs = ", rhs, ";\n"
- "Array__insert_all(&$joined, $rhs, 0, ", compile_type_info(env, operand_t), ");\n"
- "$joined; })");
+ return CORD_all("Array__concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ")");
}
default:
code_err(ast, "Concatenation isn't supported for %T types", operand_t);
@@ -375,6 +373,14 @@ CORD compile(env_t *env, ast_t *ast)
code_err(ast, "'or=' is not implemented for %T types", operand_t);
}
case BINOP_XOR: return CORD_asprintf("%r ^= %r;", lhs, rhs);
+ case BINOP_CONCAT: {
+ if (operand_t->tag == StringType)
+ return CORD_asprintf("%r = CORD_cat(%r, %r);", lhs, lhs, rhs);
+ else if (operand_t->tag == ArrayType)
+ return CORD_all(lhs, "Array__concat(", lhs, ", ", rhs, ", ", compile_type_info(env, operand_t), ")");
+ else
+ code_err(ast, "'++=' is not implemented for %T types", operand_t);
+ }
default: code_err(ast, "Update assignments are not implemented for this operation");
}
}