RAII #2
@@ -30,9 +30,6 @@ typedef struct
|
|||||||
// Environment stack
|
// Environment stack
|
||||||
fzl_vm_env_t *estack[256];
|
fzl_vm_env_t *estack[256];
|
||||||
size_t etop;
|
size_t etop;
|
||||||
|
|
||||||
fzl_vm_object_t *objects[256];
|
|
||||||
size_t objects_count;
|
|
||||||
} fzl_vm_t;
|
} fzl_vm_t;
|
||||||
|
|
||||||
// Allocate FZL VM
|
// Allocate FZL VM
|
||||||
|
|||||||
+99
-63
@@ -25,20 +25,18 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm->consts = NULL;
|
vm->consts = NULL;
|
||||||
vm->consts_count = 0;
|
vm->consts_count = 0;
|
||||||
vm->ops = NULL;
|
vm->ops = NULL;
|
||||||
vm->ops_count = 0;
|
vm->ops_count = 0;
|
||||||
vm->ip = 0;
|
vm->ip = 0;
|
||||||
vm->dtop = 0;
|
vm->dtop = 0;
|
||||||
vm->ctop = 0;
|
vm->ctop = 0;
|
||||||
vm->etop = 0;
|
vm->etop = 0;
|
||||||
vm->objects_count = 0;
|
|
||||||
|
|
||||||
memset(vm->dstack, 0, sizeof(vm->dstack));
|
memset(vm->dstack, 0, sizeof(vm->dstack));
|
||||||
memset(vm->cstack, 0, sizeof(vm->cstack));
|
memset(vm->cstack, 0, sizeof(vm->cstack));
|
||||||
memset(vm->estack, 0, sizeof(vm->estack));
|
memset(vm->estack, 0, sizeof(vm->estack));
|
||||||
memset(vm->objects, 0, sizeof(vm->objects));
|
|
||||||
|
|
||||||
FILE *fd = fopen(filepath, "rb");
|
FILE *fd = fopen(filepath, "rb");
|
||||||
if (!fd)
|
if (!fd)
|
||||||
@@ -110,6 +108,57 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
|||||||
return vm;
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Escape objects with nested objects check
|
||||||
|
static void escape_recursive(fzl_vm_env_t *current, fzl_vm_env_t *parent,
|
||||||
|
fzl_vm_object_t *obj)
|
||||||
|
{
|
||||||
|
if (!current || !parent || !obj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool found_in_current = false;
|
||||||
|
for (size_t i = 0; i < current->owned_objects_count; i++)
|
||||||
|
{
|
||||||
|
if (current->owned_objects[i] == obj)
|
||||||
|
{
|
||||||
|
current->owned_objects[i] = NULL;
|
||||||
|
found_in_current = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_in_current)
|
||||||
|
{
|
||||||
|
bool found_in_parent = false;
|
||||||
|
for (size_t i = 0; i < parent->owned_objects_count; i++)
|
||||||
|
{
|
||||||
|
if (parent->owned_objects[i] == obj)
|
||||||
|
{
|
||||||
|
found_in_parent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_in_parent)
|
||||||
|
{
|
||||||
|
if (parent->owned_objects_remainder <= parent->owned_objects_count)
|
||||||
|
{
|
||||||
|
parent->owned_objects_remainder *= 2;
|
||||||
|
parent->owned_objects =
|
||||||
|
realloc(parent->owned_objects, parent->owned_objects_remainder *
|
||||||
|
sizeof(fzl_vm_object_t *));
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->owned_objects[parent->owned_objects_count++] = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < obj->values_count; i++)
|
||||||
|
{
|
||||||
|
if (obj->values[i].type == FZL_TYPE_OBJECT && obj->values[i].as.obj != NULL)
|
||||||
|
escape_recursive(current, parent, obj->values[i].as.obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_object(fzl_vm_object_t *obj)
|
void print_object(fzl_vm_object_t *obj)
|
||||||
{
|
{
|
||||||
if (!obj)
|
if (!obj)
|
||||||
@@ -153,25 +202,32 @@ void print_err_data(fzl_vm_t *vm)
|
|||||||
printf("> Caused on IP: %zu\n", vm->ip);
|
printf("> Caused on IP: %zu\n", vm->ip);
|
||||||
|
|
||||||
printf("\n> Data stack:\n");
|
printf("\n> Data stack:\n");
|
||||||
for (ssize_t i = vm->dtop - 1; i >= 0; i--)
|
if (vm->dtop > 0)
|
||||||
{
|
{
|
||||||
printf("\t> [%d] ", vm->dstack[i].type);
|
for (ssize_t i = vm->dtop - 1; i >= 0; i--)
|
||||||
switch (vm->dstack[i].type)
|
|
||||||
{
|
{
|
||||||
case FZL_TYPE_OBJECT:
|
printf("\t> [%d] ", vm->dstack[i].type);
|
||||||
printf("ref: %p\n", vm->dstack[i].as.obj);
|
switch (vm->dstack[i].type)
|
||||||
break;
|
{
|
||||||
case FZL_TYPE_STRING:
|
case FZL_TYPE_OBJECT:
|
||||||
printf("str: '%s'\n", vm->dstack[i].as.s.value);
|
printf("ref: %p\n", vm->dstack[i].as.obj);
|
||||||
break;
|
break;
|
||||||
case FZL_TYPE_NULL:
|
case FZL_TYPE_STRING:
|
||||||
printf("<null>\n");
|
printf("str: '%s'\n", vm->dstack[i].as.s.value);
|
||||||
break;
|
break;
|
||||||
default:
|
case FZL_TYPE_NULL:
|
||||||
printf("%lu\n", vm->dstack[i].as.u);
|
printf("<null>\n");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
printf("%lu\n", vm->dstack[i].as.u);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\tEmpty\n");
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n> Environments:\n");
|
printf("\n> Environments:\n");
|
||||||
for (ssize_t i = vm->etop - 1; i >= 0; i--)
|
for (ssize_t i = vm->etop - 1; i >= 0; i--)
|
||||||
@@ -187,8 +243,20 @@ void print_err_data(fzl_vm_t *vm)
|
|||||||
|
|
||||||
printf("\t\t> Local entries (%zu/%zu):\n", env->size, env->remainder);
|
printf("\t\t> Local entries (%zu/%zu):\n", env->size, env->remainder);
|
||||||
for (size_t j = 0; j < env->size; j++)
|
for (size_t j = 0; j < env->size; j++)
|
||||||
printf("\t\t\t> [%d] %s = %lu\n", env->table[j].value.type,
|
{
|
||||||
env->table[j].name, env->table[j].value.as.u);
|
switch (env->table[j].value.type)
|
||||||
|
{
|
||||||
|
case FZL_TYPE_OBJECT:
|
||||||
|
printf("\t\t\t> [%d] %s = ref %p\n", env->table[j].value.type,
|
||||||
|
env->table[j].name, env->table[j].value.as.obj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("\t\t\t> [%d] %s = %lu\n", env->table[j].value.type,
|
||||||
|
env->table[j].name, env->table[j].value.as.u);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n> Call stack:\n");
|
printf("\n> Call stack:\n");
|
||||||
@@ -260,7 +328,7 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
fzl_value_t right = vm->dstack[--vm->dtop];
|
fzl_value_t right = vm->dstack[--vm->dtop];
|
||||||
|
|
||||||
vm->dstack[vm->dtop++] = (fzl_value_t){
|
vm->dstack[vm->dtop++] = (fzl_value_t){
|
||||||
.type = FZL_TYPE_BOOL, .as.b = &left.as.obj == &right.as.obj};
|
.type = FZL_TYPE_BOOL, .as.b = left.as.obj == right.as.obj};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,11 +345,10 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
fzl_value_t right = vm->dstack[--vm->dtop];
|
fzl_value_t right = vm->dstack[--vm->dtop];
|
||||||
|
|
||||||
vm->dstack[vm->dtop++] = (fzl_value_t){
|
vm->dstack[vm->dtop++] = (fzl_value_t){
|
||||||
.type = FZL_TYPE_BOOL, .as.b = &left.as.obj != &right.as.obj};
|
.type = FZL_TYPE_BOOL, .as.b = left.as.obj != right.as.obj};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: make recursive owning transfer for nested objects!
|
|
||||||
case FZL_OPCODE_ESCAPE_OBJECT:
|
case FZL_OPCODE_ESCAPE_OBJECT:
|
||||||
{
|
{
|
||||||
if (vm->dtop < 1)
|
if (vm->dtop < 1)
|
||||||
@@ -302,7 +369,7 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
|
|
||||||
fzl_vm_env_t *parent = vm->estack[vm->etop - 2];
|
fzl_vm_env_t *parent = vm->estack[vm->etop - 2];
|
||||||
fzl_vm_env_t *current = vm->estack[vm->etop - 1];
|
fzl_vm_env_t *current = vm->estack[vm->etop - 1];
|
||||||
if (!parent || vm->etop < 2)
|
if (vm->etop < 2)
|
||||||
{
|
{
|
||||||
snprintf(last_err, sizeof(last_err),
|
snprintf(last_err, sizeof(last_err),
|
||||||
"runtime error - cannot escape object from global env");
|
"runtime error - cannot escape object from global env");
|
||||||
@@ -310,32 +377,7 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
escape_recursive(current, parent, obj.as.obj);
|
||||||
if (obj.as.u != 0)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < current->owned_objects_count; i++)
|
|
||||||
{
|
|
||||||
if (obj.as.obj == current->owned_objects[i])
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
current->owned_objects[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
if (parent->owned_objects_remainder <= parent->owned_objects_count)
|
|
||||||
{
|
|
||||||
parent->owned_objects_remainder *= 2;
|
|
||||||
parent->owned_objects =
|
|
||||||
realloc(parent->owned_objects, parent->owned_objects_remainder *
|
|
||||||
sizeof(fzl_vm_object_t *));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent->owned_objects[parent->owned_objects_count++] = obj.as.obj;
|
|
||||||
}
|
|
||||||
vm->dstack[vm->dtop++] = obj;
|
vm->dstack[vm->dtop++] = obj;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -900,12 +942,6 @@ void fzl_freevm(fzl_vm_t *vm)
|
|||||||
free((void *)vm->consts[i].as.string.chars);
|
free((void *)vm->consts[i].as.string.chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < vm->objects_count; i++)
|
|
||||||
{
|
|
||||||
free(vm->objects[i]->values);
|
|
||||||
free(vm->objects[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(vm->consts);
|
free(vm->consts);
|
||||||
free(vm->ops);
|
free(vm->ops);
|
||||||
free(vm);
|
free(vm);
|
||||||
|
|||||||
+3
-1
@@ -109,7 +109,9 @@ void fzl_freeenv(fzl_vm_env_t *env)
|
|||||||
if (!env->owned_objects[i])
|
if (!env->owned_objects[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
free(env->owned_objects[i]->values);
|
if (env->owned_objects[i]->values)
|
||||||
|
free(env->owned_objects[i]->values);
|
||||||
|
|
||||||
free(env->owned_objects[i]);
|
free(env->owned_objects[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user