From d95ff88b6657862416c5006faa49184ef1b2fe94 Mon Sep 17 00:00:00 2001 From: samsonium Date: Thu, 5 Nov 2026 23:23:38 +0300 Subject: [PATCH] wip: working on extern in VM - Feat: add usage of vm reader instead of old way in vm.c - Ref: update debug opcodes printing --- CMakeLists.txt | 2 + include/vm/fzl_vm.h | 16 +----- src/vm/fzl_vm.c | 102 ++++----------------------------- src/vm/fzl_vm_debug.c | 41 ++++++------- src/vm/fzl_vm_reader.c | 2 + src/vm/handlers/group_and_or.c | 1 + src/vm/handlers/group_cmp.c | 1 + src/vm/handlers/group_ctx.c | 8 +-- src/vm/handlers/group_flow.c | 7 ++- src/vm/handlers/group_fn.c | 3 +- src/vm/handlers/group_math.c | 1 + src/vm/handlers/group_not.c | 1 + src/vm/handlers/group_obj.c | 7 ++- src/vm/handlers/group_objcmp.c | 1 + src/vm/handlers/group_stack.c | 17 +++--- src/vm/handlers/group_str.c | 17 +++++- src/vm/handlers/group_strcmp.c | 1 + src/vm/main.c | 21 ++++++- src/vm/reader/vm_rd_ops.c | 30 ++++++++++ 19 files changed, 133 insertions(+), 146 deletions(-) create mode 100644 src/vm/reader/vm_rd_ops.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ba91cd0..ca6fdf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,9 +165,11 @@ if (NOT FZL_SKIP_VM) src/vm/reader/vm_rd_extern_libs.c src/vm/reader/vm_rd_extern_types.c src/vm/reader/vm_rd_header.c + src/vm/reader/vm_rd_ops.c src/vm/reader/vm_rd_sections_sz.c src/vm/fzl_vm.c src/vm/fzl_vm_env.c + src/vm/fzl_vm_reader.c src/vm/fzl_vm_debug.c src/vm/main.c) diff --git a/include/vm/fzl_vm.h b/include/vm/fzl_vm.h index 45f93f2..49149c0 100644 --- a/include/vm/fzl_vm.h +++ b/include/vm/fzl_vm.h @@ -1,26 +1,16 @@ #ifndef FZL_VM_H #define FZL_VM_H -#include -#include // NOTE: move outside compiler scope to common #include #include #include #include -#include -#include +#include // VM descriptor typedef struct { - fzl_const_t *consts; - size_t consts_count; - - fzl_vm_extern_t *externs; - size_t externs_count; - - uint64_t *ops; - size_t ops_count; + fzl_vm_reader_t *reader; size_t ip; @@ -41,7 +31,7 @@ typedef struct } fzl_vm_t; // Allocate FZL VM -fzl_vm_t *fzl_mkvm(const char *filepath); +fzl_vm_t *fzl_mkvm(fzl_vm_reader_t *reader); // Load and run code int fzl_vm_run(fzl_vm_t *vm); diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index e7fe3c4..bb46ab3 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include char last_err[256]; @@ -20,8 +21,14 @@ size_t total_jmp_on_same = 0; static char *expect_hdr = "FZL\0\2"; -fzl_vm_t *fzl_mkvm(const char *filepath) +fzl_vm_t *fzl_mkvm(fzl_vm_reader_t *reader) { + if (!reader) + { + snprintf(last_err, sizeof(last_err), "reader is not provided"); + return NULL; + } + fzl_vm_t *vm = malloc(sizeof(fzl_vm_t)); if (!vm) { @@ -30,86 +37,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath) } memset(vm, 0, sizeof(fzl_vm_t)); - - FILE *fd = fopen(filepath, "rb"); - if (!fd) - { - snprintf(last_err, sizeof(last_err), "failed to open file '%s'", filepath); - free(vm); - return NULL; - } - - char hdr[5]; - fread(hdr, sizeof(char), 5, - fd); // NOTE: add red bytes check (also for freads below) - if (memcmp(hdr, expect_hdr, 5) != 0) - { - snprintf(last_err, sizeof(last_err), "magic check error"); - fclose(fd); - free(vm); - return NULL; - } - - size_t consts_count, ops_count; - fread(&consts_count, sizeof(size_t), 1, fd); - fread(&ops_count, sizeof(size_t), 1, fd); - // TODO: read externs count - - if (ops_count < 1) - { - snprintf(last_err, sizeof(last_err), "there is nothing to do (0 ops)"); - fclose(fd); - free(vm); - return NULL; - } - - if (consts_count > 0) - { - vm->consts_count = consts_count; - vm->consts = malloc(consts_count * sizeof(fzl_value_t)); - - for (size_t i = 0; i < consts_count; i++) - { - fzl_consttype_t type; - fread(&type, sizeof(fzl_consttype_t), 1, fd); - - if (type == FZL_CONSTTYPE_STRING) - { - size_t length; - char *chars; - - fread(&length, sizeof(size_t), 1, fd); - - chars = malloc(length * sizeof(char) + 1); - fread(chars, sizeof(char), length, fd); - chars[length] = 0; - - vm->consts[i] = (fzl_const_t){ - .type = type, .as.string.length = length, .as.string.chars = chars}; - } - else - { - fclose(fd); - free(vm->consts); - free(vm); - snprintf(last_err, sizeof(last_err), "unknown const type at index %ld", - i); - return NULL; - } - } - } - - vm->ops_count = ops_count; - vm->ops = malloc(ops_count * sizeof(uint64_t)); - for (size_t i = 0; i < ops_count; i++) - { - uint64_t op; - fread(&op, sizeof(uint64_t), 1, fd); - vm->ops[i] = op; - } - - // TODO: read externs - fclose(fd); + vm->reader = reader; return vm; } @@ -229,9 +157,9 @@ int fzl_vm_run(fzl_vm_t *vm) vm->ip = 0; int result = 0; - while (vm->ip < vm->ops_count) + while (vm->ip < vm->reader->ops_count) { - fzl_opcode_t opcode = vm->ops[vm->ip]; + fzl_opcode_t opcode = vm->reader->ops[vm->ip]; size_t op_group = (opcode >> 16) & 0xFF; size_t op_fnnum = (opcode & 0xFF); @@ -265,13 +193,5 @@ void fzl_freevm(fzl_vm_t *vm) while (vm->etop > 0) fzl_freeenv(vm->estack[--vm->etop]); - for (size_t i = 0; i < vm->consts_count; i++) - { - if (vm->consts[i].type == FZL_CONSTTYPE_STRING) - free((void *)vm->consts[i].as.string.chars); - } - - free(vm->consts); - free(vm->ops); free(vm); } diff --git a/src/vm/fzl_vm_debug.c b/src/vm/fzl_vm_debug.c index 40ca17f..0b3334e 100644 --- a/src/vm/fzl_vm_debug.c +++ b/src/vm/fzl_vm_debug.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,36 +9,36 @@ void fzl_vm_print_ops(fzl_vm_t *vm) if (!vm) return; - if (vm->ops_count < 1) + if (vm->reader->ops_count < 1) { printf("no opcodes\n"); return; } - for (size_t i = 0; i < vm->ops_count; i++) + for (size_t i = 0; i < vm->reader->ops_count; i++) { printf("%04ld: ", i); - switch (vm->ops[i]) + switch (vm->reader->ops[i]) { case FZL_OPCODE_STORE_LOCAL: { - size_t depth = vm->ops[++i]; - size_t slot = vm->ops[++i]; + size_t depth = vm->reader->ops[++i]; + size_t slot = vm->reader->ops[++i]; printf("STORE_LOCAL D=%zu S=%zu\n", depth, slot); break; } case FZL_OPCODE_LOAD_LOCAL: { - size_t depth = vm->ops[++i]; - size_t slot = vm->ops[++i]; + size_t depth = vm->reader->ops[++i]; + size_t slot = vm->reader->ops[++i]; printf("LOAD_LOCAL D=%zu S=%zu\n", depth, slot); break; } case FZL_OPCODE_BUILD_STR: - printf("BUILD_STR %zu\n", vm->ops[++i]); + printf("BUILD_STR %zu\n", vm->reader->ops[++i]); break; case FZL_OPCODE_DEREFERENCE: @@ -65,20 +66,20 @@ void fzl_vm_print_ops(fzl_vm_t *vm) break; case FZL_OPCODE_ALLOC_OBJECT: - printf("ALLOC_OBJECT: %lu fields\n", vm->ops[++i]); + printf("ALLOC_OBJECT: %lu fields\n", vm->reader->ops[++i]); break; case FZL_OPCODE_GET_FIELD: - printf("GET_FIELD #%lu\n", vm->ops[++i]); + printf("GET_FIELD #%lu\n", vm->reader->ops[++i]); break; case FZL_OPCODE_SET_FIELD: - printf("SET_FIELD #%lu\n", vm->ops[++i]); + printf("SET_FIELD #%lu\n", vm->reader->ops[++i]); break; case FZL_OPCODE_CALL: { - size_t ip = vm->ops[++i]; + size_t ip = vm->reader->ops[++i]; printf("CALL IP: %lu\n", ip); break; } @@ -89,22 +90,22 @@ void fzl_vm_print_ops(fzl_vm_t *vm) case FZL_OPCODE_LOADCONST: { - size_t const_n = vm->ops[++i]; - fzl_const_t c = vm->consts[const_n]; - printf("LOADCONST #%lu ('%s')\n", const_n, c.as.string.chars); + size_t const_n = vm->reader->ops[++i]; + fzl_value_t c = vm->reader->consts[const_n]; + printf("LOADCONST #%lu ('%s')\n", const_n, c.as.s.value); break; } case FZL_OPCODE_CALL_BUILTIN: - printf("CALL_BUILTIN #%lu\n", vm->ops[++i]); + printf("CALL_BUILTIN #%lu\n", vm->reader->ops[++i]); break; case FZL_OPCODE_PUSHNUM: - printf("PUSHNUM %lu\n", vm->ops[++i]); + printf("PUSHNUM %lu\n", vm->reader->ops[++i]); break; case FZL_OPCODE_PUSHBOOL: - printf("PUSHBOOL %s\n", vm->ops[++i] ? "true" : "false"); + printf("PUSHBOOL %s\n", vm->reader->ops[++i] ? "true" : "false"); break; case FZL_OPCODE_MK_ENVTABLE: @@ -177,11 +178,11 @@ void fzl_vm_print_ops(fzl_vm_t *vm) break; case FZL_OPCODE_JZ: - printf("JZ IP: %ld\n", vm->ops[++i]); + printf("JZ IP: %ld\n", vm->reader->ops[++i]); break; case FZL_OPCODE_JMP: - printf("JMP IP: %ld\n", vm->ops[++i]); + printf("JMP IP: %ld\n", vm->reader->ops[++i]); break; } } diff --git a/src/vm/fzl_vm_reader.c b/src/vm/fzl_vm_reader.c index b093b2c..09bbdbe 100644 --- a/src/vm/fzl_vm_reader.c +++ b/src/vm/fzl_vm_reader.c @@ -112,6 +112,8 @@ bool fzl_vm_read(fzl_vm_reader_t *reader) return false; } + fclose(fd); + return true; } diff --git a/src/vm/handlers/group_and_or.c b/src/vm/handlers/group_and_or.c index a1febf2..59bf5a6 100644 --- a/src/vm/handlers/group_and_or.c +++ b/src/vm/handlers/group_and_or.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/vm/handlers/group_cmp.c b/src/vm/handlers/group_cmp.c index 672687e..22ce748 100644 --- a/src/vm/handlers/group_cmp.c +++ b/src/vm/handlers/group_cmp.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/vm/handlers/group_ctx.c b/src/vm/handlers/group_ctx.c index 251035c..5e8de86 100644 --- a/src/vm/handlers/group_ctx.c +++ b/src/vm/handlers/group_ctx.c @@ -132,8 +132,8 @@ int op_write(fzl_vm_t *vm) int op_load_local(fzl_vm_t *vm) { - size_t depth = vm->ops[++vm->ip]; - size_t slot = vm->ops[++vm->ip]; + size_t depth = vm->reader->ops[++vm->ip]; + size_t slot = vm->reader->ops[++vm->ip]; if (depth >= vm->etop) { @@ -168,8 +168,8 @@ int op_store_local(fzl_vm_t *vm) fzl_value_t value = vm->dstack[--vm->dtop]; - size_t depth = vm->ops[++vm->ip]; - size_t slot = vm->ops[++vm->ip]; + size_t depth = vm->reader->ops[++vm->ip]; + size_t slot = vm->reader->ops[++vm->ip]; if (depth >= vm->etop) { diff --git a/src/vm/handlers/group_flow.c b/src/vm/handlers/group_flow.c index 0f1f02d..5a2ae20 100644 --- a/src/vm/handlers/group_flow.c +++ b/src/vm/handlers/group_flow.c @@ -1,16 +1,17 @@ +#include #include #include // Jump at specified address int op_jmp(fzl_vm_t *vm) { - if (vm->ops_count <= vm->ip) + if (vm->reader->ops_count <= vm->ip) { snprintf(last_err, sizeof(last_err), "runtime error - expected JMP addr"); return -1; } - uint64_t jmp_ip = vm->ops[++vm->ip]; + uint64_t jmp_ip = vm->reader->ops[++vm->ip]; if (!vm->allow_infinite) { if (jmp_ip == last_jmp_ip) @@ -46,7 +47,7 @@ int op_jz(fzl_vm_t *vm) } fzl_value_t jzval = vm->dstack[--vm->dtop]; - uint64_t jzip = vm->ops[++vm->ip] - 1; + uint64_t jzip = vm->reader->ops[++vm->ip] - 1; if (jzval.as.b == 0) vm->ip = jzip; diff --git a/src/vm/handlers/group_fn.c b/src/vm/handlers/group_fn.c index 72bb884..9d1c35e 100644 --- a/src/vm/handlers/group_fn.c +++ b/src/vm/handlers/group_fn.c @@ -1,10 +1,11 @@ +#include #include #include // Call function (store return address and jump into function init) int op_call(fzl_vm_t *vm) { - uint64_t ip = vm->ops[++vm->ip]; + uint64_t ip = vm->reader->ops[++vm->ip]; vm->cstack[vm->ctop++] = vm->ip; vm->ip = ip - 1; return 0; diff --git a/src/vm/handlers/group_math.c b/src/vm/handlers/group_math.c index d746366..100ff94 100644 --- a/src/vm/handlers/group_math.c +++ b/src/vm/handlers/group_math.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/vm/handlers/group_not.c b/src/vm/handlers/group_not.c index ab88558..c22521b 100644 --- a/src/vm/handlers/group_not.c +++ b/src/vm/handlers/group_not.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/vm/handlers/group_obj.c b/src/vm/handlers/group_obj.c index d090305..ce9ef02 100644 --- a/src/vm/handlers/group_obj.c +++ b/src/vm/handlers/group_obj.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -57,7 +58,7 @@ void escape_recursive(fzl_vm_env_t *current, fzl_vm_env_t *parent, // Allocate specified count of fields and create object int op_alloc_object(fzl_vm_t *vm) { - uint64_t values_count = vm->ops[++vm->ip]; + uint64_t values_count = vm->reader->ops[++vm->ip]; fzl_vm_object_t *obj = malloc(sizeof(fzl_vm_object_t)); if (values_count < 1) @@ -94,7 +95,7 @@ int op_get_field(fzl_vm_t *vm) return -1; } - uint64_t field_slot = vm->ops[++vm->ip]; + uint64_t field_slot = vm->reader->ops[++vm->ip]; fzl_value_t val = vm->dstack[--vm->dtop]; if (val.type != FZL_TYPE_OBJECT) { @@ -130,7 +131,7 @@ int op_set_field(fzl_vm_t *vm) return -1; } - uint64_t field_slot = vm->ops[++vm->ip]; + uint64_t field_slot = vm->reader->ops[++vm->ip]; fzl_value_t objval = vm->dstack[--vm->dtop]; fzl_value_t wrval = vm->dstack[--vm->dtop]; if (objval.type != FZL_TYPE_OBJECT) diff --git a/src/vm/handlers/group_objcmp.c b/src/vm/handlers/group_objcmp.c index 671bcbd..bc07582 100644 --- a/src/vm/handlers/group_objcmp.c +++ b/src/vm/handlers/group_objcmp.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/vm/handlers/group_stack.c b/src/vm/handlers/group_stack.c index 4b60bd8..e93f70f 100644 --- a/src/vm/handlers/group_stack.c +++ b/src/vm/handlers/group_stack.c @@ -1,21 +1,20 @@ #include +#include +#include #include #include // Load constant onto stack int op_loadconst(fzl_vm_t *vm) { - uint64_t cn = vm->ops[++vm->ip]; - if (vm->consts_count <= cn) + uint64_t cn = vm->reader->ops[++vm->ip]; + if (vm->reader->consts_count <= cn) { snprintf(last_err, sizeof(last_err), "runtime error - unknown const"); print_err_data(vm); return -1; } - fzl_const_t c = vm->consts[cn]; - vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_STRING, - .as.s.length = c.as.string.length, - .as.s.value = c.as.string.chars}; + vm->dstack[vm->dtop++] = vm->reader->consts[cn]; return 0; } @@ -23,7 +22,7 @@ int op_loadconst(fzl_vm_t *vm) // Call builtin function int op_call_builtin(fzl_vm_t *vm) { - uint64_t fn_id = vm->ops[++vm->ip]; + uint64_t fn_id = vm->reader->ops[++vm->ip]; if (fn_id == FZL_BUILTIN_PRINTLINE) { fzl_value_t arg = vm->dstack[--vm->dtop]; @@ -64,7 +63,7 @@ int op_call_builtin(fzl_vm_t *vm) // Push number onto stack int op_pushnum(fzl_vm_t *vm) { - uint64_t push_n = vm->ops[++vm->ip]; + uint64_t push_n = vm->reader->ops[++vm->ip]; vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_UINT, .as.u = push_n}; return 0; } @@ -72,7 +71,7 @@ int op_pushnum(fzl_vm_t *vm) // Push boolean onto stack int op_pushbool(fzl_vm_t *vm) { - uint64_t push_b = vm->ops[++vm->ip]; + uint64_t push_b = vm->reader->ops[++vm->ip]; vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_BOOL, .as.b = push_b}; return 0; } diff --git a/src/vm/handlers/group_str.c b/src/vm/handlers/group_str.c index aada897..68bc1b9 100644 --- a/src/vm/handlers/group_str.c +++ b/src/vm/handlers/group_str.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -8,7 +10,7 @@ char build_result[512]; // Build string from specified count using stack values int op_build_str(fzl_vm_t *vm) { - uint64_t n = vm->ops[++vm->ip]; + uint64_t n = vm->reader->ops[++vm->ip]; if (vm->dtop < n) { snprintf(last_err, sizeof(last_err), @@ -34,6 +36,19 @@ int op_build_str(fzl_vm_t *vm) switch (val.type) { + case FZL_TYPE_HANDLE: + snprintf(temp, sizeof(temp), "pointer<%p>", val.as.obj); + strcpy(build_result + gi, temp); + gi += strlen(temp); + break; + + case FZL_TYPE_STRUCT: + snprintf(temp, sizeof(temp), "field(values: %zu)", + ((fzl_extern_type_t *)val.as.obj)->structure.fields_count); + strcpy(build_result + gi, temp); + gi += strlen(temp); + break; + case FZL_TYPE_UINT: snprintf(temp, sizeof(temp), "%zu", val.as.u); strcpy(build_result + gi, temp); diff --git a/src/vm/handlers/group_strcmp.c b/src/vm/handlers/group_strcmp.c index 50dffb1..aa11b08 100644 --- a/src/vm/handlers/group_strcmp.c +++ b/src/vm/handlers/group_strcmp.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/src/vm/main.c b/src/vm/main.c index b8f2530..8f91556 100644 --- a/src/vm/main.c +++ b/src/vm/main.c @@ -6,6 +6,7 @@ #include #include #include +#include typedef struct { @@ -113,10 +114,28 @@ int main(int argc, char **argv) return 0; } - fzl_vm_t *vm = fzl_mkvm(args->filepath); + fzl_vm_reader_t *reader = fzl_vm_mkreader(args->filepath); + if (!reader) + { + printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_getreadererror()); + free(args); + return -1; + } + + bool result = fzl_vm_read(reader); + if (!result) + { + printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_getreadererror()); + fzl_vm_freereader(reader); + free(args); + return -1; + } + + fzl_vm_t *vm = fzl_mkvm(reader); if (!vm) { printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_geterror()); + fzl_vm_freereader(reader); free(args); return -1; } diff --git a/src/vm/reader/vm_rd_ops.c b/src/vm/reader/vm_rd_ops.c new file mode 100644 index 0000000..9e5938c --- /dev/null +++ b/src/vm/reader/vm_rd_ops.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +// Read opcodes +bool vm_rd_ops(fzl_vm_reader_t *reader, FILE *fd) +{ + if (!reader || !fd) + return false; + + size_t ops_count = reader->ops_count; + if (!ops_count) + return false; + + reader->ops = malloc(sizeof(size_t) * ops_count); + if (!reader->ops) + return false; + + for (size_t i = 0; i < ops_count; i++) + { + size_t opcode; + if (!vm_rd_word(fd, 1, &opcode)) + return false; + + reader->ops[i] = opcode; + } + + return true; +}