mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
interpreter: migration to universial stdlib support (without varargs yet)
This commit is contained in:
parent
318ebc72aa
commit
58f0bfc0b9
9 changed files with 163 additions and 119 deletions
|
|
@ -24,3 +24,5 @@ int32_t mod_load(const char *name, bool do_verification); // < 0 => not found
|
||||||
uint32_t mod_add(Bytefile *module, bool do_verification);
|
uint32_t mod_add(Bytefile *module, bool do_verification);
|
||||||
|
|
||||||
struct ModSearchResult mod_search_pub_symbol(const char *name);
|
struct ModSearchResult mod_search_pub_symbol(const char *name);
|
||||||
|
|
||||||
|
bool run_stdlib_func(const char *name, size_t args_count);
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,12 @@ enum class Cmd : int8_t {
|
||||||
LINE,
|
LINE,
|
||||||
CALLF,
|
CALLF,
|
||||||
PATT,
|
PATT,
|
||||||
Lread,
|
// NOTE: no longer used
|
||||||
Lwrite,
|
// Lread,
|
||||||
Llength,
|
// Lwrite,
|
||||||
Lstring,
|
// Llength,
|
||||||
Barray,
|
// Lstring,
|
||||||
|
// Barray,
|
||||||
EXIT,
|
EXIT,
|
||||||
_UNDEF_,
|
_UNDEF_,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ enum CMD_TOPLVL {
|
||||||
CMD_ST,
|
CMD_ST,
|
||||||
CMD_CTRL,
|
CMD_CTRL,
|
||||||
CMD_PATT,
|
CMD_PATT,
|
||||||
CMD_BUILTIN,
|
// CMD_BUILTIN, // NOTE: no longer used
|
||||||
CMD_EXIT = 15,
|
CMD_EXIT = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -177,10 +177,10 @@ enum CMD_PATTS {
|
||||||
CMD_PATT_FUN_TAG,
|
CMD_PATT_FUN_TAG,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CMD_BUILTINS {
|
// enum CMD_BUILTINS { // NOTE: no longer used
|
||||||
CMD_BUILTIN_Lread = 0,
|
// CMD_BUILTIN_Lread = 0,
|
||||||
CMD_BUILTIN_Lwrite,
|
// CMD_BUILTIN_Lwrite,
|
||||||
CMD_BUILTIN_Llength,
|
// CMD_BUILTIN_Llength,
|
||||||
CMD_BUILTIN_Lstring,
|
// CMD_BUILTIN_Lstring,
|
||||||
CMD_BUILTIN_Barray,
|
// CMD_BUILTIN_Barray,
|
||||||
};
|
// };
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,3 @@ time ./byterun.exe -i Sort.bc > /dev/null
|
||||||
|
|
||||||
rm Sort.*
|
rm Sort.*
|
||||||
rm *.o
|
rm *.o
|
||||||
rm *.a
|
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ void analyze(uint32_t mod_id) {
|
||||||
break;
|
break;
|
||||||
case Cmd::CALLF: {
|
case Cmd::CALLF: {
|
||||||
// TODO: find link to real function and replace call (need to save all
|
// TODO: find link to real function and replace call (need to save all
|
||||||
// modules in one space)
|
// modules in one space) <- optimization
|
||||||
|
|
||||||
ip_read_int_unsafe(¤t_ip); // function name (str)
|
ip_read_int_unsafe(¤t_ip); // function name (str)
|
||||||
uint args_count = ip_read_int_unsafe(¤t_ip);
|
uint args_count = ip_read_int_unsafe(¤t_ip);
|
||||||
|
|
@ -344,23 +344,24 @@ void analyze(uint32_t mod_id) {
|
||||||
}
|
}
|
||||||
++current_stack_depth;
|
++current_stack_depth;
|
||||||
break;
|
break;
|
||||||
case Cmd::Lread:
|
// NOTE: no longer used
|
||||||
++current_stack_depth;
|
// case Cmd::Lread:
|
||||||
break;
|
// ++current_stack_depth;
|
||||||
case Cmd::Lwrite:
|
// break;
|
||||||
case Cmd::Llength:
|
// case Cmd::Lwrite:
|
||||||
case Cmd::Lstring:
|
// case Cmd::Llength:
|
||||||
if (current_stack_depth < 1) {
|
// case Cmd::Lstring:
|
||||||
ip_failure(saved_current_ip, mod_id, "not enough elements in stack");
|
// if (current_stack_depth < 1) {
|
||||||
}
|
// ip_failure(saved_current_ip, mod_id, "not enough elements in stack");
|
||||||
break;
|
// }
|
||||||
case Cmd::Barray:
|
// break;
|
||||||
current_stack_depth -= ip_read_int_unsafe(¤t_ip); // elem count
|
// case Cmd::Barray:
|
||||||
if (current_stack_depth < 0) {
|
// current_stack_depth -= ip_read_int_unsafe(¤t_ip); // elem count
|
||||||
ip_failure(saved_current_ip, mod_id, "not enough elements in stack");
|
// if (current_stack_depth < 0) {
|
||||||
}
|
// ip_failure(saved_current_ip, mod_id, "not enough elements in stack");
|
||||||
++current_stack_depth;
|
// }
|
||||||
break;
|
// ++current_stack_depth;
|
||||||
|
// break;
|
||||||
case Cmd::EXIT:
|
case Cmd::EXIT:
|
||||||
ip_failure(saved_current_ip, mod_id,
|
ip_failure(saved_current_ip, mod_id,
|
||||||
"exit should be unreachable"); // NOTE: not sure
|
"exit should be unreachable"); // NOTE: not sure
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,27 @@ void run_mod_rec(uint mod_id, int argc, char **argv, bool do_verification) {
|
||||||
run_mod(mod_id, argc, argv);
|
run_mod(mod_id, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void call_Barray(size_t elem_count, char** ip, void** buffer) {
|
||||||
|
// size_t elem_count = ip_read_int(ip);
|
||||||
|
|
||||||
|
void **opr_buffer = (void**)(elem_count > BUFFER_SIZE
|
||||||
|
? alloc(elem_count * sizeof(void *))
|
||||||
|
: buffer);
|
||||||
|
for (size_t i = 0; i < elem_count; ++i) {
|
||||||
|
opr_buffer[elem_count - i - 1] = s_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// s_rotate_n(elem_count);
|
||||||
|
|
||||||
|
// NOTE: not sure if elems should be added
|
||||||
|
void *array =
|
||||||
|
Barray((aint *)opr_buffer,
|
||||||
|
BOX(elem_count));
|
||||||
|
|
||||||
|
// void *array = Barray((aint *)s_peek(), BOX(elem_count));
|
||||||
|
s_push(array);
|
||||||
|
}
|
||||||
|
|
||||||
void run_mod(uint mod_id, int argc, char **argv) {
|
void run_mod(uint mod_id, int argc, char **argv) {
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("--- module init state ---\n");
|
printf("--- module init state ---\n");
|
||||||
|
|
@ -463,11 +484,21 @@ void run_mod(uint mod_id, int argc, char **argv) {
|
||||||
|
|
||||||
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function
|
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function
|
||||||
const char *call_func_name = ip_read_string(&s.ip);
|
const char *call_func_name = ip_read_string(&s.ip);
|
||||||
ip_read_int(&s.ip); // args count
|
size_t args_count = ip_read_int(&s.ip); // args count
|
||||||
|
|
||||||
|
if (run_stdlib_func(call_func_name, args_count)) {
|
||||||
|
// case of stdlib function
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(call_func_name, ".array") == 0) {
|
||||||
|
call_Barray(args_count, &s.ip, buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
struct ModSearchResult func = mod_search_pub_symbol(call_func_name);
|
struct ModSearchResult func = mod_search_pub_symbol(call_func_name);
|
||||||
if (func.mod_file == NULL) {
|
if (func.mod_file == NULL) {
|
||||||
s_failure(&s, "external function not found");
|
failure("RUNTIME:ERROR: external function <%s> with <%zu> args not found\n", call_func_name, args_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
call_happened = true;
|
call_happened = true;
|
||||||
|
|
@ -519,52 +550,53 @@ void run_mod(uint mod_id, int argc, char **argv) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_BUILTIN: {
|
// NOTE: no longer used
|
||||||
switch (l) {
|
// case CMD_BUILTIN: {
|
||||||
case CMD_BUILTIN_Lread: // CALL Lread
|
// switch (l) {
|
||||||
s_push_i(Lread());
|
// case CMD_BUILTIN_Lread: // CALL Lread
|
||||||
break;
|
// s_push_i(Lread());
|
||||||
|
// break;
|
||||||
|
|
||||||
case CMD_BUILTIN_Lwrite: // CALL Lwrite
|
// case CMD_BUILTIN_Lwrite: // CALL Lwrite
|
||||||
Lwrite(*s_peek_i());
|
// Lwrite(*s_peek_i());
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
case CMD_BUILTIN_Llength: // CALL Llength
|
// case CMD_BUILTIN_Llength: // CALL Llength
|
||||||
s_push_i(Llength(s_pop()));
|
// s_push_i(Llength(s_pop()));
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
case CMD_BUILTIN_Lstring: { // CALL Lstring
|
// case CMD_BUILTIN_Lstring: { // CALL Lstring
|
||||||
void *val = s_pop();
|
// void *val = s_pop();
|
||||||
void *str = Lstring((aint *)&val);
|
// void *str = Lstring((aint *)&val);
|
||||||
s_push(str);
|
// s_push(str);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case CMD_BUILTIN_Barray: { // CALL Barray %d
|
// case CMD_BUILTIN_Barray: { // CALL Barray %d
|
||||||
size_t elem_count = ip_read_int(&s.ip);
|
// size_t elem_count = ip_read_int(&s.ip);
|
||||||
|
|
||||||
void **opr_buffer = (void**)(elem_count > BUFFER_SIZE
|
// void **opr_buffer = (void**)(elem_count > BUFFER_SIZE
|
||||||
? alloc(elem_count * sizeof(void *))
|
// ? alloc(elem_count * sizeof(void *))
|
||||||
: buffer);
|
// : buffer);
|
||||||
for (size_t i = 0; i < elem_count; ++i) {
|
// for (size_t i = 0; i < elem_count; ++i) {
|
||||||
opr_buffer[elem_count - i - 1] = s_pop();
|
// opr_buffer[elem_count - i - 1] = s_pop();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// s_rotate_n(elem_count);
|
// // s_rotate_n(elem_count);
|
||||||
void *array =
|
// void *array =
|
||||||
Barray((aint *)opr_buffer,
|
// Barray((aint *)opr_buffer,
|
||||||
BOX(elem_count)); // NOTE: not sure if elems should be
|
// BOX(elem_count)); // NOTE: not sure if elems should be
|
||||||
// added
|
// // added
|
||||||
|
|
||||||
// void *array = Barray((aint *)s_peek(), BOX(elem_count));
|
// // void *array = Barray((aint *)s_peek(), BOX(elem_count));
|
||||||
s_push(array);
|
// s_push(array);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
default:
|
// default:
|
||||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
// s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||||
}
|
// }
|
||||||
} break;
|
// } break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ struct StdFunc {
|
||||||
bool is_args = false; // one var for all args
|
bool is_args = false; // one var for all args
|
||||||
bool is_vararg = false;
|
bool is_vararg = false;
|
||||||
};
|
};
|
||||||
bool run_stdlib_func(const char *name) {
|
bool run_stdlib_func(const char *name, size_t args_count) {
|
||||||
static const std::unordered_map<std::string, StdFunc> std_func = {
|
static const std::unordered_map<std::string, StdFunc> std_func = {
|
||||||
{"Luppercase", {.ptr = (void (*)()) & Luppercase, .args_count = 1}},
|
{"Luppercase", {.ptr = (void (*)()) & Luppercase, .args_count = 1}},
|
||||||
{"Llowercase", {.ptr = (void (*)()) & Llowercase, .args_count = 1}},
|
{"Llowercase", {.ptr = (void (*)()) & Llowercase, .args_count = 1}},
|
||||||
|
|
@ -217,8 +217,14 @@ bool run_stdlib_func(const char *name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stack safity check
|
// TODO: move to bytecode verifier
|
||||||
// TODO: add stdlib func stack check to verification step
|
if ((!it->second.is_vararg && it->second.args_count != args_count) ||
|
||||||
|
it->second.args_count > args_count) {
|
||||||
|
failure("RUNTIME ERROR: stdlib function <%s> argument count <%zu> is not "
|
||||||
|
"expected (expected is <%s%zu>)\n",
|
||||||
|
name, it->second.args_count, it->second.is_vararg ? ">=" : "=",
|
||||||
|
args_count);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: work with varargs
|
// TODO: work with varargs
|
||||||
if (it->second.is_vararg) {
|
if (it->second.is_vararg) {
|
||||||
|
|
|
||||||
|
|
@ -219,16 +219,17 @@ const char *command_name(Cmd cmd, int8_t l) {
|
||||||
return "_UNDEF_PATT_";
|
return "_UNDEF_PATT_";
|
||||||
}
|
}
|
||||||
return pats[l];
|
return pats[l];
|
||||||
case Cmd::Lread:
|
// NOTE: no longer used
|
||||||
return "CALL\tLread";
|
// case Cmd::Lread:
|
||||||
case Cmd::Lwrite:
|
// return "CALL\tLread";
|
||||||
return "CALL\tLwrite";
|
// case Cmd::Lwrite:
|
||||||
case Cmd::Llength:
|
// return "CALL\tLwrite";
|
||||||
return "CALL\tLlength";
|
// case Cmd::Llength:
|
||||||
case Cmd::Lstring:
|
// return "CALL\tLlength";
|
||||||
return "CALL\tLstring";
|
// case Cmd::Lstring:
|
||||||
case Cmd::Barray:
|
// return "CALL\tLstring";
|
||||||
return "CALL\tBarray\t%d";
|
// case Cmd::Barray:
|
||||||
|
// return "CALL\tBarray\t%d";
|
||||||
case Cmd::_UNDEF_:
|
case Cmd::_UNDEF_:
|
||||||
return "_UNDEF_";
|
return "_UNDEF_";
|
||||||
}
|
}
|
||||||
|
|
@ -552,35 +553,37 @@ std::pair<Cmd, uint8_t> parse_command_impl(char **ip, const Bytefile &bf,
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_BUILTIN: {
|
// NOTE: no longer used
|
||||||
switch (l) {
|
// case CMD_BUILTIN: {
|
||||||
case CMD_BUILTIN_Lread: // CALL Lread
|
// switch (l) {
|
||||||
cmd = Cmd::Lread;
|
// case CMD_BUILTIN_Lread: // CALL Lread
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
// cmd = Cmd::Lread;
|
||||||
break;
|
// read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
||||||
case CMD_BUILTIN_Lwrite: // CALL Lwrite
|
// break;
|
||||||
cmd = Cmd::Lwrite;
|
// case CMD_BUILTIN_Lwrite: // CALL Lwrite
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
// cmd = Cmd::Lwrite;
|
||||||
break;
|
// read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
||||||
case CMD_BUILTIN_Llength: // CALL Llength
|
// break;
|
||||||
cmd = Cmd::Llength;
|
// case CMD_BUILTIN_Llength: // CALL Llength
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
// cmd = Cmd::Llength;
|
||||||
break;
|
// read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
||||||
case CMD_BUILTIN_Lstring: // CALL Lstring
|
// break;
|
||||||
cmd = Cmd::Lstring;
|
// case CMD_BUILTIN_Lstring: // CALL Lstring
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
// cmd = Cmd::Lstring;
|
||||||
break;
|
// read_print_cmd_seq_opt<do_read_args, use_out>(cmd, l, ip, bf, out);
|
||||||
|
// break;
|
||||||
|
|
||||||
case CMD_BUILTIN_Barray: // CALL Barray %d
|
// case CMD_BUILTIN_Barray: // CALL Barray %d
|
||||||
cmd = Cmd::Barray;
|
// cmd = Cmd::Barray;
|
||||||
read_print_cmd_seq_opt<do_read_args, use_out, ArgT::INT>(cmd, l, ip, bf,
|
// read_print_cmd_seq_opt<do_read_args, use_out, ArgT::INT>(cmd, l, ip,
|
||||||
out);
|
// bf,
|
||||||
break;
|
// out);
|
||||||
|
// break;
|
||||||
|
|
||||||
default:
|
// default:
|
||||||
failure("invalid opcode");
|
// failure("invalid opcode");
|
||||||
}
|
// }
|
||||||
} break;
|
// } break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
failure("invalid opcode");
|
failure("invalid opcode");
|
||||||
|
|
|
||||||
14
src/SM.ml
14
src/SM.ml
|
|
@ -275,17 +275,17 @@ module ByteCode = struct
|
||||||
add_fixup s;
|
add_fixup s;
|
||||||
add_ints [ 0 ]
|
add_ints [ 0 ]
|
||||||
(* 0x70 *)
|
(* 0x70 *)
|
||||||
| CALL (f, _, _) when f = labeled "read" -> add_bytes [ (7 * 16) + 0 ]
|
(* | CALL (f, _, _) when f = labeled "read" -> add_bytes [ (7 * 16) + 0 ] *)
|
||||||
(* 0x71 *)
|
(* 0x71 *)
|
||||||
| CALL (f, _, _) when f = labeled "write" -> add_bytes [ (7 * 16) + 1 ]
|
(* | CALL (f, _, _) when f = labeled "write" -> add_bytes [ (7 * 16) + 1 ] *)
|
||||||
(* 0x72 *)
|
(* 0x72 *)
|
||||||
| CALL (f, _, _) when f = labeled "length" -> add_bytes [ (7 * 16) + 2 ]
|
(* | CALL (f, _, _) when f = labeled "length" -> add_bytes [ (7 * 16) + 2 ] *)
|
||||||
(* 0x73 *)
|
(* 0x73 *)
|
||||||
| CALL (f, _, _) when f = labeled "string" -> add_bytes [ (7 * 16) + 3 ]
|
(* | CALL (f, _, _) when f = labeled "string" -> add_bytes [ (7 * 16) + 3 ] *)
|
||||||
(* 0x74 *)
|
(* 0x74 *)
|
||||||
| CALL (".array", n, _) ->
|
(* | CALL (".array", n, _) -> *)
|
||||||
add_bytes [ (7 * 16) + 4 ];
|
(* add_bytes [ (7 * 16) + 4 ]; *)
|
||||||
add_ints [ n ]
|
(* add_ints [ n ] *)
|
||||||
(* 0x52 n:32 n:32 *)
|
(* 0x52 n:32 n:32 *)
|
||||||
| BEGIN (_, a, l, [], _, _) ->
|
| BEGIN (_, a, l, [], _, _) ->
|
||||||
add_bytes [ (5 * 16) + 2 ];
|
add_bytes [ (5 * 16) + 2 ];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue