feat: implement environment table for vm
This commit is contained in:
@@ -20,5 +20,6 @@ add_executable(fzc
|
|||||||
# Virtual machine
|
# Virtual machine
|
||||||
add_executable(fz
|
add_executable(fz
|
||||||
src/vm/fzl_vm.c
|
src/vm/fzl_vm.c
|
||||||
|
src/vm/fzl_vm_env.c
|
||||||
src/vm/main.c)
|
src/vm/main.c)
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,7 @@
|
|||||||
#include <compiler/utils/fzl_const_pool.h> // NOTE: move outside compiler scope to common
|
#include <compiler/utils/fzl_const_pool.h> // NOTE: move outside compiler scope to common
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <vm/fzl_vm_env.h>
|
||||||
|
|
||||||
// VM descriptor
|
// VM descriptor
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -26,7 +27,8 @@ typedef struct
|
|||||||
size_t ctop;
|
size_t ctop;
|
||||||
|
|
||||||
// Environment stack
|
// Environment stack
|
||||||
// TODO: implement `estack` and `etop`
|
fzl_vm_env_t estack[256];
|
||||||
|
size_t etop;
|
||||||
} fzl_vm_t;
|
} fzl_vm_t;
|
||||||
|
|
||||||
// Allocate FZL VM
|
// Allocate FZL VM
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef FZL_VM_ENV_H
|
||||||
|
#define FZL_VM_ENV_H
|
||||||
|
|
||||||
|
#include <common/fzl_value.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FZL_VM_ENV_WRESULT_OK,
|
||||||
|
FZL_VM_ENV_WRESULT_ERR,
|
||||||
|
FZL_VM_ENV_WRESULT_ERR_EXISTS,
|
||||||
|
FZL_VM_ENV_WRESULT_ERR_NOT_FOUND
|
||||||
|
} fzl_vm_env_wresult_t;
|
||||||
|
|
||||||
|
// Environment table entry descriptor
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
fzl_value_t value;
|
||||||
|
} fzl_vm_env_entry_t;
|
||||||
|
|
||||||
|
// Environment table descriptor
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
size_t remainder;
|
||||||
|
|
||||||
|
fzl_vm_env_entry_t *table;
|
||||||
|
} fzl_vm_env_t;
|
||||||
|
|
||||||
|
// Allocate env table
|
||||||
|
fzl_vm_env_t *fzl_mkenv();
|
||||||
|
|
||||||
|
// Try get value by name
|
||||||
|
fzl_value_t fzl_env_lookup(fzl_vm_env_t *env, char *name);
|
||||||
|
|
||||||
|
// Check name in env table
|
||||||
|
bool fzl_env_contains(fzl_vm_env_t *env, char *name);
|
||||||
|
|
||||||
|
// Store new value
|
||||||
|
fzl_vm_env_wresult_t fzl_env_storevalue(fzl_vm_env_t *env, char *name,
|
||||||
|
fzl_value_t val);
|
||||||
|
|
||||||
|
// Overwrite existing value
|
||||||
|
fzl_vm_env_wresult_t fzl_env_writevalue(fzl_vm_env_t *env, char *name,
|
||||||
|
fzl_value_t newval);
|
||||||
|
|
||||||
|
// Free env table
|
||||||
|
void fzl_freeenv(fzl_vm_env_t *env);
|
||||||
|
|
||||||
|
#endif // FZL_VM_ENV_H
|
||||||
+11
-17
@@ -29,8 +29,13 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
|||||||
vm->ops = NULL;
|
vm->ops = NULL;
|
||||||
vm->ops_count = 0;
|
vm->ops_count = 0;
|
||||||
vm->ip = 0;
|
vm->ip = 0;
|
||||||
|
vm->dtop = 0;
|
||||||
|
vm->ctop = 0;
|
||||||
|
vm->etop = 0;
|
||||||
|
|
||||||
memset(vm->dstack, 0, sizeof(vm->dstack));
|
memset(vm->dstack, 0, sizeof(vm->dstack));
|
||||||
vm->dtop = 0;
|
memset(vm->cstack, 0, sizeof(vm->cstack));
|
||||||
|
memset(vm->estack, 0, sizeof(vm->estack));
|
||||||
|
|
||||||
FILE *fd = fopen(filepath, "rb");
|
FILE *fd = fopen(filepath, "rb");
|
||||||
if (!fd)
|
if (!fd)
|
||||||
@@ -117,6 +122,11 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
case FZL_OPCODE_MK_ENVTABLE:
|
||||||
|
case FZL_OPCODE_STORE:
|
||||||
|
case FZL_OPCODE_WRITE:
|
||||||
|
break;
|
||||||
|
|
||||||
case FZL_OPCODE_CALL_BUILTIN:
|
case FZL_OPCODE_CALL_BUILTIN:
|
||||||
{
|
{
|
||||||
uint64_t fn_id = vm->ops[++vm->ip];
|
uint64_t fn_id = vm->ops[++vm->ip];
|
||||||
@@ -127,24 +137,8 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
printf("%s\n", arg.as.s.value);
|
printf("%s\n", arg.as.s.value);
|
||||||
else if (arg.type == FZL_TYPE_CHAR)
|
else if (arg.type == FZL_TYPE_CHAR)
|
||||||
printf("%c\n", arg.as.c);
|
printf("%c\n", arg.as.c);
|
||||||
else if (arg.type == FZL_TYPE_INT8)
|
|
||||||
printf("%d\n", arg.as.i8);
|
|
||||||
else if (arg.type == FZL_TYPE_INT16)
|
|
||||||
printf("%d\n", arg.as.i16);
|
|
||||||
else if (arg.type == FZL_TYPE_INT32)
|
|
||||||
printf("%d\n", arg.as.i32);
|
|
||||||
else if (arg.type == FZL_TYPE_INT64)
|
|
||||||
printf("%ld\n", arg.as.i64);
|
|
||||||
else if (arg.type == FZL_TYPE_INT)
|
else if (arg.type == FZL_TYPE_INT)
|
||||||
printf("%ld\n", arg.as.i);
|
printf("%ld\n", arg.as.i);
|
||||||
else if (arg.type == FZL_TYPE_UINT8)
|
|
||||||
printf("%u\n", arg.as.u8);
|
|
||||||
else if (arg.type == FZL_TYPE_UINT16)
|
|
||||||
printf("%u\n", arg.as.u16);
|
|
||||||
else if (arg.type == FZL_TYPE_UINT32)
|
|
||||||
printf("%u\n", arg.as.u32);
|
|
||||||
else if (arg.type == FZL_TYPE_UINT64)
|
|
||||||
printf("%lu\n", arg.as.u64);
|
|
||||||
else if (arg.type == FZL_TYPE_UINT)
|
else if (arg.type == FZL_TYPE_UINT)
|
||||||
printf("%lu\n", arg.as.u);
|
printf("%lu\n", arg.as.u);
|
||||||
else if (arg.type == FZL_TYPE_BOOL)
|
else if (arg.type == FZL_TYPE_BOOL)
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
#include <common/fzl_types.h>
|
||||||
|
#include <common/fzl_value.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vm/fzl_vm_env.h>
|
||||||
|
|
||||||
|
static const fzl_value_t null = {.type = FZL_TYPE_NULL};
|
||||||
|
|
||||||
|
fzl_vm_env_t *fzl_mkenv()
|
||||||
|
{
|
||||||
|
fzl_vm_env_t *env = malloc(sizeof(fzl_vm_env_t));
|
||||||
|
env->remainder = 2;
|
||||||
|
env->size = 0;
|
||||||
|
env->table = malloc(env->remainder * sizeof(fzl_vm_env_entry_t));
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize table if size eq to remainder
|
||||||
|
static void resize_env_if_needed(fzl_vm_env_t *env)
|
||||||
|
{
|
||||||
|
if (env->remainder > env->size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
env->remainder *= 2;
|
||||||
|
env->table = realloc(env->table, env->remainder * sizeof(fzl_vm_env_entry_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_value_t fzl_env_lookup(fzl_vm_env_t *env, char *name)
|
||||||
|
{
|
||||||
|
if (!env)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < env->size; i++)
|
||||||
|
if (strcmp(env->table[i].name, name) == 0)
|
||||||
|
return env->table[i].value;
|
||||||
|
|
||||||
|
return (fzl_value_t){.type = FZL_TYPE_NULL};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fzl_env_contains(fzl_vm_env_t *env, char *name)
|
||||||
|
{
|
||||||
|
if (!env)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < env->size; i++)
|
||||||
|
if (strcmp(env->table[i].name, name) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_vm_env_wresult_t fzl_env_storevalue(fzl_vm_env_t *env, char *name,
|
||||||
|
fzl_value_t val)
|
||||||
|
{
|
||||||
|
if (!env)
|
||||||
|
return FZL_VM_ENV_WRESULT_ERR;
|
||||||
|
|
||||||
|
resize_env_if_needed(env);
|
||||||
|
if (fzl_env_contains(env, name))
|
||||||
|
return FZL_VM_ENV_WRESULT_ERR_EXISTS;
|
||||||
|
|
||||||
|
env->table[env->size] = (fzl_vm_env_entry_t){.name = name, .value = val};
|
||||||
|
|
||||||
|
return FZL_VM_ENV_WRESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_vm_env_wresult_t fzl_env_writevalue(fzl_vm_env_t *env, char *name,
|
||||||
|
fzl_value_t newval)
|
||||||
|
{
|
||||||
|
if (!env)
|
||||||
|
return FZL_VM_ENV_WRESULT_ERR;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < env->size; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(env->table[i].name, name) == 0)
|
||||||
|
{
|
||||||
|
env->table[i].value = newval;
|
||||||
|
return FZL_VM_ENV_WRESULT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FZL_VM_ENV_WRESULT_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fzl_freeenv(fzl_vm_env_t *env)
|
||||||
|
{
|
||||||
|
if (!env)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (env->table)
|
||||||
|
free(env->table);
|
||||||
|
|
||||||
|
free(env);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user