Files
fz-lang/src/vm/handlers/group_ctx.c
T
samsonium d95ff88b66 wip: working on extern in VM
- Feat: add usage of vm reader instead of old way in vm.c
- Ref: update debug opcodes printing
2026-11-05 23:23:38 +03:00

203 lines
4.6 KiB
C

#include "common/fzl_types.h"
#include <common/fzl_value.h>
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/fzl_vm_env.h>
#include <vm/internals/opcode.h>
// Allocate environment table and increment scope level
int op_mk_envtable(fzl_vm_t *vm)
{
vm->estack[vm->etop++] = fzl_mkenv();
return 0;
}
// Remove environment table and decrement scope level
int op_rm_envtable(fzl_vm_t *vm)
{
fzl_freeenv(vm->estack[--vm->etop]);
return 0;
}
// Store new variable
int op_store(fzl_vm_t *vm)
{
if (vm->dtop < 1)
{
snprintf(last_err, sizeof(last_err),
"runtime error - expected var name in data stack");
print_err_data(vm);
return -1;
}
fzl_value_t varname = vm->dstack[--vm->dtop];
fzl_env_storevalue(vm->estack[vm->etop - 1], (char *)varname.as.s.value,
(fzl_value_t){});
return 0;
}
// Lookup environment(s) for variable using name on stack
int op_lookup_env(fzl_vm_t *vm)
{
if (vm->dtop < 1)
{
snprintf(last_err, sizeof(last_err),
"runtime error - LOOKUP_ENV: empty data stack");
print_err_data(vm);
return -1;
}
fzl_value_t val = vm->dstack[--vm->dtop];
fzl_value_t env_val;
bool result;
for (ssize_t i = vm->etop - 1; i >= 0; i--)
{
if ((result =
fzl_env_lookup(vm->estack[i], (char *)val.as.s.value, &env_val)))
break;
}
vm->dstack[vm->dtop++] = env_val;
return 0;
}
// Writable variable value
int op_write(fzl_vm_t *vm)
{
if (vm->dtop < 2)
{
snprintf(last_err, sizeof(last_err),
"runtime error - expected 2 values in data stack");
print_err_data(vm);
return -1;
}
fzl_value_t writevar = vm->dstack[--vm->dtop];
fzl_value_t value = vm->dstack[--vm->dtop];
char *wrname = (char *)writevar.as.s.value;
bool wrfound;
fzl_value_t wrenv;
ssize_t wrlvl = -1;
for (ssize_t i = vm->etop - 1; i >= 0; i--)
{
if ((wrfound = fzl_env_lookup(vm->estack[i], wrname, &wrenv)))
{
wrlvl = i;
break;
}
}
if (wrlvl <= -1)
{
snprintf(last_err, sizeof(last_err),
"runtime error - name '%s' not found in this scope", wrname);
print_err_data(vm);
return -1;
}
fzl_vm_env_wresult_t wresult =
fzl_env_writevalue(vm->estack[wrlvl], (char *)wrname, value);
if (wresult != FZL_VM_ENV_WRESULT_OK)
{
switch (wresult)
{
case FZL_VM_ENV_WRESULT_ERR:
snprintf(last_err, sizeof(last_err),
"runtime error - failed to write variable");
print_err_data(vm);
return -1;
case FZL_VM_ENV_WRESULT_ERR_EXISTS:
snprintf(last_err, sizeof(last_err),
"runtime error - redefenition of '%s'", writevar.as.s.value);
print_err_data(vm);
return -1;
case FZL_VM_ENV_WRESULT_ERR_NOT_FOUND:
snprintf(last_err, sizeof(last_err),
"runtime error - cannot find name '%s'", writevar.as.s.value);
print_err_data(vm);
return -1;
default:
print_err_data(vm);
return -1;
}
}
return 0;
}
int op_load_local(fzl_vm_t *vm)
{
size_t depth = vm->reader->ops[++vm->ip];
size_t slot = vm->reader->ops[++vm->ip];
if (depth >= vm->etop)
{
snprintf(last_err, sizeof(last_err),
"runtime error - local depth out of range");
print_err_data(vm);
return -1;
}
fzl_vm_env_t *env = vm->estack[vm->etop - 1 - depth];
if (env->size <= slot)
{
snprintf(last_err, sizeof(last_err),
"runtime error - local slot out of range");
print_err_data(vm);
return -1;
}
vm->dstack[vm->dtop++] = env->table[slot].value;
return 0;
}
int op_store_local(fzl_vm_t *vm)
{
if (vm->dtop < 1)
{
snprintf(last_err, sizeof(last_err),
"runtime error - expected value in data stack");
print_err_data(vm);
return -1;
}
fzl_value_t value = vm->dstack[--vm->dtop];
size_t depth = vm->reader->ops[++vm->ip];
size_t slot = vm->reader->ops[++vm->ip];
if (depth >= vm->etop)
{
snprintf(last_err, sizeof(last_err),
"runtime error - local depth out of range");
print_err_data(vm);
return -1;
}
fzl_vm_env_t *env = vm->estack[vm->etop - 1 - depth];
if (env->size <= slot)
{
snprintf(last_err, sizeof(last_err),
"runtime error - local slot out of range");
print_err_data(vm);
return -1;
}
if (value.type == FZL_TYPE_OBJECT && depth != 0)
{
for (size_t i = 0; i < depth; i++)
{
escape_recursive(vm->estack[vm->etop - i], vm->estack[vm->etop - 1 - i],
value.as.obj);
}
}
env->table[slot].value = value;
return 0;
}