2024-10-31 00:54:04 +03:00
|
|
|
#include "interpreter.h"
|
2024-10-31 21:08:48 +03:00
|
|
|
|
|
|
|
|
#include "../../runtime/gc.h"
|
2024-11-04 01:43:43 +03:00
|
|
|
#include "../../runtime/runtime.h"
|
2024-10-31 21:08:48 +03:00
|
|
|
|
2025-01-08 23:52:39 +03:00
|
|
|
#include "module_manager.h"
|
2024-10-31 21:08:48 +03:00
|
|
|
#include "runtime_externs.h"
|
2024-11-04 01:43:43 +03:00
|
|
|
#include "stack.h"
|
|
|
|
|
#include "types.h"
|
|
|
|
|
#include "utils.h"
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-12-15 16:19:54 +03:00
|
|
|
void *__start_custom_data;
|
|
|
|
|
void *__stop_custom_data;
|
|
|
|
|
|
2024-11-14 14:02:36 +03:00
|
|
|
#define ASSERT_UNBOXED(memo, x) \
|
|
|
|
|
do \
|
|
|
|
|
if (!UNBOXED(x)) \
|
2024-12-17 04:15:25 +03:00
|
|
|
failure("%s: unboxed value expected in %s\n", __LINE__, memo); \
|
2024-11-14 14:02:36 +03:00
|
|
|
while (0)
|
|
|
|
|
|
2024-11-12 02:38:26 +03:00
|
|
|
struct State s;
|
|
|
|
|
|
2024-12-15 01:32:49 +03:00
|
|
|
static inline uint16_t ip_read_half_int(char **ip) {
|
2024-12-15 16:19:54 +03:00
|
|
|
#ifdef WITH_CHECK
|
|
|
|
|
return ip_read_half_int_unsafe(ip);
|
|
|
|
|
#else
|
|
|
|
|
return ip_read_half_int_safe(ip, s.bf);
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-12-15 01:32:49 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-12 02:38:26 +03:00
|
|
|
static inline int ip_read_int(char **ip) {
|
2024-12-15 16:19:54 +03:00
|
|
|
#ifdef WITH_CHECK
|
|
|
|
|
return ip_read_int_unsafe(ip);
|
|
|
|
|
#else
|
|
|
|
|
return ip_read_int_safe(ip, s.bf);
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
static inline uint8_t ip_read_byte(char **ip) {
|
2024-12-15 16:19:54 +03:00
|
|
|
#ifdef WITH_CHECK
|
|
|
|
|
return ip_read_byte_unsafe(ip);
|
|
|
|
|
#else
|
|
|
|
|
return ip_read_byte_safe(ip, s.bf);
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-11-14 00:50:43 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
static inline const char *ip_read_string(char **ip) {
|
2024-12-15 16:19:54 +03:00
|
|
|
#ifdef WITH_CHECK
|
|
|
|
|
return get_string_unsafe(s.bf, ip_read_int(ip));
|
|
|
|
|
#else
|
|
|
|
|
return get_string_safe(s.bf, ip_read_int(ip));
|
|
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-12 02:12:28 +03:00
|
|
|
const size_t BUFFER_SIZE = 1000;
|
|
|
|
|
|
2025-01-08 23:52:39 +03:00
|
|
|
void run_init(size_t *stack) {
|
|
|
|
|
init_state(&s, (void**)stack);
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2025-03-02 15:05:09 +03:00
|
|
|
void set_argc_argv(int argc, char **argv) {
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(BOX(argc));
|
2025-01-11 23:51:50 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
|
|
|
|
printf("- argc: %i\n", argc);
|
|
|
|
|
#endif
|
2024-11-07 19:31:25 +03:00
|
|
|
for (size_t i = 0; i < argc; ++i) {
|
2025-01-11 23:51:50 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
|
|
|
|
printf("- arg: %s\n", argv[argc - i - 1]);
|
|
|
|
|
#endif
|
2024-11-14 00:50:43 +03:00
|
|
|
s_push(Bstring((aint *)&argv[argc - i - 1]));
|
2024-11-07 19:31:25 +03:00
|
|
|
}
|
2024-11-14 00:50:43 +03:00
|
|
|
s_push(Barray((aint *)s_peek(), argc));
|
|
|
|
|
void *argv_elem = s_pop();
|
|
|
|
|
s_popn(argc);
|
|
|
|
|
s_push(argv_elem);
|
2025-01-11 23:51:50 +03:00
|
|
|
|
|
|
|
|
#ifdef DEBUG_VERSION
|
|
|
|
|
print_stack(s);
|
|
|
|
|
printf("- state init done\n");
|
|
|
|
|
#endif
|
2025-01-08 23:52:39 +03:00
|
|
|
}
|
|
|
|
|
|
2025-03-09 16:33:56 +03:00
|
|
|
static inline void call_Bsexp(const char* name, size_t args_count) {
|
|
|
|
|
#ifdef DEBUG_VERSION
|
|
|
|
|
printf("tag hash is %i, n is %i\n", UNBOX(LtagHash((char *)name)),
|
|
|
|
|
args_count);
|
|
|
|
|
#endif
|
|
|
|
|
s_push((void *)LtagHash((char *)name));
|
|
|
|
|
s_rotate_n(args_count + 1);
|
|
|
|
|
|
|
|
|
|
void *sexp = Bsexp((aint *)s_peek(), BOX(args_count + 1));
|
|
|
|
|
s_popn(args_count + 1);
|
|
|
|
|
s_push(sexp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void call_Barray(size_t elem_count) {
|
2025-03-03 13:15:21 +03:00
|
|
|
s_rotate_n(elem_count);
|
2025-01-20 23:13:42 +03:00
|
|
|
|
|
|
|
|
// NOTE: not sure if elems should be added
|
2025-03-03 13:15:21 +03:00
|
|
|
void *array = NULL;
|
2025-01-20 23:13:42 +03:00
|
|
|
|
2025-03-03 13:15:21 +03:00
|
|
|
array = Barray((aint*)s_peek(), BOX(elem_count));
|
|
|
|
|
s_popn(elem_count);
|
2025-01-20 23:13:42 +03:00
|
|
|
s_push(array);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-30 09:34:50 +03:00
|
|
|
void call_builtin(uint builtin_id, uint args_count) {
|
|
|
|
|
#ifdef DEBUG_VERSION
|
|
|
|
|
printf("builtin id: %zu\n", builtin_id);
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef WITH_CHECK
|
|
|
|
|
if (builtin_id >= BUILTIN_NONE) {
|
|
|
|
|
s_failure(&s, "invalid builtin");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (builtin_id == BUILTIN_Barray) {
|
|
|
|
|
call_Barray(args_count);
|
|
|
|
|
} else {
|
|
|
|
|
run_stdlib_func(builtin_id, args_count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-02 15:05:09 +03:00
|
|
|
void run_main(Bytefile* bf, int argc, char **argv) {
|
2025-01-08 23:52:39 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2025-03-02 15:05:09 +03:00
|
|
|
printf("--- init state ---\n");
|
2025-01-08 23:52:39 +03:00
|
|
|
#endif
|
|
|
|
|
|
2025-03-02 15:05:09 +03:00
|
|
|
prepare_state(bf, &s);
|
2025-01-08 23:52:39 +03:00
|
|
|
|
|
|
|
|
void *buffer[BUFFER_SIZE];
|
|
|
|
|
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2025-03-02 15:05:09 +03:00
|
|
|
printf("--- run begin ---\n");
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
do {
|
2024-11-06 02:28:46 +03:00
|
|
|
bool call_happened = false;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-01-08 23:52:39 +03:00
|
|
|
if (s.ip >= s.bf->code_ptr + s.bf->code_size) {
|
2024-11-12 21:08:41 +03:00
|
|
|
s_failure(&s, "instruction pointer is out of range (>= size)");
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-08 23:52:39 +03:00
|
|
|
if (s.ip < s.bf->code_ptr) {
|
2024-11-12 21:08:41 +03:00
|
|
|
s_failure(&s, "instruction pointer is out of range (< 0)");
|
|
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-11-12 21:08:41 +03:00
|
|
|
|
|
|
|
|
s.instr_ip = s.ip;
|
2024-11-14 00:50:43 +03:00
|
|
|
uint8_t x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2025-03-03 00:13:19 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2025-01-08 23:52:39 +03:00
|
|
|
printf("0x%.8x: %s\n", s.ip - s.bf->code_ptr - 1, read_cmd(s.ip - 1, s.bf));
|
2025-03-03 00:13:19 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
|
|
|
|
|
switch (h) {
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_EXIT:
|
2024-10-11 17:07:04 +03:00
|
|
|
goto stop;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
/* BINOP */
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BINOP: { // BINOP ops[l-1]
|
2024-11-14 14:02:36 +03:00
|
|
|
void *snd = s_pop();
|
|
|
|
|
void *fst = s_pop();
|
2024-12-17 04:15:25 +03:00
|
|
|
int op = l - 1;
|
|
|
|
|
if (op == CMD_BINOP_SUB) {
|
2024-11-14 14:02:36 +03:00
|
|
|
s_push_i(Ls__Infix_45(fst, snd));
|
2024-12-17 04:15:25 +03:00
|
|
|
} else if (op == CMD_BINOP_EQ) {
|
|
|
|
|
s_push_i(Ls__Infix_6161(fst, snd));
|
2024-11-14 14:02:36 +03:00
|
|
|
} else {
|
2024-12-17 04:15:25 +03:00
|
|
|
switch (op) {
|
2024-11-14 14:02:36 +03:00
|
|
|
#define BINOP_OPR(val, op) \
|
|
|
|
|
case val: \
|
|
|
|
|
ASSERT_UNBOXED("captured op:1", fst); \
|
|
|
|
|
ASSERT_UNBOXED("captured op:2", snd); \
|
|
|
|
|
s_push_i(BOX(UNBOX(fst) op UNBOX(snd))); \
|
|
|
|
|
break;
|
|
|
|
|
FORALL_BINOP(BINOP_OPR)
|
|
|
|
|
#undef BINOP_OPR
|
|
|
|
|
|
|
|
|
|
default:
|
2025-03-02 15:05:09 +03:00
|
|
|
s_failure(&s, "interpreter: invalid opcode"); // %d-%d\n", h, l);
|
2024-11-14 14:02:36 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-11-14 00:50:43 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC:
|
2024-10-11 17:07:04 +03:00
|
|
|
switch (l) {
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_CONST: // CONST %d
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(BOX(ip_read_int(&s.ip)));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_STRING: { // STRING %s
|
|
|
|
|
void *str = (void *)ip_read_string(&s.ip);
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(Bstring((aint *)&str));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-02 01:19:54 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_SEXP: { // SEXP %s %d // create sexpr with tag=%s and %d
|
|
|
|
|
// elements from
|
|
|
|
|
// stack
|
2024-10-30 02:44:33 +03:00
|
|
|
// params read from stack
|
2024-11-14 00:50:43 +03:00
|
|
|
const char *name = ip_read_string(&s.ip);
|
|
|
|
|
size_t args_count = ip_read_int(&s.ip);
|
2025-03-09 16:33:56 +03:00
|
|
|
call_Bsexp(name, args_count);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_STI: { // STI - write by ref (?)
|
2024-11-07 19:31:25 +03:00
|
|
|
// NOTE: example not found, no checks done
|
2024-11-12 02:38:26 +03:00
|
|
|
void *elem = s_pop();
|
|
|
|
|
void **addr = (void **)s_pop();
|
2024-11-07 01:14:57 +03:00
|
|
|
*addr = elem;
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(elem);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-07 01:14:57 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_STA: { // STA - write to array elem
|
2024-11-12 02:38:26 +03:00
|
|
|
void *elem = s_pop();
|
|
|
|
|
aint index = s_pop_i();
|
|
|
|
|
void *data = s_pop();
|
|
|
|
|
s_push(Bsta(data, index, elem));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_JMP: { // JMP 0x%.8x
|
|
|
|
|
uint jmp_p = ip_read_int(&s.ip);
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-01-08 23:52:39 +03:00
|
|
|
if (jmp_p >= s.bf->code_size) {
|
2024-11-14 00:50:43 +03:00
|
|
|
s_failure(&s, "jump out of file");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2025-01-08 23:52:39 +03:00
|
|
|
s.ip = s.bf->code_ptr + jmp_p;
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_END: // END
|
2024-11-12 02:38:26 +03:00
|
|
|
if (!s_is_empty() && s.fp->prev_fp != 0) {
|
|
|
|
|
s.fp->ret = *s_peek();
|
|
|
|
|
s_pop();
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-11-12 02:38:26 +03:00
|
|
|
s_exit_f();
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_RET: // RET
|
2024-11-12 02:38:26 +03:00
|
|
|
if (!s_is_empty() && s.fp->prev_fp != 0) {
|
|
|
|
|
s.fp->ret = *s_peek();
|
|
|
|
|
s_pop();
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-11-12 02:38:26 +03:00
|
|
|
s_exit_f();
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_DROP: // DROP
|
2024-11-12 02:38:26 +03:00
|
|
|
s_pop();
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_DUP: // DUP
|
2024-11-04 01:43:43 +03:00
|
|
|
{
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(*s_peek());
|
2024-11-04 01:43:43 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-10-12 00:37:28 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_SWAP: // SWAP
|
2025-03-30 09:34:50 +03:00
|
|
|
s_swap_tops();
|
|
|
|
|
break;
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_BASIC_ELEM: // ELEM
|
2024-11-04 01:43:43 +03:00
|
|
|
{
|
2024-11-12 02:38:26 +03:00
|
|
|
aint index = s_pop_i();
|
|
|
|
|
void *data = s_pop();
|
|
|
|
|
s_push(Belem(data, index));
|
2024-11-04 01:43:43 +03:00
|
|
|
} break;
|
|
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
default:
|
2025-03-02 15:05:09 +03:00
|
|
|
s_failure(&s, "interpreter: basic, invalid opcode"); // %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_LD: { // LD %d
|
|
|
|
|
void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(*var_ptr);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-10-25 19:38:45 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_LDA: { // LDA %d
|
|
|
|
|
void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(*var_ptr);
|
2024-10-25 19:38:45 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_ST: { // ST %d
|
|
|
|
|
void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
2024-11-12 02:38:26 +03:00
|
|
|
*var_ptr = *s_peek();
|
2024-10-25 19:38:45 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL:
|
2024-10-11 17:07:04 +03:00
|
|
|
switch (l) {
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x
|
|
|
|
|
uint jmp_p = ip_read_int(&s.ip);
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-01-08 23:52:39 +03:00
|
|
|
if (jmp_p >= s.bf->code_size) {
|
2024-11-14 00:50:43 +03:00
|
|
|
s_failure(&s, "jump out of file");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-11-12 02:38:26 +03:00
|
|
|
if (UNBOX(s_pop_i()) == 0) {
|
2025-01-08 23:52:39 +03:00
|
|
|
s.ip = s.bf->code_ptr + jmp_p;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x
|
|
|
|
|
uint jmp_p = ip_read_int(&s.ip);
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-01-08 23:52:39 +03:00
|
|
|
if (jmp_p >= s.bf->code_size) {
|
2024-11-14 00:50:43 +03:00
|
|
|
s_failure(&s, "jump out of file");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-11-12 02:38:26 +03:00
|
|
|
if (UNBOX(s_pop_i()) != 0) {
|
2025-01-08 23:52:39 +03:00
|
|
|
s.ip = s.bf->code_ptr + jmp_p;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_BEGIN: { // BEGIN %d %d // function begin
|
2024-12-15 01:32:49 +03:00
|
|
|
uint args_sz = ip_read_int(&s.ip);
|
2024-12-15 03:33:46 +03:00
|
|
|
// #ifdef WITH_CHECK
|
2024-12-15 01:32:49 +03:00
|
|
|
uint locals_sz = ip_read_half_int(&s.ip);
|
|
|
|
|
uint max_additional_stack_sz = ip_read_half_int(&s.ip);
|
2024-12-15 03:33:46 +03:00
|
|
|
// #else
|
|
|
|
|
// uint locals_sz = ip_read_int(&s.ip);
|
|
|
|
|
// #endif
|
2025-03-03 00:13:19 +03:00
|
|
|
#ifndef WITH_CHECK
|
2024-11-06 02:28:46 +03:00
|
|
|
if (s.fp != NULL && s.call_ip == NULL) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "begin should only be called after call");
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2025-03-02 15:05:09 +03:00
|
|
|
s_enter_f(s.call_ip /*ip from call*/,
|
2025-01-08 23:52:39 +03:00
|
|
|
s.is_closure_call, args_sz, locals_sz);
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2024-12-15 01:32:49 +03:00
|
|
|
if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) {
|
2025-03-09 16:33:56 +03:00
|
|
|
s_failure(&s, "stack overflow");
|
2024-12-15 01:32:49 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CBEGIN: { // CBEGIN %d %d
|
2024-11-07 19:31:25 +03:00
|
|
|
// NOTE: example not found, no checks done
|
2024-12-15 01:32:49 +03:00
|
|
|
uint args_sz = ip_read_int(&s.ip);
|
2024-12-15 03:33:46 +03:00
|
|
|
// #ifdef WITH_CHECK
|
2024-12-15 01:32:49 +03:00
|
|
|
uint locals_sz = ip_read_half_int(&s.ip);
|
2024-12-15 03:33:46 +03:00
|
|
|
uint max_additional_stack_sz = ip_read_half_int(&s.ip);
|
|
|
|
|
// #else
|
|
|
|
|
// uint locals_sz = ip_read_int(&s.ip);
|
|
|
|
|
// #endif
|
|
|
|
|
#ifndef WITH_CHECK
|
2024-11-06 02:28:46 +03:00
|
|
|
if (s.fp != NULL && s.call_ip == NULL) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "begin should only be called after call");
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2025-03-02 15:05:09 +03:00
|
|
|
s_enter_f(s.call_ip /*ip from call*/,
|
2025-01-08 23:52:39 +03:00
|
|
|
s.is_closure_call, args_sz, locals_sz);
|
2025-03-03 00:13:19 +03:00
|
|
|
#ifndef WITH_CHECK
|
2024-12-15 01:32:49 +03:00
|
|
|
if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) {
|
2025-01-21 00:57:38 +03:00
|
|
|
s_failure(&s, "stack overflow");
|
2024-12-15 01:32:49 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CLOSURE: // CLOSURE 0x%.8x
|
2024-11-07 01:14:57 +03:00
|
|
|
{
|
|
|
|
|
aint call_offset = ip_read_int(&s.ip);
|
|
|
|
|
aint args_count = ip_read_int(&s.ip);
|
|
|
|
|
for (aint i = 0; i < args_count; i++) {
|
2024-12-15 00:54:48 +03:00
|
|
|
uint8_t arg_type = ip_read_byte(&s.ip);
|
|
|
|
|
auint arg_id = ip_read_int(&s.ip);
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 01:14:57 +03:00
|
|
|
void **var_ptr =
|
2024-12-15 00:54:48 +03:00
|
|
|
var_by_category(to_var_category(arg_type), arg_id);
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push(*var_ptr);
|
2024-11-07 01:14:57 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-03-30 09:34:50 +03:00
|
|
|
// check correct offset
|
2025-01-08 23:52:39 +03:00
|
|
|
if (call_offset >= s.bf->code_size) {
|
2024-11-22 17:10:40 +03:00
|
|
|
s_failure(&s, "jump out of file");
|
|
|
|
|
}
|
2025-03-30 09:34:50 +03:00
|
|
|
// or correct builtin // TODO: add this check to analyzer
|
|
|
|
|
if (call_offset < 0 && call_offset + 1 <= -BUILTIN_NONE) {
|
|
|
|
|
s_failure(&s, "closure");
|
|
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2025-03-30 09:34:50 +03:00
|
|
|
// NOTE: call_offset < 0 => deal with closure of builtin function
|
|
|
|
|
s_push_i(BOX(call_offset));
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-12-17 04:15:25 +03:00
|
|
|
void *closure = Bclosure((aint *)__gc_stack_top, BOX(args_count));
|
|
|
|
|
// printf("args is %li, count is %li\n", args_count, get_len(TO_DATA(closure)));
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-12 02:38:26 +03:00
|
|
|
s_popn(args_count + 1);
|
|
|
|
|
s_push(closure);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CALLC: { // CALLC %d // call clojure
|
2024-11-07 00:56:21 +03:00
|
|
|
aint args_count = ip_read_int(&s.ip); // args count
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2025-03-30 09:34:50 +03:00
|
|
|
aint closure_offset = UNBOX((char*)Belem(*s_nth(args_count), BOX(0)));
|
2024-11-06 02:28:46 +03:00
|
|
|
call_happened = true;
|
|
|
|
|
s.is_closure_call = true;
|
|
|
|
|
s.call_ip = s.ip;
|
2025-03-30 09:34:50 +03:00
|
|
|
s.ip = s.bf->code_ptr + closure_offset;
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-07 00:56:21 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_CALL: { // CALL 0x%.8x %d // call function
|
|
|
|
|
uint call_p = ip_read_int(&s.ip);
|
2024-11-06 02:28:46 +03:00
|
|
|
ip_read_int(&s.ip); // args count
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-06 02:28:46 +03:00
|
|
|
call_happened = true;
|
|
|
|
|
s.is_closure_call = false;
|
2024-11-04 01:43:43 +03:00
|
|
|
s.call_ip = s.ip;
|
|
|
|
|
|
2024-12-15 03:33:46 +03:00
|
|
|
#ifndef WITH_CHECK
|
2025-01-08 23:52:39 +03:00
|
|
|
if (call_p >= s.bf->code_size) {
|
2024-11-14 00:50:43 +03:00
|
|
|
s_failure(&s, "jump out of file");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
2024-12-15 03:33:46 +03:00
|
|
|
#endif
|
2025-01-08 23:52:39 +03:00
|
|
|
s.ip = s.bf->code_ptr + call_p;
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_TAG: { // TAG %s %d
|
|
|
|
|
const char *name = ip_read_string(&s.ip);
|
2024-11-06 02:28:46 +03:00
|
|
|
aint args_count = ip_read_int(&s.ip);
|
|
|
|
|
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2024-12-17 04:15:25 +03:00
|
|
|
printf("tag hash is %i, n is %i, peek is %i, unboxed: %li\n",
|
|
|
|
|
UNBOX(LtagHash((char *)name)), args_count, s_peek(&s), UNBOXED(s_peek(&s)));
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Btag(s_pop(), LtagHash((char *)name), BOX(args_count)));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_ARRAY: // ARRAY %d
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Barray_patt(s_pop(), BOX(ip_read_int(&s.ip))));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_FAIL: { // FAIL %d %d
|
|
|
|
|
int line = ip_read_int(&s.ip);
|
|
|
|
|
int col = ip_read_int(&s.ip);
|
2025-03-30 09:34:50 +03:00
|
|
|
print_stack(&s);
|
2024-11-12 02:38:26 +03:00
|
|
|
Bmatch_failure(s_pop(), argv[0], BOX(line), BOX(col));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-09 23:32:09 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_CTRL_LINE: // LINE %d
|
2024-11-09 23:32:09 +03:00
|
|
|
s.current_line = ip_read_int(&s.ip);
|
2024-10-12 00:37:28 +03:00
|
|
|
// maybe some metainfo should be collected
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2025-03-02 15:05:09 +03:00
|
|
|
case CMD_CTRL_BUILTIN: { // BUILTIN %d %d // call builtin
|
|
|
|
|
size_t builtin_id = ip_read_int(&s.ip);
|
|
|
|
|
size_t args_count = ip_read_int(&s.ip); // args count
|
2025-03-30 09:34:50 +03:00
|
|
|
call_builtin(builtin_id, args_count);
|
|
|
|
|
s.ip = s.call_ip; // TODO: check
|
2025-03-02 15:05:09 +03:00
|
|
|
break;
|
2025-03-30 09:34:50 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
default:
|
2025-03-02 15:05:09 +03:00
|
|
|
s_failure(&s, "interpreter: ctrl, invalid opcode"); // %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT: // PATT pats[l]
|
2024-11-02 01:19:54 +03:00
|
|
|
// {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}
|
|
|
|
|
switch (l) {
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_STR: // =str
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Bstring_patt(s_pop(), s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_STR_TAG: // #string
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Bstring_tag_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_ARRAY_TAG: // #array
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Barray_tag_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_SEXP_TAG: // #sexp
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Bsexp_tag_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_REF_TAG: // #ref
|
2025-03-16 14:26:48 +03:00
|
|
|
s_push_i(Bboxed_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_VAL_TAG: // #val
|
2025-03-16 14:26:48 +03:00
|
|
|
s_push_i(Bunboxed_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-14 00:50:43 +03:00
|
|
|
case CMD_PATT_FUN_TAG: // #fun
|
2024-11-12 02:38:26 +03:00
|
|
|
s_push_i(Bclosure_tag_patt(s_pop()));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
|
|
|
|
default:
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
2024-11-02 01:19:54 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2025-01-20 23:13:42 +03:00
|
|
|
// NOTE: no longer used
|
|
|
|
|
// case CMD_BUILTIN: {
|
|
|
|
|
// switch (l) {
|
|
|
|
|
// case CMD_BUILTIN_Lread: // CALL Lread
|
|
|
|
|
// s_push_i(Lread());
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
// case CMD_BUILTIN_Lwrite: // CALL Lwrite
|
|
|
|
|
// Lwrite(*s_peek_i());
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
// case CMD_BUILTIN_Llength: // CALL Llength
|
|
|
|
|
// s_push_i(Llength(s_pop()));
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
// case CMD_BUILTIN_Lstring: { // CALL Lstring
|
|
|
|
|
// void *val = s_pop();
|
|
|
|
|
// void *str = Lstring((aint *)&val);
|
|
|
|
|
// s_push(str);
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// case CMD_BUILTIN_Barray: { // CALL Barray %d
|
|
|
|
|
// size_t elem_count = ip_read_int(&s.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);
|
|
|
|
|
// void *array =
|
|
|
|
|
// Barray((aint *)opr_buffer,
|
|
|
|
|
// BOX(elem_count)); // NOTE: not sure if elems should be
|
|
|
|
|
// // added
|
|
|
|
|
|
|
|
|
|
// // void *array = Barray((aint *)s_peek(), BOX(elem_count));
|
|
|
|
|
// s_push(array);
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
// s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
|
|
|
|
// }
|
|
|
|
|
// } break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
default:
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2025-03-30 09:34:50 +03:00
|
|
|
// NOTE: do not clear for now, assume that call are correct
|
2024-11-06 02:28:46 +03:00
|
|
|
if (!call_happened) {
|
|
|
|
|
s.is_closure_call = false;
|
|
|
|
|
s.call_ip = NULL;
|
|
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
if (s.fp == NULL) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2024-11-04 01:43:43 +03:00
|
|
|
print_stack(&s);
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-11-04 01:43:43 +03:00
|
|
|
} while (1);
|
2024-10-12 00:37:28 +03:00
|
|
|
stop:;
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2025-03-30 09:34:50 +03:00
|
|
|
printf("--- run end ---\n");
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
2025-01-08 23:52:39 +03:00
|
|
|
|
|
|
|
|
void run_cleanup() { cleanup_state(&s); }
|