all repos — hex @ 28e9f7eb34fddb835342dd113082b302e1be9451

A tiny, minimalist, slightly-esoteric concatenative programming lannguage.

Changes to memory management in map; minor fixes.
h3rald h3rald@h3rald.com
Wed, 10 Sep 2025 17:27:18 +0200
commit

28e9f7eb34fddb835342dd113082b302e1be9451

parent

ad7bd4bfe43a6167901548d506eca5854f8d5dea

4 files changed, 68 insertions(+), 14 deletions(-)

jump to
M src/hex.csrc/hex.c

@@ -6453,7 +6453,8 @@ return 1;

} else { - hex_item_t **quotation = (hex_item_t **)malloc(list->quotation_size * sizeof(hex_item_t)); + // Allocate result quotation (array of element pointers) + hex_item_t **quotation = (hex_item_t **)malloc(list->quotation_size * sizeof(hex_item_t *)); if (!quotation) { hex_error(ctx, "[symbol map] Memory allocation failed");

@@ -6463,26 +6464,43 @@ return 1;

} for (size_t i = 0; i < list->quotation_size; i++) { - if (hex_push(ctx, list->data.quotation_value[i]) != 0) + // Push a deep copy of the list element to avoid aliasing + hex_item_t *elem_copy = hex_copy_item(ctx, list->data.quotation_value[i]); + if (!elem_copy || hex_push(ctx, elem_copy) != 0) { + if (elem_copy) + hex_free_item(ctx, elem_copy); HEX_FREE(ctx, action); HEX_FREE(ctx, list); hex_free_list(ctx, quotation, i); return 1; } - hex_item_t *act = hex_copy_item(ctx, action); - for (size_t j = 0; j < act->quotation_size; j++) + // Execute action quotation: push deep copies of its elements + for (size_t j = 0; j < action->quotation_size; j++) { - if (hex_push(ctx, act->data.quotation_value[j]) != 0) + hex_item_t *act_elem = hex_copy_item(ctx, action->data.quotation_value[j]); + if (!act_elem || hex_push(ctx, act_elem) != 0) { + if (act_elem) + hex_free_item(ctx, act_elem); HEX_FREE(ctx, action); - HEX_FREE(ctx, act); HEX_FREE(ctx, list); hex_free_list(ctx, quotation, i); return 1; } } - quotation[i] = hex_copy_item(ctx, hex_pop(ctx)); + // Pop result of action execution, copy into result quotation, free temporary + hex_item_t *result_item = hex_pop(ctx); + quotation[i] = hex_copy_item(ctx, result_item); + HEX_FREE(ctx, result_item); + if (!quotation[i]) + { + hex_error(ctx, "[symbol map] Failed to copy result item"); + HEX_FREE(ctx, action); + HEX_FREE(ctx, list); + hex_free_list(ctx, quotation, i); + return 1; + } } if (hex_push_quotation(ctx, quotation, list->quotation_size) != 0) {

@@ -6491,6 +6509,9 @@ HEX_FREE(ctx, list);

hex_free_list(ctx, quotation, list->quotation_size); return 1; } + // Free consumed inputs after success + HEX_FREE(ctx, action); + HEX_FREE(ctx, list); } return 0;
M src/registry.csrc/registry.c

@@ -78,7 +78,9 @@ {

hex_registry_t *registry = ctx->registry; if (!registry) + { return; + } for (size_t i = 0; i < registry->bucket_count; i++) {
M src/stack.csrc/stack.c

@@ -10,7 +10,9 @@ // Free a token

void hex_free_token(hex_token_t *token) { if (token == NULL) + { return; + } if (token->value) {

@@ -253,7 +255,9 @@

void hex_free_list(hex_context_t *ctx, hex_item_t **quotation, size_t size) { if (!quotation) + { return; + } for (size_t i = 0; i < size; i++) {

@@ -271,7 +275,9 @@

void hex_free_item(hex_context_t *ctx, hex_item_t *item) { if (item == NULL) + { return; + } switch (item->type) {
M src/symbols.csrc/symbols.c

@@ -2560,7 +2560,8 @@ return 1;

} else { - hex_item_t **quotation = (hex_item_t **)malloc(list->quotation_size * sizeof(hex_item_t)); + // Allocate result quotation (array of element pointers) + hex_item_t **quotation = (hex_item_t **)malloc(list->quotation_size * sizeof(hex_item_t *)); if (!quotation) { hex_error(ctx, "[symbol map] Memory allocation failed");

@@ -2570,26 +2571,47 @@ return 1;

} for (size_t i = 0; i < list->quotation_size; i++) { - if (hex_push(ctx, list->data.quotation_value[i]) != 0) + // Push a deep copy of the list element to avoid aliasing + hex_item_t *elem_copy = hex_copy_item(ctx, list->data.quotation_value[i]); + if (!elem_copy || hex_push(ctx, elem_copy) != 0) { + if (elem_copy) + { + hex_free_item(ctx, elem_copy); + } HEX_FREE(ctx, action); HEX_FREE(ctx, list); hex_free_list(ctx, quotation, i); return 1; } - hex_item_t *act = hex_copy_item(ctx, action); - for (size_t j = 0; j < act->quotation_size; j++) + // Execute action quotation: push deep copies of its elements + for (size_t j = 0; j < action->quotation_size; j++) { - if (hex_push(ctx, act->data.quotation_value[j]) != 0) + hex_item_t *act_elem = hex_copy_item(ctx, action->data.quotation_value[j]); + if (!act_elem || hex_push(ctx, act_elem) != 0) { + if (act_elem) + { + hex_free_item(ctx, act_elem); + } HEX_FREE(ctx, action); - HEX_FREE(ctx, act); HEX_FREE(ctx, list); hex_free_list(ctx, quotation, i); return 1; } } - quotation[i] = hex_copy_item(ctx, hex_pop(ctx)); + // Pop result of action execution, copy into result quotation, free temporary + hex_item_t *result_item = hex_pop(ctx); + quotation[i] = hex_copy_item(ctx, result_item); + HEX_FREE(ctx, result_item); + if (!quotation[i]) + { + hex_error(ctx, "[symbol map] Failed to copy result item"); + HEX_FREE(ctx, action); + HEX_FREE(ctx, list); + hex_free_list(ctx, quotation, i); + return 1; + } } if (hex_push_quotation(ctx, quotation, list->quotation_size) != 0) {

@@ -2598,6 +2620,9 @@ HEX_FREE(ctx, list);

hex_free_list(ctx, quotation, list->quotation_size); return 1; } + // Free consumed inputs after success + HEX_FREE(ctx, action); + HEX_FREE(ctx, list); } return 0;