Add list type, obj_free for compound types, and self-reference guard

- Implement OBJ_LIST with offset-based items array and capacity
- obj_free now releases child allocations (string buffer, list items)
- obj_print detects self-referencing lists to prevent infinite recursion
- Visualizer distinguishes freed blocks (JLANG_NOT_USE) from active ones
- JLANG_free now zeroes payload on release
This commit is contained in:
Jose Luis Montañes Ojados
2026-02-16 00:33:02 +01:00
parent 13c9d052a0
commit d14227efeb
3 changed files with 97 additions and 35 deletions

View File

@@ -1,24 +1,32 @@
#include "objects/object.h"
int main() {
// Creamos un allocator
JLANG_memory_allocator *allocPtr = JLANG_CreateAllocator();
printf("allocatorPtr=%p\n", allocPtr);
printf("memoryPtr=%p\n", allocPtr->memory);
printf("size=%zu\n", allocPtr->size);
size_t stringVar1 = obj_new_string(allocPtr, "Hello world!");
size_t floatVar1 = obj_new_float(allocPtr, 3.14);
size_t listVar1 = obj_new_list(allocPtr, 3);
Object *list = (Object *)JLANG_RESOLVE(allocPtr, listVar1);
size_t stringVar1 = obj_new_string(allocPtr, "\nHello world!\n");
obj_print(allocPtr, stringVar1);
size_t *items = (size_t *)JLANG_RESOLVE(allocPtr, list->data.list_val.items);
items[0] = floatVar1;
items[1] = stringVar1;
items[2] = listVar1;
obj_print(allocPtr, listVar1, "");
obj_free(allocPtr, stringVar1);
stringVar1 = obj_new_string(allocPtr, "Hola Mundo!");
items[1] = stringVar1;
items[2] = stringVar1;
obj_print(allocPtr, listVar1, "");
JLANG_visualize(allocPtr);
// obj_free(allocPtr, stringVar1);
for (int i = 0; i < 20; i++) {
obj_new_string(allocPtr, "FFFFFFFFFFFFFF");
}
obj_print(allocPtr, stringVar1);
JLANG_visualize(allocPtr);
return 0;
}

View File

@@ -14,6 +14,7 @@
#define JLANG_FREE 0
#define JLANG_HEADER 1
#define JLANG_PAYLOAD 2
#define JLANG_NOT_USE 3
/*
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si
@@ -144,6 +145,9 @@ void JLANG_free(void *ptr, size_t blockOffset) {
// Set block as not_used
blockHeader->in_use = 0;
// Set to 0 payload
memset(blockPtr, 0, blockHeader->size);
}
/*
@@ -181,6 +185,7 @@ void JLANG_visualize(void *ptr) {
*/
if (currentHeader->size > 0) {
if (currentHeader->in_use == 1) {
byteMapPtr[blockIndex] = JLANG_HEADER;
for (int i = 0; i < sizeof(JLANG_metadata); i++) {
byteMapPtr[blockIndex + i] = JLANG_HEADER;
@@ -192,6 +197,10 @@ void JLANG_visualize(void *ptr) {
for (int i = 0; i < currentHeader->size; i++) {
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
}
} else {
// Mark all block as JLANG_NOT_USE
memset(byteMapPtr + blockIndex, JLANG_NOT_USE, sizeof(JLANG_metadata) + currentHeader->size);
}
} else {
break;
}
@@ -223,6 +232,9 @@ void JLANG_visualize(void *ptr) {
case JLANG_FREE:
printf("\033[32m");
break;
case JLANG_NOT_USE:
printf("\033[47;5;224m");
break;
default:
printf("\033[41m");
break;

View File

@@ -15,7 +15,7 @@ typedef struct Object {
int length;
} string_val;
struct {
struct Object **items;
size_t items;
int count;
int capacity;
} list_val;
@@ -58,22 +58,39 @@ size_t obj_new_string(void *allocator, const char *str) {
return offset;
}
size_t obj_new_list(void *allocator) {
size_t obj_new_list(void *allocator, int capacity) {
size_t offset = JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->type = OBJ_LIST;
size_t itemsOffset = JLANG_malloc(allocator, capacity * sizeof(size_t));
// Re-resolver por si malloc disparó grow
objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->data.list_val.capacity = capacity;
objPtr->data.list_val.items = itemsOffset;
objPtr->data.list_val.count = 0;
return offset;
}
void obj_list_append(void *allocator, size_t offset) {}
void obj_free(void *allocator, size_t offset) {
// if (obj->type == OBJ_STRING) {
// JLANG_free(allocator, obj->data.string_val.chars);
// }
Object *obj = (Object *)JLANG_RESOLVE(allocator, offset);
if (obj->type == OBJ_STRING) {
JLANG_free(allocator, obj->data.string_val.chars);
}
if (obj->type == OBJ_LIST) {
JLANG_free(allocator, obj->data.list_val.items);
}
JLANG_free(allocator, offset);
}
void obj_print(void *allocator, size_t offset) {
void obj_print(void *allocator, size_t offset, const char *preffix) {
Object *obj = (Object *)JLANG_RESOLVE(allocator, offset);
switch (obj->type) {
@@ -83,15 +100,40 @@ void obj_print(void *allocator, size_t offset) {
case OBJ_FLOAT:
printf("%f", obj->data.float_val);
break;
// case OBJ_LIST:
// for (int i = 0; i < obj->data.list_val.count; i++) {
// obj_print(obj->data.list_val.items[i]);
// }
// break;
case OBJ_LIST: {
// Iterate items
size_t *items =
(size_t *)JLANG_RESOLVE(allocator, obj->data.list_val.items);
printf("[");
for (int i = 0; i < obj->data.list_val.capacity; i++) {
// Check if the item is the list itself
if (items[i] == offset) {
printf("<self:0x%zu>", offset);
} else {
obj_print(allocator, items[i], "\"");
}
if (i < obj->data.list_val.capacity - 1) {
printf(", ");
}
}
printf("]\n");
break;
}
case OBJ_STRING:
if (strcmp(preffix, "") != 0) {
printf("%s", preffix);
}
printf("%s", (char *)JLANG_RESOLVE(allocator, obj->data.string_val.chars));
if (strcmp(preffix, "") != 0) {
printf("%s", preffix);
}
break;
default:
break;
}
};
}