From 4d7afdeae0d98ab0a93751d205bb0ba833875f44 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sat, 12 Apr 2025 17:09:02 +0300 Subject: [PATCH] fixes to run stdlib tests and tutorial tests. No unexpected exits on these tests (without output checkings). + remove som e leftovers from stdlib closure coding + bug fixes --- byterun/dep_check.sh | 1 - byterun/include/module_manager.h | 6 +- byterun/include/parser.h | 2 - byterun/include/runtime_externs.h | 2 +- byterun/regression_check.sh | 6 +- byterun/src/interpreter.c | 15 +++-- byterun/src/module_manager.cpp | 90 +++++++++++++++++++----------- byterun/src/types.c | 2 +- byterun/stdlib_regression_check.sh | 10 ++-- byterun/tutorial_check.sh | 1 + 10 files changed, 84 insertions(+), 51 deletions(-) diff --git a/byterun/dep_check.sh b/byterun/dep_check.sh index 77f70c897..305f500d9 100755 --- a/byterun/dep_check.sh +++ b/byterun/dep_check.sh @@ -28,5 +28,4 @@ for test in regression/dep_test*.lama; do echo "done" done -rm *.bc rm *.o diff --git a/byterun/include/module_manager.h b/byterun/include/module_manager.h index 91ad07c61..e31022eea 100644 --- a/byterun/include/module_manager.h +++ b/byterun/include/module_manager.h @@ -54,15 +54,17 @@ enum BUILTIN : uint { // BUILTIN_LkindOf, // 39 BUILTIN_LcompareTags, // 40 + BUILTIN_Ls__Infix_58, // 41 // #define BUILTIN_NAME(name) BUILTIN_##name, FORALL_BINOP_FUNC(BUILTIN_NAME) #undef BUILTIN_NAME // - BUILTIN_Barray, // 41+14 // can't be run with run_stdlib_func - BUILTIN_NONE, // 42+14 + BUILTIN_Barray, // 42+14 // can't be run with run_stdlib_func + BUILTIN_NONE, // 43+14 }; enum BUILTIN id_by_builtin(const char *name); +bool is_builtin_with_ret(enum BUILTIN id); void run_stdlib_func(enum BUILTIN id, size_t args_count); diff --git a/byterun/include/parser.h b/byterun/include/parser.h index 1a275f29e..26ffae469 100644 --- a/byterun/include/parser.h +++ b/byterun/include/parser.h @@ -19,9 +19,7 @@ DEF(CMD_BINOP_AND, &&) \ DEF(CMD_BINOP_OR, ||) -// NOTE: includes additional ':' operator #define FORALL_BINOP_FUNC(DEF) \ - DEF(Ls__Infix_58) \ DEF(Ls__Infix_3333) \ DEF(Ls__Infix_3838) \ DEF(Ls__Infix_6161) \ diff --git a/byterun/include/runtime_externs.h b/byterun/include/runtime_externs.h index 0140cc131..9a9bfb3b2 100644 --- a/byterun/include/runtime_externs.h +++ b/byterun/include/runtime_externs.h @@ -25,7 +25,7 @@ aint LkindOf(void *p); aint LcompareTags(void *p, void *q); // Functional synonym for built-in operator ":"; -void *Ls__Infix_58(void *p, void *q); +void *Ls__Infix_58(void **args); // Functional synonym for built-in operator "!!"; aint Ls__Infix_3333(void *p, void *q); diff --git a/byterun/regression_check.sh b/byterun/regression_check.sh index c1044efdb..d17a6294a 100755 --- a/byterun/regression_check.sh +++ b/byterun/regression_check.sh @@ -16,9 +16,9 @@ for test in ../regression/*.lama; do test_path="${test%.*}" test_file="${test_path##*/}" echo $test_path: $test_file - # cat $test_file.input | ./byterun.exe -p $test_file.bc > test.bc.code - # cat $test_file.input | ./byterun.exe -p $test_file.bc - # cat $test_file.input | ./byterun.exe -vi $test_file.bc + # cat $test_path.input | ./byterun.exe -p $test_file.bc > test.bc.code + # cat $test_path.input | ./byterun.exe -p $test_file.bc + # cat $test_path.input | ./byterun.exe -vi $test_file.bc cat $test_path.input | ./byterun.exe -vi $test_file.bc > test.log sed '1d;s/^..//' $test_path.t > test_orig.log diff test.log test_orig.log diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 14de0320c..c47c3e4a1 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -69,13 +69,13 @@ void set_argc_argv(int argc, char **argv) { #endif s_push(Bstring((aint *)&argv[argc - i - 1])); } - s_push(Barray((aint *)s_peek(), argc)); - void *argv_elem = s_pop(); + void *args_array = Barray((aint *)s_peek(), BOX(argc)); s_popn(argc); - s_push(argv_elem); + s_push(args_array); + *var_by_category(VAR_GLOBAL, 0) = args_array; // NOTE: implementation detail, stdlib/test26.lama #ifdef DEBUG_VERSION - print_stack(s); + print_stack(&s); printf("- state init done\n"); #endif } @@ -468,6 +468,13 @@ void run_main(Bytefile* bf, int argc, char **argv) { size_t builtin_id = ip_read_int(&s.ip); size_t args_count = ip_read_int(&s.ip); // args count call_builtin(builtin_id, args_count); + if (s.is_closure_call) { + // NOTE: all functions have returned value, some values undefined + // if (is_builtin_with_ret(builtin_id)) { + s_swap_tops(); + // } + s_pop(); + } s.ip = s.call_ip; // TODO: check break; } diff --git a/byterun/src/module_manager.cpp b/byterun/src/module_manager.cpp index e8fbc3d3b..763c98747 100644 --- a/byterun/src/module_manager.cpp +++ b/byterun/src/module_manager.cpp @@ -19,15 +19,21 @@ extern "C" { template requires(N == 0) -void call_func(void (*f)(), Args... args) { - s_push(((void *(*)(Args...))f)(args...)); +void call_func(void (*f)(), size_t n, Args... args) { + // std::cout << std::endl << "args_count=" << n << " "; // TODO FIXME TMP + std::cout << std::endl; // TODO: TMP, to work with problematic \n display + asm volatile("movq %0, %%r11" + : /* no outputs */ + : "m"(n)); + /*s_push(*/ ((void (*)(Args...))f)(args...); //); + s_push(0); } template requires(N != 0) -void call_func(void (*f)(), Args... args) { +void call_func(void (*f)(), size_t n, Args... args) { void *arg = s_pop(); - call_func(f, arg, args...); + call_func(f, n, arg, args...); // TODO: check that arg is added on the right position } @@ -39,7 +45,7 @@ void call_anyarg_func(void (*f)(), size_t n) { } } if (n == N) { - call_func(f); + call_func(f, n); } else if constexpr (N > 0) { call_anyarg_func(f, n); } @@ -55,8 +61,6 @@ struct Offsets { }; void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { - // TODO: globals offsets - char *ip = bytefile->code_ptr; while (ip - bytefile->code_ptr < bytefile->code_size) { char *instr_ip = ip; @@ -73,6 +77,8 @@ void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { char *write_ip = instr_ip + 1; switch (cmd) { case Cmd::STRING: + case Cmd::SEXP: + case Cmd::TAG: ip_write_int_unsafe(write_ip, ip_read_int_unsafe(&read_ip) + offsets.strings); break; @@ -85,16 +91,14 @@ void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { break; case Cmd::CLOSURE: { aint offset = ip_read_int_unsafe(&read_ip); - // NOTE: do not modify offset for builtin's closures - ip_write_int_unsafe(write_ip, - offset < 0 ? offset : offset + offsets.code); + ip_write_int_unsafe(write_ip, offset + offsets.code); size_t args_count = ip_read_int_unsafe(&read_ip); for (size_t i = 0; i < args_count; ++i) { uint8_t arg_type = ip_read_byte_unsafe(&read_ip); + aint value = ip_read_int_unsafe(&read_ip); if (to_var_category(arg_type) == VAR_GLOBAL) { write_ip = read_ip; - ip_write_int_unsafe(write_ip, - ip_read_int_unsafe(&read_ip) + offsets.globals); + ip_write_int_unsafe(write_ip, value + offsets.globals); } } break; @@ -173,8 +177,8 @@ void add_subst_builtin_offsets(BuiltinSubstMap &subst_map, size_t code_offset, // NOTE: unmanaged memory allocated std::pair gen_builtins(size_t code_offset, BuiltinSubstMap &subst_map) { - size_t code_size = - subst_map.size() * /*size of builtin command*/ (1 + 2 * sizeof(uint32_t)); + size_t code_size = subst_map.size() * + /*size of builtin command*/ (1 + 2 * sizeof(uint32_t)); char *code = (char *)malloc(code_size); char *code_it = code; @@ -377,7 +381,6 @@ Bytefile *path_mod_load(const char *name, std::filesystem::path &&path) { static std::vector search_paths; extern "C" { - void mod_add_search_path(const char *path) { search_paths.emplace_back(path); } Bytefile *mod_load(const char *name) { @@ -533,6 +536,7 @@ BUILTIN id_by_builtin(const char *name) { {"LgetEnv", BUILTIN_LgetEnv}, {"Lrandom", BUILTIN_Lrandom}, {"Ltime", BUILTIN_Ltime}, + {"Ls__Infix_58", BUILTIN_Ls__Infix_58}, // {"LkindOf", BUILTIN_LkindOf}, {"LcompareTags", BUILTIN_LcompareTags}, @@ -549,6 +553,27 @@ BUILTIN id_by_builtin(const char *name) { return it == std_func.end() ? BUILTIN_NONE : it->second; } +/* NOTE: all functions have returned value, some values undefined */ +// bool is_builtin_with_ret(BUILTIN id) { +// switch (id) { +// case BUILTIN_Lassert: +// case BUILTIN_Lsprintf: +// case BUILTIN_Lprintf: +// case BUILTIN_Lfclose: +// case BUILTIN_Lfwrite: +// case BUILTIN_Lfprintf: +// case BUILTIN_Lfailure: +// return false; +// default: +// return true; +// } +// } + +/* NOTE: from src/X86_64.ml: */ +/* For vararg functions where we pass them in the stdlib function using va_list, + we have to unbox values to print them correctly. + For this we have special assemply functions in `printf.S`. + We additionally pass them amount of arguments to unbox using register r11. */ void run_stdlib_func(BUILTIN id, size_t args_count) { // std::cout << "RUN BUILTIN: " << id << '\n'; // TODO: TMP void *ret = NULL; @@ -565,10 +590,8 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_push(ret); break; case BUILTIN_Lassert: - s_popn(args_count); - std::cout << "!!> assert is not properly checked yet, skipping\n"; // NOTE: basic params: .args_count = 2, .is_vararg = true - // call_anyarg_func<20>((void (*)()) & Lassert, args_count); + call_anyarg_func<20>((void (*)()) & Lassert, args_count); break; case BUILTIN_Lstring: ret = Lstring(s_nth_i(0)); // .is_args = true @@ -617,17 +640,18 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_push(ret); break; case BUILTIN_Lsprintf: - s_popn(args_count); - std::cout << "!!> printf is not properly checked yet, skipping\n"; // NOTE: basic params: .args_count = 1, .is_vararg = true - // call_anyarg_func<20>((void (*)()) & Lsprintf, args_count); + call_anyarg_func<20>((void (*)()) & Lsprintf, args_count); break; case BUILTIN_Lsubstring: + // std::cout << "substr\n"; + s_rotate_n(3); // NOTE: is fix ? ret = (void *)Lsubstring(s_nth_i(0)); // .is_args = true; s_popn(3); s_push(ret); break; case BUILTIN_Li__Infix_4343: + s_rotate_n(2); // NOTE: is fix ? ret = (void *)Li__Infix_4343(s_nth_i(0)); // .is_args = true s_popn(2); s_push(ret); @@ -682,10 +706,8 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_push(ret); break; case BUILTIN_Lprintf: - s_popn(args_count); - std::cout << "!!> printf is not properly checked yet, skipping\n"; // NOTE: basic params: .args_count = 1, .is_vararg = true - // call_anyarg_func<20>((void (*)()) & Lprintf, args_count); + call_anyarg_func<20>((void (*)()) & Lprintf, args_count); break; case BUILTIN_Lfopen: ret = (void *)Lfopen((char *)*s_nth(1), (char *)*s_nth(0)); @@ -695,7 +717,7 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { case BUILTIN_Lfclose: /*ret = (void *)*/ Lfclose((FILE *)*s_nth(0)); s_popn(1); - // s_push(ret); // NOTE: ?? + s_push(0); // NOTE: UB on use break; case BUILTIN_Lfread: ret = (void *)Lfread((char *)*s_nth(0)); @@ -705,7 +727,7 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { case BUILTIN_Lfwrite: /*ret = (void *)*/ Lfwrite((char *)*s_nth(1), (char *)*s_nth(0)); s_popn(2); - // s_push(ret); // NOTE: ?? + s_push(0); // NOTE: UB on use break; case BUILTIN_Lfexists: ret = (void *)Lfexists((char *)*s_nth(0)); @@ -713,10 +735,8 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_push(ret); break; case BUILTIN_Lfprintf: - s_popn(args_count); - std::cout << "!!> printf is not properly checked yet, skipping\n"; // NOTE: basic params: .args_count = 2, .is_vararg = true - // call_anyarg_func<20>((void (*)()) & Lfprintf, args_count); + call_anyarg_func<20>((void (*)()) & Lfprintf, args_count); break; case BUILTIN_Lregexp: ret = (void *)Lregexp((char *)*s_nth(0)); @@ -730,9 +750,8 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_push(ret); break; case BUILTIN_Lfailure: - std::cout << "!!> failure is not properly checked yet, skipping\n"; // NOTE: basic params: .args_count = 1, .is_vararg = true - // call_anyarg_func<20>((void (*)()) & Lfailure, args_count); + call_anyarg_func<20>((void (*)()) & Lfailure, args_count); break; case BUILTIN_Lsystem: ret = (void *)Lsystem((char *)*s_nth(0)); @@ -763,6 +782,12 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { s_popn(2); s_push(ret); break; + case BUILTIN_Ls__Infix_58: + s_rotate_n(2); // NOTE: is fix ? + ret = (void *)Ls__Infix_58((void **)s_nth_i(0)); // .is_args = true + s_popn(2); + s_push(ret); + break; #define BUILTIN_CASE(name) \ case BUILTIN_##name: \ ret = (void *)name((char *)*s_nth(1), (char *)*s_nth(0)); \ @@ -784,7 +809,8 @@ void run_stdlib_func(BUILTIN id, size_t args_count) { // // TODO: move to bytecode verifier // if ((!func.is_vararg && func.args_count != args_count) || // func.args_count > args_count) { - // failure("RUNTIME ERROR: stdlib function <%u> argument count <%zu> is not + // failure("RUNTIME ERROR: stdlib function <%u> argument count <%zu> is + // not // " // "expected (expected is <%s%zu>)\n", // id, func.args_count, func.is_vararg ? ">=" : "=", args_count); diff --git a/byterun/src/types.c b/byterun/src/types.c index 7a8cf21f1..12d6bbedb 100644 --- a/byterun/src/types.c +++ b/byterun/src/types.c @@ -58,7 +58,7 @@ void prepare_state(Bytefile* bf, struct State* s) { } void push_globals(struct State *s) { - s->bf->global_ptr = (void*)__gc_stack_top; + s->bf->global_ptr = s_peek(); // (void*)__gc_stack_top; s_pushn_nil(s->bf->global_area_size); #ifdef DEBUG_VERSION diff --git a/byterun/stdlib_regression_check.sh b/byterun/stdlib_regression_check.sh index 94b0ae52b..da68e1e54 100755 --- a/byterun/stdlib_regression_check.sh +++ b/byterun/stdlib_regression_check.sh @@ -21,16 +21,16 @@ for mod in ../stdlib/*.lama; do done echo "Run tests:" -for test in ../stdlib/regression/*.lama; do +for test in ../stdlib/regression/*.lama; do echo $test $compiler -b $test -I ../stdlib/ > /dev/null test_path="${test%.*}" test_file="${test_path##*/}" echo $test_path: $test_file - # cat $test_file.input | ./byterun.exe -p $test_file.bc > test.bc.code - # cat $test_file.input | ./byterun.exe -p $test_file.bc - echo "" | ./byterun.exe -vi $test_file.bc - # echo "" | ./byterun.exe -vi $test_file.bc > test.log + echo "" | ./byterun.exe -p $test_file.bc > test.bc.code + # echo "" | ./byterun.exe -p $test_file.bc + # echo "" | ./byterun.exe -vi $test_file.bc + echo "" | ./byterun.exe -vi $test_file.bc > test.log # sed '1d;s/^..//' $test_file.t > test_orig.log # diff test.log test_orig.log diff --git a/byterun/tutorial_check.sh b/byterun/tutorial_check.sh index ea1ca49a4..3fbcb90bc 100755 --- a/byterun/tutorial_check.sh +++ b/byterun/tutorial_check.sh @@ -27,6 +27,7 @@ for test in ../tutorial/*.lama; do test_file="${test_path##*/}" echo $test_path: $test_file echo " " | ./byterun.exe -vi $test_file.bc + echo "" | ./byterun.exe -vi $test_file.bc > test.log rm $test_file.bc echo "done" done