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
|
|
|
|
|
|
|
|
#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-11-04 01:43:43 +03:00
|
|
|
int ip_read_int(char **ip) {
|
2024-10-11 17:07:04 +03:00
|
|
|
*ip += sizeof(int);
|
2024-11-04 01:43:43 +03:00
|
|
|
return *(int *)((*ip) - sizeof(int));
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-04 01:43:43 +03:00
|
|
|
char ip_read_byte(char **ip) { return *(*ip)++; }
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-11-04 01:43:43 +03:00
|
|
|
char *ip_read_string(char **ip, bytefile *bf) {
|
2024-10-20 16:42:57 +03:00
|
|
|
return get_string(bf, ip_read_int(ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
void run(bytefile *bf, int argc, char **argv) {
|
2024-11-12 00:10:02 +03:00
|
|
|
void *buffer[10000]; // FIXME: TODO: TMP
|
2024-11-06 02:28:46 +03:00
|
|
|
struct State s;
|
|
|
|
|
init_state(bf, &s);
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2024-11-04 01:43:43 +03:00
|
|
|
printf("--- interpreter run ---\n");
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-10-25 19:38:45 +03:00
|
|
|
const size_t OPS_SIZE = 13;
|
2024-11-04 01:43:43 +03:00
|
|
|
const char *ops[] = {
|
|
|
|
|
"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
|
|
|
|
aint (*ops_func[])(void *, void *) = {
|
|
|
|
|
&Ls__Infix_43, // +
|
|
|
|
|
&Ls__Infix_45, // -
|
|
|
|
|
&Ls__Infix_42, // *
|
|
|
|
|
&Ls__Infix_47, // /
|
|
|
|
|
&Ls__Infix_37, // %
|
|
|
|
|
&Ls__Infix_60, // <
|
|
|
|
|
&Ls__Infix_6061, // <=
|
|
|
|
|
&Ls__Infix_62, // >
|
|
|
|
|
&Ls__Infix_6261, // >=
|
|
|
|
|
&Ls__Infix_6161, // ==
|
|
|
|
|
&Ls__Infix_3361, // !=
|
|
|
|
|
&Ls__Infix_3838, // &&
|
|
|
|
|
&Ls__Infix_3333, // !!
|
2024-10-31 21:08:48 +03:00
|
|
|
};
|
2024-10-25 19:38:45 +03:00
|
|
|
|
|
|
|
|
const size_t PATS_SIZE = 7;
|
2024-11-04 01:43:43 +03:00
|
|
|
const char *pats[] = {"=str", "#string", "#array", "#sexp",
|
|
|
|
|
"#ref", "#val", "#fun"};
|
|
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
// argc, argv
|
|
|
|
|
{
|
|
|
|
|
s_push_i(&s, BOX(argc));
|
|
|
|
|
void **argv_strs = calloc(argc, sizeof(void *));
|
|
|
|
|
for (size_t i = 0; i < argc; ++i) {
|
|
|
|
|
argv_strs[i] = Bstring((aint *)&argv[i]);
|
|
|
|
|
}
|
|
|
|
|
s_push(&s, Barray((aint *)&argv_strs, argc));
|
|
|
|
|
free(argv_strs);
|
|
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2024-11-04 01:43:43 +03:00
|
|
|
printf("- loop start\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-04 01:43:43 +03:00
|
|
|
// char *before_op_ip = s.ip; // save to set s.prev_ip
|
2024-11-06 02:28:46 +03:00
|
|
|
bool call_happened = false;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
char x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-11-07 19:07:26 +03:00
|
|
|
#ifdef DEBUG_VERSION
|
2024-11-04 01:43:43 +03:00
|
|
|
printf("0x%.8x\n", s.ip - bf->code_ptr - 1);
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-10-11 17:07:04 +03:00
|
|
|
|
|
|
|
|
switch (h) {
|
|
|
|
|
case 15:
|
|
|
|
|
goto stop;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
/* BINOP */
|
2024-10-12 00:37:28 +03:00
|
|
|
case 0: // BINOP ops[l-1]
|
2024-10-25 19:38:45 +03:00
|
|
|
if (l > OPS_SIZE) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "undefined binop type index");
|
2024-10-25 19:38:45 +03:00
|
|
|
}
|
|
|
|
|
if (l < 1) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "negative binop type index");
|
2024-10-25 19:38:45 +03:00
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
void *left = s_pop(&s);
|
|
|
|
|
void *right = s_pop(&s);
|
|
|
|
|
s_push(&s, (void *)ops_func[l - 1](right, left));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
case 1:
|
|
|
|
|
switch (l) {
|
2024-11-04 01:43:43 +03:00
|
|
|
case 0: // CONST %d
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push_i(&s, BOX(ip_read_int(&s.ip)));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
case 1: { // STRING %s
|
|
|
|
|
void *str = ip_read_string(&s.ip, bf);
|
|
|
|
|
s_push(&s, 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-06 02:28:46 +03:00
|
|
|
case 2: { // 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-07 01:14:57 +03:00
|
|
|
const char *name = ip_read_string(&s.ip, bf);
|
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-11-07 19:31:25 +03:00
|
|
|
printf("tag hash is %i, n is %i\n", UNBOX(LtagHash((char *)name)),
|
2024-11-07 01:14:57 +03:00
|
|
|
args_count);
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-11-06 02:28:46 +03:00
|
|
|
|
|
|
|
|
if (args_count < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "args count should be >= 0");
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-12 00:10:02 +03:00
|
|
|
// void **buffer = calloc(args_count + 1, sizeof(void *));
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
for (size_t i = 1; i <= args_count; ++i) {
|
|
|
|
|
buffer[args_count - i] = s_pop(&s);
|
2024-11-06 02:28:46 +03:00
|
|
|
}
|
2024-11-07 01:14:57 +03:00
|
|
|
buffer[args_count] = (void *)LtagHash((char *)name);
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 01:14:57 +03:00
|
|
|
void *sexp = Bsexp((aint *)buffer, BOX(args_count + 1));
|
2024-11-06 02:28:46 +03:00
|
|
|
|
|
|
|
|
push_extra_root(sexp);
|
|
|
|
|
s_push(&s, sexp);
|
|
|
|
|
pop_extra_root(sexp);
|
|
|
|
|
|
2024-11-12 00:10:02 +03:00
|
|
|
// free(buffer);
|
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-07 01:14:57 +03:00
|
|
|
case 3: { // STI - write by ref (?)
|
2024-11-07 19:31:25 +03:00
|
|
|
// NOTE: example not found, no checks done
|
2024-11-07 01:14:57 +03:00
|
|
|
void *elem = s_pop(&s);
|
|
|
|
|
void **addr = (void **)s_pop(&s);
|
|
|
|
|
*addr = elem;
|
|
|
|
|
s_push(&s, 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-06 02:28:46 +03:00
|
|
|
case 4: { // STA - write to array elem
|
2024-11-07 01:14:57 +03:00
|
|
|
void *elem = s_pop(&s);
|
2024-11-06 02:28:46 +03:00
|
|
|
aint index = s_pop_i(&s);
|
2024-11-07 01:14:57 +03:00
|
|
|
void *data = s_pop(&s);
|
2024-11-06 02:28:46 +03:00
|
|
|
s_push(&s, 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-07 01:14:57 +03:00
|
|
|
case 5: { // JMP 0x%.8x
|
|
|
|
|
int jmp_p = ip_read_int(&s.ip);
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
if (jmp_p < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "negative file offset jumps are not allowed");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
s.ip = bf->code_ptr + jmp_p;
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 6: // END
|
|
|
|
|
if (!s_is_empty(&s) && s.fp->prev_fp != 0) {
|
|
|
|
|
s.fp->ret = *s_peek(&s);
|
|
|
|
|
s_pop(&s);
|
|
|
|
|
}
|
|
|
|
|
s_exit_f(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
case 7: // RET
|
|
|
|
|
if (!s_is_empty(&s) && s.fp->prev_fp != 0) {
|
|
|
|
|
s.fp->ret = *s_peek(&s);
|
|
|
|
|
s_pop(&s);
|
|
|
|
|
}
|
|
|
|
|
s_exit_f(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
case 8: // DROP
|
2024-11-02 01:19:54 +03:00
|
|
|
s_pop(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
|
|
|
|
case 9: // DUP
|
|
|
|
|
{
|
2024-11-12 00:10:02 +03:00
|
|
|
s_push(&s, *s_peek(&s));
|
2024-11-04 01:43:43 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-10-12 00:37:28 +03:00
|
|
|
|
|
|
|
|
case 10: // SWAP
|
2024-11-04 01:43:43 +03:00
|
|
|
{
|
2024-11-12 00:10:02 +03:00
|
|
|
void* x = s_pop(&s);
|
|
|
|
|
void* y = s_pop(&s);
|
|
|
|
|
s_push(&s, y);
|
|
|
|
|
s_push(&s, x);
|
|
|
|
|
|
|
|
|
|
// if (s.sp + 1 >= s.stack + STACK_SIZE ||
|
|
|
|
|
// (s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) {
|
|
|
|
|
// s_failure(&s, "can't SWAP: < 2 values on stack");
|
|
|
|
|
// }
|
|
|
|
|
// void *v = *s.sp;
|
|
|
|
|
// push_extra_root(v);
|
|
|
|
|
// *s.sp = *(s.sp + 1);
|
|
|
|
|
// *(s.sp + 1) = v;
|
|
|
|
|
// pop_extra_root(v);
|
2024-11-04 01:43:43 +03:00
|
|
|
} break;
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 11: // ELEM
|
2024-11-04 01:43:43 +03:00
|
|
|
{
|
|
|
|
|
aint index = s_pop_i(&s);
|
2024-11-06 02:28:46 +03:00
|
|
|
void *data = s_pop(&s);
|
|
|
|
|
s_push(&s, Belem(data, index));
|
2024-11-04 01:43:43 +03:00
|
|
|
} break;
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-25 19:38:45 +03:00
|
|
|
case 2: { // LD %d
|
2024-11-04 01:43:43 +03:00
|
|
|
void **var_ptr =
|
2024-11-12 00:10:02 +03:00
|
|
|
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push(&s, *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-10-25 19:38:45 +03:00
|
|
|
case 3: { // LDA %d
|
2024-11-04 01:43:43 +03:00
|
|
|
void **var_ptr =
|
2024-11-12 00:10:02 +03:00
|
|
|
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
2024-11-04 01:43:43 +03:00
|
|
|
s_push(&s, var_ptr);
|
2024-10-25 19:38:45 +03:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 4: { // ST %d
|
2024-11-04 01:43:43 +03:00
|
|
|
void **var_ptr =
|
2024-11-12 00:10:02 +03:00
|
|
|
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
2024-11-04 01:43:43 +03:00
|
|
|
*var_ptr = *s_peek(&s);
|
2024-10-25 19:38:45 +03:00
|
|
|
break;
|
|
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-11 17:07:04 +03:00
|
|
|
case 5:
|
|
|
|
|
switch (l) {
|
2024-11-04 01:43:43 +03:00
|
|
|
case 0: { // CJMPz 0x%.8x
|
|
|
|
|
int jmp_p = ip_read_int(&s.ip);
|
|
|
|
|
|
|
|
|
|
if (jmp_p < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "negative file offset jumps are not allowed");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
if (UNBOX(s_pop_i(&s)) == 0) {
|
|
|
|
|
s.ip = 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-10-12 00:37:28 +03:00
|
|
|
case 1: { // CJMPnz 0x%.8x
|
2024-11-04 01:43:43 +03:00
|
|
|
int jmp_p = ip_read_int(&s.ip);
|
|
|
|
|
|
|
|
|
|
if (jmp_p < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "negative file offset jumps are not allowed");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
if (UNBOX(s_pop_i(&s)) != 0) {
|
|
|
|
|
s.ip = 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
|
|
|
|
|
|
|
|
case 2: { // BEGIN %d %d // function begin
|
|
|
|
|
int args_sz = ip_read_int(&s.ip);
|
|
|
|
|
int locals_sz = ip_read_int(&s.ip);
|
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-11-07 01:14:57 +03:00
|
|
|
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
|
|
|
|
locals_sz);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
case 3: { // CBEGIN %d %d
|
|
|
|
|
// NOTE: example not found, no checks done
|
2024-11-04 01:43:43 +03:00
|
|
|
int args_sz = ip_read_int(&s.ip);
|
|
|
|
|
int locals_sz = ip_read_int(&s.ip);
|
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-11-07 01:14:57 +03:00
|
|
|
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
|
|
|
|
locals_sz);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-07 01:14:57 +03:00
|
|
|
case 4: // CLOSURE 0x%.8x
|
|
|
|
|
{
|
|
|
|
|
aint call_offset = ip_read_int(&s.ip);
|
|
|
|
|
aint args_count = ip_read_int(&s.ip);
|
|
|
|
|
for (aint i = 0; i < args_count; i++) {
|
|
|
|
|
aint arg_type = ip_read_byte(&s.ip);
|
|
|
|
|
aint 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-11-12 00:10:02 +03:00
|
|
|
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
2024-11-07 01:14:57 +03:00
|
|
|
s_push(&s, *var_ptr);
|
|
|
|
|
}
|
2024-11-07 19:31:25 +03:00
|
|
|
s_push(&s, bf->code_ptr + call_offset);
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 01:14:57 +03:00
|
|
|
void *closure = Bclosure((aint *)s.sp, args_count);
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 01:14:57 +03:00
|
|
|
push_extra_root(closure);
|
|
|
|
|
s_popn(&s, args_count + 1);
|
|
|
|
|
s_push(&s, closure);
|
|
|
|
|
pop_extra_root(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-07 01:14:57 +03:00
|
|
|
case 5: { // 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
|
|
|
|
|
|
|
|
call_happened = true;
|
|
|
|
|
s.is_closure_call = true;
|
|
|
|
|
s.call_ip = s.ip;
|
|
|
|
|
|
2024-11-07 00:56:21 +03:00
|
|
|
s.ip = Belem(*s_nth(&s, args_count), BOX(0)); // use offset instead ??
|
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-07 01:14:57 +03:00
|
|
|
case 6: { // CALL 0x%.8x %d // call function
|
2024-11-06 02:28:46 +03:00
|
|
|
int call_p = ip_read_int(&s.ip);
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (call_p < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "negative file offset jumps are not allowed");
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
s.ip = bf->code_ptr + call_p;
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-06 02:28:46 +03:00
|
|
|
case 7: { // TAG %s %d
|
2024-11-07 01:14:57 +03:00
|
|
|
const char *name = ip_read_string(&s.ip, bf);
|
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-11-07 01:14:57 +03:00
|
|
|
printf("tag hash is %i, n is %i, peek is %i\n",
|
|
|
|
|
UNBOX(LtagHash((char *)name)), args_count, s_peek(&s));
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-11-06 02:28:46 +03:00
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
s_push_i(&s, Btag(s_pop(&s), 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
|
|
|
|
|
|
|
|
case 8: // ARRAY %d
|
2024-11-09 23:32:09 +03:00
|
|
|
s_push_i(&s, Barray_patt(s_pop(&s), 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-09 23:32:09 +03:00
|
|
|
case 9: { // FAIL %d %d
|
|
|
|
|
int line = ip_read_int(&s.ip); // ??
|
|
|
|
|
int col = ip_read_int(&s.ip); // ??
|
|
|
|
|
Bmatch_failure(s_pop(&s), 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-10-12 00:37:28 +03:00
|
|
|
case 10: // 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;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-11-06 02:28:46 +03:00
|
|
|
case 6: // PATT pats[l]
|
2024-11-02 01:19:54 +03:00
|
|
|
// {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}
|
|
|
|
|
switch (l) {
|
2024-11-06 02:28:46 +03:00
|
|
|
case 0: // =str
|
|
|
|
|
s_push_i(&s, Bstring_patt(s_pop(&s), s_pop(&s)));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
|
|
|
|
case 1: // #string
|
|
|
|
|
s_push_i(&s, Bstring_tag_patt(s_pop(&s)));
|
|
|
|
|
break;
|
|
|
|
|
case 2: // #array
|
|
|
|
|
s_push_i(&s, Barray_tag_patt(s_pop(&s)));
|
|
|
|
|
break;
|
|
|
|
|
case 3: // #sexp
|
|
|
|
|
s_push_i(&s, Bsexp_tag_patt(s_pop(&s)));
|
|
|
|
|
break;
|
2024-11-07 19:31:25 +03:00
|
|
|
case 4: // #ref
|
|
|
|
|
s_push_i(&s, Bunboxed_patt(s_pop(&s)));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
2024-11-07 19:31:25 +03:00
|
|
|
case 5: // #val
|
|
|
|
|
s_push_i(&s, Bboxed_patt(s_pop(&s)));
|
2024-11-02 01:19:54 +03:00
|
|
|
break;
|
|
|
|
|
case 6: // #fun
|
|
|
|
|
s_push_i(&s, Bclosure_tag_patt(s_pop(&s)));
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
case 7: {
|
|
|
|
|
switch (l) {
|
2024-10-12 00:37:28 +03:00
|
|
|
case 0: // CALL Lread
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push_i(&s, Lread());
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-04 01:43:43 +03:00
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 1: // CALL Lwrite
|
2024-11-04 01:43:43 +03:00
|
|
|
Lwrite(*s_peek_i(&s));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 2: // CALL Llength
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push_i(&s, Llength(s_pop(&s)));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-11-02 01:19:54 +03:00
|
|
|
case 3: { // CALL Lstring
|
2024-11-04 01:43:43 +03:00
|
|
|
void *val = s_pop(&s);
|
2024-11-07 01:14:57 +03:00
|
|
|
void *str = Lstring((aint *)&val);
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push(&s, str);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-02 01:19:54 +03:00
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
|
2024-11-02 01:19:54 +03:00
|
|
|
case 4: { // CALL Barray %d
|
2024-11-09 23:32:09 +03:00
|
|
|
size_t elem_count = ip_read_int(&s.ip);
|
|
|
|
|
if (elem_count < 0) {
|
2024-11-12 00:10:02 +03:00
|
|
|
s_failure(&s, "elements count should be >= 0");
|
2024-11-09 23:32:09 +03:00
|
|
|
}
|
|
|
|
|
|
2024-11-12 00:10:02 +03:00
|
|
|
// void **buffer = calloc(elem_count, sizeof(void *));
|
2024-11-09 23:32:09 +03:00
|
|
|
for (size_t i = 0; i < elem_count; ++i) {
|
|
|
|
|
buffer[elem_count - i - 1] = s_pop(&s);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-07 19:31:25 +03:00
|
|
|
void *array =
|
2024-11-09 23:32:09 +03:00
|
|
|
Barray((aint *)buffer, BOX(elem_count)); // NOTE: not shure if elems should be added
|
|
|
|
|
// s_popn(&s, elem_count);
|
2024-11-02 01:19:54 +03:00
|
|
|
s_push(&s, array);
|
2024-11-09 23:32:09 +03:00
|
|
|
|
2024-11-12 00:10:02 +03:00
|
|
|
// free(buffer);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-11-02 01:19:54 +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
|
|
|
}
|
2024-11-04 01:43:43 +03:00
|
|
|
} break;
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
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
|
2024-11-04 01:43:43 +03:00
|
|
|
printf("--- run end ---\n");
|
2024-11-07 19:07:26 +03:00
|
|
|
#endif
|
2024-10-31 21:08:48 +03:00
|
|
|
cleanup_state(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|