diff --git a/CMakeLists.txt b/CMakeLists.txt index 8231649..a70597c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -project(fun VERSION 0.2.1 LANGUAGES C) +project(fun VERSION 0.2.2 LANGUAGES C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/examples/objects_more.fun b/examples/objects_more.fun old mode 100644 new mode 100755 diff --git a/src/vm.c b/src/vm.c index 7998125..38d972c 100644 --- a/src/vm.c +++ b/src/vm.c @@ -193,69 +193,78 @@ void vm_run(VM *vm, Bytecode *entry) { switch (inst.op) { /* All opcode handlers as .c includes */ - #include "vm_cases/core/vm_case_nop.c" - #include "vm_cases/core/vm_case_load_const.c" - #include "vm_cases/core/vm_case_load_local.c" - #include "vm_cases/core/vm_case_store_local.c" - #include "vm_cases/arithmetic/vm_case_add.c" - #include "vm_cases/arithmetic/vm_case_sub.c" - #include "vm_case_mul.c" - #include "vm_case_div.c" - #include "vm_case_lt.c" - #include "vm_case_lte.c" - #include "vm_cases/core/vm_case_jump.c" - #include "vm_case_gt.c" - #include "vm_case_gte.c" - #include "vm_cases/logic/vm_case_eq.c" - #include "vm_case_neq.c" - #include "vm_cases/core/vm_case_jump_if_false.c" - #include "vm_case_call.c" - #include "vm_case_return.c" - #include "vm_case_print.c" - #include "vm_cases/core/vm_case_halt.c" - #include "vm_case_pop.c" - #include "vm_case_dup.c" - #include "vm_case_swap.c" - #include "vm_case_make_array.c" - #include "vm_case_index_get.c" - #include "vm_case_index_set.c" - #include "vm_case_len.c" - #include "vm_case_arr_push.c" - #include "vm_case_arr_pop.c" - #include "vm_case_arr_set.c" - #include "vm_case_arr_insert.c" - #include "vm_case_arr_remove.c" - #include "vm_case_slice.c" - #include "vm_case_to_number.c" - #include "vm_case_to_string.c" - #include "vm_case_split.c" - #include "vm_case_join.c" - #include "vm_case_substr.c" - #include "vm_case_find.c" - #include "vm_case_contains.c" - #include "vm_case_index_of.c" - #include "vm_case_clear.c" - #include "vm_case_enumerate.c" - #include "vm_case_zip.c" - #include "vm_case_min.c" - #include "vm_case_max.c" - #include "vm_case_clamp.c" - #include "vm_case_abs.c" - #include "vm_case_pow.c" - #include "vm_case_random_seed.c" - #include "vm_case_random_int.c" - #include "vm_case_make_map.c" - #include "vm_case_keys.c" - #include "vm_case_values.c" - #include "vm_case_has_key.c" - #include "vm_case_read_file.c" - #include "vm_case_write_file.c" - #include "vm_case_load_global.c" - #include "vm_case_store_global.c" - #include "vm_case_mod.c" - #include "vm_case_and.c" - #include "vm_case_or.c" - #include "vm_case_not.c" + #include "vm/arithmetic/add.c" + #include "vm/arithmetic/div.c" + #include "vm/arithmetic/mul.c" + #include "vm/arithmetic/sub.c" + + #include "vm/arrays/arr_insert.c" + #include "vm/arrays/arr_pop.c" + #include "vm/arrays/arr_push.c" + #include "vm/arrays/arr_remove.c" + #include "vm/arrays/arr_set.c" + #include "vm/arrays/clear.c" + #include "vm/arrays/contains.c" + #include "vm/arrays/enumerate.c" + #include "vm/arrays/index_get.c" + #include "vm/arrays/index_of.c" + #include "vm/arrays/index_set.c" + #include "vm/arrays/join.c" + #include "vm/arrays/make_array.c" + #include "vm/arrays/slice.c" + #include "vm/arrays/zip.c" + + #include "vm/core/call.c" + #include "vm/core/dup.c" + #include "vm/core/halt.c" + #include "vm/core/jump.c" + #include "vm/core/jump_if_false.c" + #include "vm/core/load_const.c" + #include "vm/core/load_global.c" + #include "vm/core/load_local.c" + #include "vm/core/nop.c" + #include "vm/core/pop.c" + #include "vm/core/return.c" + #include "vm/core/store_global.c" + #include "vm/core/store_local.c" + #include "vm/core/swap.c" + + #include "vm/io/read_file.c" + #include "vm/io/write_file.c" + + #include "vm/logic/and.c" + #include "vm/logic/eq.c" + #include "vm/logic/gt.c" + #include "vm/logic/gte.c" + #include "vm/logic/lt.c" + #include "vm/logic/lte.c" + #include "vm/logic/neq.c" + #include "vm/logic/not.c" + #include "vm/logic/or.c" + + #include "vm/maps/has_key.c" + #include "vm/maps/keys.c" + #include "vm/maps/make_map.c" + #include "vm/maps/values.c" + + #include "vm/math/abs.c" + #include "vm/math/clamp.c" + #include "vm/math/max.c" + #include "vm/math/min.c" + #include "vm/math/mod.c" + #include "vm/math/pow.c" + #include "vm/math/random_int.c" + #include "vm/math/random_seed.c" + + #include "vm/strings/find.c" + #include "vm/strings/split.c" + #include "vm/strings/substr.c" + + #include "vm/len.c" + #include "vm/print.c" + #include "vm/to_number.c" + #include "vm/to_string.c" + default: if (!opcode_is_valid(inst.op)) { fprintf(stderr, "Runtime error: unknown opcode %d (%s) at instruction %d\n", diff --git a/src/vm_cases/arithmetic/vm_case_add.c b/src/vm/arithmetic/add.c similarity index 100% rename from src/vm_cases/arithmetic/vm_case_add.c rename to src/vm/arithmetic/add.c diff --git a/src/vm_case_div.c b/src/vm/arithmetic/div.c similarity index 100% rename from src/vm_case_div.c rename to src/vm/arithmetic/div.c diff --git a/src/vm_case_mul.c b/src/vm/arithmetic/mul.c similarity index 100% rename from src/vm_case_mul.c rename to src/vm/arithmetic/mul.c diff --git a/src/vm_cases/arithmetic/vm_case_sub.c b/src/vm/arithmetic/sub.c similarity index 100% rename from src/vm_cases/arithmetic/vm_case_sub.c rename to src/vm/arithmetic/sub.c diff --git a/src/vm_case_arr_insert.c b/src/vm/arrays/arr_insert.c similarity index 100% rename from src/vm_case_arr_insert.c rename to src/vm/arrays/arr_insert.c diff --git a/src/vm_case_arr_pop.c b/src/vm/arrays/arr_pop.c similarity index 100% rename from src/vm_case_arr_pop.c rename to src/vm/arrays/arr_pop.c diff --git a/src/vm_case_arr_push.c b/src/vm/arrays/arr_push.c similarity index 100% rename from src/vm_case_arr_push.c rename to src/vm/arrays/arr_push.c diff --git a/src/vm_case_arr_remove.c b/src/vm/arrays/arr_remove.c similarity index 100% rename from src/vm_case_arr_remove.c rename to src/vm/arrays/arr_remove.c diff --git a/src/vm_case_arr_set.c b/src/vm/arrays/arr_set.c similarity index 100% rename from src/vm_case_arr_set.c rename to src/vm/arrays/arr_set.c diff --git a/src/vm_case_clear.c b/src/vm/arrays/clear.c similarity index 100% rename from src/vm_case_clear.c rename to src/vm/arrays/clear.c diff --git a/src/vm_case_contains.c b/src/vm/arrays/contains.c similarity index 100% rename from src/vm_case_contains.c rename to src/vm/arrays/contains.c diff --git a/src/vm_case_enumerate.c b/src/vm/arrays/enumerate.c similarity index 100% rename from src/vm_case_enumerate.c rename to src/vm/arrays/enumerate.c diff --git a/src/vm_case_index_get.c b/src/vm/arrays/index_get.c similarity index 97% rename from src/vm_case_index_get.c rename to src/vm/arrays/index_get.c index 71c194d..eae25e7 100644 --- a/src/vm_case_index_get.c +++ b/src/vm/arrays/index_get.c @@ -18,7 +18,6 @@ case OP_INDEX_GET: { if (idx.type != VAL_STRING) { fprintf(stderr, "INDEX_GET key must be string for map\n"); exit(1); } Value out; if (!map_get_copy(&container, idx.s ? idx.s : "", &out)) { - /* missing -> nil */ out = make_nil(); } free_value(container); diff --git a/src/vm_case_index_of.c b/src/vm/arrays/index_of.c similarity index 100% rename from src/vm_case_index_of.c rename to src/vm/arrays/index_of.c diff --git a/src/vm_case_index_set.c b/src/vm/arrays/index_set.c similarity index 97% rename from src/vm_case_index_set.c rename to src/vm/arrays/index_set.c index 24f3e77..ce5785b 100644 --- a/src/vm_case_index_set.c +++ b/src/vm/arrays/index_set.c @@ -11,7 +11,6 @@ case OP_INDEX_SET: { if (!array_set(&container, (int)idx.i, v)) { fprintf(stderr, "Runtime error: index out of range\n"); exit(1); } - /* v moved into array */ free_value(container); free_value(idx); } else if (container.type == VAL_MAP) { diff --git a/src/vm_case_join.c b/src/vm/arrays/join.c similarity index 100% rename from src/vm_case_join.c rename to src/vm/arrays/join.c diff --git a/src/vm_case_make_array.c b/src/vm/arrays/make_array.c similarity index 100% rename from src/vm_case_make_array.c rename to src/vm/arrays/make_array.c diff --git a/src/vm_case_slice.c b/src/vm/arrays/slice.c similarity index 100% rename from src/vm_case_slice.c rename to src/vm/arrays/slice.c diff --git a/src/vm_case_zip.c b/src/vm/arrays/zip.c similarity index 100% rename from src/vm_case_zip.c rename to src/vm/arrays/zip.c diff --git a/src/vm_case_call.c b/src/vm/core/call.c similarity index 100% rename from src/vm_case_call.c rename to src/vm/core/call.c diff --git a/src/vm_case_dup.c b/src/vm/core/dup.c similarity index 100% rename from src/vm_case_dup.c rename to src/vm/core/dup.c diff --git a/src/vm_cases/core/vm_case_halt.c b/src/vm/core/halt.c similarity index 100% rename from src/vm_cases/core/vm_case_halt.c rename to src/vm/core/halt.c diff --git a/src/vm_cases/core/vm_case_jump.c b/src/vm/core/jump.c similarity index 100% rename from src/vm_cases/core/vm_case_jump.c rename to src/vm/core/jump.c diff --git a/src/vm_cases/core/vm_case_jump_if_false.c b/src/vm/core/jump_if_false.c similarity index 100% rename from src/vm_cases/core/vm_case_jump_if_false.c rename to src/vm/core/jump_if_false.c diff --git a/src/vm_cases/core/vm_case_load_const.c b/src/vm/core/load_const.c similarity index 100% rename from src/vm_cases/core/vm_case_load_const.c rename to src/vm/core/load_const.c diff --git a/src/vm_case_load_global.c b/src/vm/core/load_global.c similarity index 100% rename from src/vm_case_load_global.c rename to src/vm/core/load_global.c diff --git a/src/vm_cases/core/vm_case_load_local.c b/src/vm/core/load_local.c similarity index 100% rename from src/vm_cases/core/vm_case_load_local.c rename to src/vm/core/load_local.c diff --git a/src/vm_cases/core/vm_case_nop.c b/src/vm/core/nop.c similarity index 100% rename from src/vm_cases/core/vm_case_nop.c rename to src/vm/core/nop.c diff --git a/src/vm_case_pop.c b/src/vm/core/pop.c similarity index 79% rename from src/vm_case_pop.c rename to src/vm/core/pop.c index 5ef72d4..d2d9fd3 100644 --- a/src/vm_case_pop.c +++ b/src/vm/core/pop.c @@ -4,6 +4,6 @@ case OP_POP: { exit(1); } Value v = pop_value(vm); - free_value(v); // free the popped value + free_value(v); break; } diff --git a/src/vm/core/return.c b/src/vm/core/return.c new file mode 100644 index 0000000..c0c28ae --- /dev/null +++ b/src/vm/core/return.c @@ -0,0 +1,8 @@ +case OP_RETURN: { + Value retv; + if (vm->sp >= 0) retv = pop_value(vm); + else retv = make_nil(); + vm_pop_frame(vm); + push_value(vm, retv); + break; +} diff --git a/src/vm_case_store_global.c b/src/vm/core/store_global.c similarity index 100% rename from src/vm_case_store_global.c rename to src/vm/core/store_global.c diff --git a/src/vm_cases/core/vm_case_store_local.c b/src/vm/core/store_local.c similarity index 100% rename from src/vm_cases/core/vm_case_store_local.c rename to src/vm/core/store_local.c diff --git a/src/vm_case_swap.c b/src/vm/core/swap.c similarity index 100% rename from src/vm_case_swap.c rename to src/vm/core/swap.c diff --git a/src/vm_case_read_file.c b/src/vm/io/read_file.c similarity index 100% rename from src/vm_case_read_file.c rename to src/vm/io/read_file.c diff --git a/src/vm_case_write_file.c b/src/vm/io/write_file.c similarity index 100% rename from src/vm_case_write_file.c rename to src/vm/io/write_file.c diff --git a/src/vm_case_len.c b/src/vm/len.c similarity index 100% rename from src/vm_case_len.c rename to src/vm/len.c diff --git a/src/vm_case_and.c b/src/vm/logic/and.c similarity index 100% rename from src/vm_case_and.c rename to src/vm/logic/and.c diff --git a/src/vm_cases/logic/vm_case_eq.c b/src/vm/logic/eq.c similarity index 100% rename from src/vm_cases/logic/vm_case_eq.c rename to src/vm/logic/eq.c diff --git a/src/vm_case_gt.c b/src/vm/logic/gt.c similarity index 100% rename from src/vm_case_gt.c rename to src/vm/logic/gt.c diff --git a/src/vm_case_gte.c b/src/vm/logic/gte.c similarity index 100% rename from src/vm_case_gte.c rename to src/vm/logic/gte.c diff --git a/src/vm_case_lt.c b/src/vm/logic/lt.c similarity index 100% rename from src/vm_case_lt.c rename to src/vm/logic/lt.c diff --git a/src/vm_case_lte.c b/src/vm/logic/lte.c similarity index 100% rename from src/vm_case_lte.c rename to src/vm/logic/lte.c diff --git a/src/vm_case_neq.c b/src/vm/logic/neq.c similarity index 100% rename from src/vm_case_neq.c rename to src/vm/logic/neq.c diff --git a/src/vm_case_not.c b/src/vm/logic/not.c similarity index 100% rename from src/vm_case_not.c rename to src/vm/logic/not.c diff --git a/src/vm_case_or.c b/src/vm/logic/or.c similarity index 100% rename from src/vm_case_or.c rename to src/vm/logic/or.c diff --git a/src/vm_case_has_key.c b/src/vm/maps/has_key.c similarity index 100% rename from src/vm_case_has_key.c rename to src/vm/maps/has_key.c diff --git a/src/vm_case_keys.c b/src/vm/maps/keys.c similarity index 100% rename from src/vm_case_keys.c rename to src/vm/maps/keys.c diff --git a/src/vm_case_make_map.c b/src/vm/maps/make_map.c similarity index 94% rename from src/vm_case_make_map.c rename to src/vm/maps/make_map.c index ca79961..8b4df69 100644 --- a/src/vm_case_make_map.c +++ b/src/vm/maps/make_map.c @@ -10,7 +10,6 @@ case OP_MAKE_MAP: { fprintf(stderr, "Map literal set failed\n"); exit(1); } free_value(key); - /* val ownership moved */ } push_value(vm, m); break; diff --git a/src/vm_case_values.c b/src/vm/maps/values.c similarity index 100% rename from src/vm_case_values.c rename to src/vm/maps/values.c diff --git a/src/vm_case_abs.c b/src/vm/math/abs.c similarity index 100% rename from src/vm_case_abs.c rename to src/vm/math/abs.c diff --git a/src/vm_case_clamp.c b/src/vm/math/clamp.c similarity index 67% rename from src/vm_case_clamp.c rename to src/vm/math/clamp.c index cdca05e..1fc0489 100644 --- a/src/vm_case_clamp.c +++ b/src/vm/math/clamp.c @@ -2,11 +2,16 @@ case OP_CLAMP: { Value hi = pop_value(vm); Value lo = pop_value(vm); Value x = pop_value(vm); - if (x.type != VAL_INT || lo.type != VAL_INT || hi.type != VAL_INT) { fprintf(stderr, "CLAMP expects ints\n"); exit(1); } + if (x.type != VAL_INT || lo.type != VAL_INT || hi.type != VAL_INT) { + fprintf(stderr, "CLAMP expects ints\n"); + exit(1); + } int64_t v = x.i; if (v < lo.i) v = lo.i; if (v > hi.i) v = hi.i; push_value(vm, make_int(v)); - free_value(x); free_value(lo); free_value(hi); + free_value(x); + free_value(lo); + free_value(hi); break; } diff --git a/src/vm_case_max.c b/src/vm/math/max.c similarity index 100% rename from src/vm_case_max.c rename to src/vm/math/max.c diff --git a/src/vm_case_min.c b/src/vm/math/min.c similarity index 100% rename from src/vm_case_min.c rename to src/vm/math/min.c diff --git a/src/vm_case_mod.c b/src/vm/math/mod.c similarity index 100% rename from src/vm_case_mod.c rename to src/vm/math/mod.c diff --git a/src/vm_case_pow.c b/src/vm/math/pow.c similarity index 94% rename from src/vm_case_pow.c rename to src/vm/math/pow.c index ed38f29..f25d5cc 100644 --- a/src/vm_case_pow.c +++ b/src/vm/math/pow.c @@ -2,7 +2,6 @@ case OP_POW: { Value b = pop_value(vm); Value a = pop_value(vm); if (a.type != VAL_INT || b.type != VAL_INT) { fprintf(stderr, "POW expects ints\n"); exit(1); } - /* simple integer pow */ int64_t base = a.i; int64_t exp = b.i; int64_t res = 1; diff --git a/src/vm_case_random_int.c b/src/vm/math/random_int.c similarity index 100% rename from src/vm_case_random_int.c rename to src/vm/math/random_int.c diff --git a/src/vm_case_random_seed.c b/src/vm/math/random_seed.c similarity index 100% rename from src/vm_case_random_seed.c rename to src/vm/math/random_seed.c diff --git a/src/vm_case_print.c b/src/vm/print.c similarity index 61% rename from src/vm_case_print.c rename to src/vm/print.c index 6bd64f8..7873c73 100644 --- a/src/vm_case_print.c +++ b/src/vm/print.c @@ -1,12 +1,11 @@ case OP_PRINT: { Value v = pop_value(vm); - /* snapshot value at print time (deep copy arrays) */ Value snap = deep_copy_value(&v); free_value(v); if (vm->output_count < VM_OUTPUT_SIZE) { - vm->output[vm->output_count++] = snap; // store snapshot + vm->output[vm->output_count++] = snap; } else { - free_value(snap); // prevent leak + free_value(snap); fprintf(stderr, "Runtime error: output buffer overflow\n"); exit(1); } diff --git a/src/vm_case_find.c b/src/vm/strings/find.c similarity index 100% rename from src/vm_case_find.c rename to src/vm/strings/find.c diff --git a/src/vm_case_split.c b/src/vm/strings/split.c similarity index 100% rename from src/vm_case_split.c rename to src/vm/strings/split.c diff --git a/src/vm_case_substr.c b/src/vm/strings/substr.c similarity index 100% rename from src/vm_case_substr.c rename to src/vm/strings/substr.c diff --git a/src/vm_case_to_number.c b/src/vm/to_number.c similarity index 82% rename from src/vm_case_to_number.c rename to src/vm/to_number.c index 35f3a55..0ecb668 100644 --- a/src/vm_case_to_number.c +++ b/src/vm/to_number.c @@ -1,28 +1,23 @@ case OP_TO_NUMBER: { Value v = pop_value(vm); if (v.type == VAL_INT) { - /* pass-through */ Value out = make_int(v.i); free_value(v); push_value(vm, out); } else if (v.type == VAL_STRING) { const char *s = v.s ? v.s : ""; - /* trim spaces */ const char *p = s; while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') p++; char *endp = NULL; long long parsed = strtoll(p, &endp, 10); - /* skip trailing spaces */ while (endp && (*endp == ' ' || *endp == '\t' || *endp == '\r' || *endp == '\n')) endp++; if (endp && *endp != '\0') { - /* non-numeric suffix -> 0 */ push_value(vm, make_int(0)); } else { push_value(vm, make_int((int64_t)parsed)); } free_value(v); } else { - /* nil, array, function -> 0 */ free_value(v); push_value(vm, make_int(0)); } diff --git a/src/vm_case_to_string.c b/src/vm/to_string.c similarity index 100% rename from src/vm_case_to_string.c rename to src/vm/to_string.c diff --git a/src/vm_case_return.c b/src/vm_case_return.c deleted file mode 100644 index 264564c..0000000 --- a/src/vm_case_return.c +++ /dev/null @@ -1,13 +0,0 @@ -case OP_RETURN: { - Value retv; - /* if there's something on the stack -> return it, else nil */ - if (vm->sp >= 0) retv = pop_value(vm); - else retv = make_nil(); - - /* pop frame (free locals) */ - vm_pop_frame(vm); - - /* push return value into caller frame (or onto stack if no caller) */ - push_value(vm, retv); - break; -}