Skip to content

Commit

Permalink
repeat( array, or expr, number of times) works, up to certain limits.
Browse files Browse the repository at this point in the history
  • Loading branch information
reginaldford committed Sep 3, 2024
1 parent b736941 commit 8f297c5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 18 deletions.
103 changes: 87 additions & 16 deletions src/main/engine/sm_ast_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,23 +559,94 @@ inline sm_object *sm_engine_eval(sm_object *input, sm_cx *current_cx, sm_expr *s
break;
}
case SM_REPEAT_EXPR: {
sm_expr *list0 = (sm_expr *)eager_type_check(sme, 0, SM_EXPR_TYPE, current_cx, sf);
if (list0->my_type == SM_ERR_TYPE)
return (sm_object *)list0;
sm_f64 *reps = (sm_f64 *)eager_type_check(sme, 1, SM_F64_TYPE, current_cx, sf);
if (reps->my_type == SM_ERR_TYPE)
return (sm_object *)reps;
f64 repetitions = reps->value;
int original_size = list0->size;
int new_size = (int)(original_size * repetitions);
sm_expr *new_tuple = sm_new_expr_n(SM_TUPLE_EXPR, new_size, new_size, NULL);
for (int i = 0; i < new_size; i++) {
int original_index = i % original_size;
sm_object *element = sm_expr_get_arg(list0, original_index);
sm_expr_set_arg(new_tuple, i, element);
sm_expr *obj =
(sm_expr *)eager_type_check2(sme, 0, SM_EXPR_TYPE, SM_ARRAY_TYPE, current_cx, sf);
if (!obj || obj->my_type == SM_ERR_TYPE)
return (sm_object *)obj;

sm_f64 *repeat_count_obj = (sm_f64 *)eager_type_check(sme, 1, SM_F64_TYPE, current_cx, sf);
if (!repeat_count_obj || repeat_count_obj->my_type == SM_ERR_TYPE)
return (sm_object *)repeat_count_obj;
uint32_t repeat_count = (uint32_t)repeat_count_obj->value;

if (repeat_count == 0)
return (obj->my_type == SM_EXPR_TYPE)
? (sm_object *)sm_new_expr_n(((sm_expr *)obj)->op, 0, 0, NULL)
: (sm_object *)sm_new_array(((sm_array *)obj)->inner_type, 0, NULL,
sizeof(sm_space));

switch (obj->my_type) {
case SM_EXPR_TYPE: {
sm_expr *arr = (sm_expr *)obj;
uint32_t new_size = arr->size * repeat_count;
sm_expr *result_expr = sm_new_expr_n(arr->op, new_size, new_size, NULL);
if (!result_expr)
return (sm_object *)sm_new_error_from_strings(
sm_new_symbol("MemoryError", 10),
sm_new_string(44, "Failed to allocate memory for repeated tuple"), NULL, 0, NULL);

// Repeating the expression arguments
for (uint32_t i = 0; i < repeat_count; i++) {
for (uint32_t j = 0; j < arr->size; j++) {
sm_object *arg = sm_expr_get_arg(arr, j);
if (!arg)
return (sm_object *)sm_new_error_from_strings(
sm_new_symbol("InvalidMemoryAccess", 19),
sm_new_string(40, "Invalid memory access during repetition"), NULL, 0, NULL);
sm_expr_set_arg(result_expr, i * arr->size + j, arg);
}
}
return (sm_object *)result_expr;
}
case SM_ARRAY_TYPE: {
sm_array *arr = (sm_array *)obj;
uint32_t element_size = (arr->inner_type == SM_UI8_TYPE) ? sizeof(ui8) : sizeof(f64);
uint32_t new_size = arr->size * repeat_count * element_size;
sm_space *new_space = sm_new_space(new_size);
if (!new_space)
return (sm_object *)sm_new_error_from_strings(
sm_new_symbol("MemoryError", 10),
sm_new_string(44, "Failed to allocate memory for repeated array"), NULL, 0, NULL);

void *src_data, *dst_data = (char *)(new_space + 1); // Start of data after sm_space header
switch (arr->inner_type) {
case SM_F64_TYPE:
src_data = sm_f64_array_get_start(arr); // Get pointer to actual f64 data
if (!src_data)
return (sm_object *)sm_new_error_from_strings(
sm_new_symbol("InvalidMemoryAccess", 19),
sm_new_string(27, "Invalid f64 array access"), NULL, 0, NULL);
for (uint32_t i = 0; i < repeat_count; i++)
memcpy((char *)dst_data + i * arr->size * sizeof(f64), src_data,
arr->size * sizeof(f64));
break;
case SM_UI8_TYPE:
src_data = sm_ui8_array_get_start(arr); // Get pointer to actual ui8 data
if (!src_data)
return (sm_object *)sm_new_error_from_strings(
sm_new_symbol("InvalidMemoryAccess", 19),
sm_new_string(27, "Invalid ui8 array access"), NULL, 0, NULL);
for (uint32_t i = 0; i < repeat_count; i++)
memcpy((char *)dst_data + i * arr->size * sizeof(ui8), src_data,
arr->size * sizeof(ui8));
break;
default: {
sm_symbol *title = sm_new_symbol("arrayTypeUnknownError", 19);
sm_string *message =
sm_new_fstring_at(sms_heap, "Unsupported array inner type %i", (int)arr->inner_type);
return (sm_object *)sm_new_error_from_expr(title, message, sme, NULL);
}
}
return (sm_object *)sm_new_array(arr->inner_type, new_size / element_size,
(sm_object *)new_space, sizeof(sm_space));
}
default: {
sm_symbol *title = sm_new_symbol("invalidExpressionType", 19);
sm_string *message =
sm_new_fstring_at(sms_heap, "Invalid expression type %i", (int)obj->my_type);
return (sm_object *)sm_new_error_from_expr(title, message, sme, NULL);
}
}
return (sm_object *)new_tuple;
break;
}
case SM_CAT_EXPR: {
sm_expr *list0 = (sm_expr *)eager_type_check(sme, 0, SM_EXPR_TYPE, current_cx, sf);
Expand Down
2 changes: 1 addition & 1 deletion src/main/object/sm_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ uint32_t sm_ui8_array_contents_sprint(sm_array *array, char *buffer, bool fake)
return 0;
uint32_t cursor = 0;
uint32_t i = 0;
char tmp[20];
char tmp[array->size];
if (fake)
buffer = tmp;
for (; i + 1 < array->size; i++) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/sm_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern uint32_t sms_num_symbols;

void sm_init(sm_env *env, int num_args, char **argv) {
// Set version number. Major.Minor.Patch
char *sms_version = "0.21.34";
char *sms_version = "0.21.35";
int sms_version_len = 7;
sm_strncpy(env->version, sms_version, sms_version_len);
env->version_len = sms_version_len;
Expand Down

0 comments on commit 8f297c5

Please sign in to comment.