2024-10-11 17:07:04 +03:00
|
|
|
#include "../include/interpreter.h"
|
2024-10-20 16:42:57 +03:00
|
|
|
#include "../include/types.h"
|
2024-10-11 17:07:04 +03:00
|
|
|
#include "../../runtime/runtime.h"
|
|
|
|
|
|
2024-10-20 16:42:57 +03:00
|
|
|
int ip_read_int(char** ip) {
|
2024-10-11 17:07:04 +03:00
|
|
|
*ip += sizeof(int);
|
|
|
|
|
return *(int*)((*ip) - sizeof(int));
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 16:42:57 +03:00
|
|
|
char ip_read_byte(char** ip) {
|
2024-10-11 17:07:04 +03:00
|
|
|
return *(*ip)++;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 16:42:57 +03:00
|
|
|
char* ip_read_string(char** ip, bytefile* bf) {
|
|
|
|
|
return get_string(bf, ip_read_int(ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: store globals in some way ?? // maybe some first vars ??
|
|
|
|
|
|
|
|
|
|
void run(bytefile *bf) {
|
|
|
|
|
struct State s = init_state(bf);
|
|
|
|
|
|
|
|
|
|
const char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
|
|
|
|
const char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
|
|
|
|
const char *lds [] = {"LD", "LDA", "ST"};
|
|
|
|
|
do {
|
2024-10-12 00:37:28 +03:00
|
|
|
char* before_op_ip = s.ip; // save to set s.prev_ip
|
|
|
|
|
|
2024-10-20 16:42:57 +03:00
|
|
|
char x = ip_read_byte(&s.ip),
|
2024-10-11 17:07:04 +03:00
|
|
|
h = (x & 0xF0) >> 4,
|
|
|
|
|
l = x & 0x0F;
|
|
|
|
|
|
|
|
|
|
// fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1);
|
|
|
|
|
|
|
|
|
|
switch (h) {
|
|
|
|
|
case 15:
|
|
|
|
|
goto stop;
|
|
|
|
|
|
|
|
|
|
/* BINOP */
|
2024-10-12 00:37:28 +03:00
|
|
|
case 0: // BINOP ops[l-1]
|
|
|
|
|
// TODO: all binops
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
switch (l) {
|
2024-10-12 00:37:28 +03:00
|
|
|
case 0: // CONST %d
|
2024-10-20 16:42:57 +03:00
|
|
|
s_put_i(&s, ip_read_int(&s.ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 1: // STRING %s
|
2024-10-20 16:42:57 +03:00
|
|
|
s_put_const_str(&s, ip_read_string(&s.ip, bf));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 2: // SEXP %s %d
|
2024-10-11 17:07:04 +03:00
|
|
|
// TODO: call sexp ??
|
|
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 3: // STI
|
|
|
|
|
// TODO
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 4: // STA
|
|
|
|
|
// TODO
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 5: // JMP 0x%.8x
|
2024-10-20 16:42:57 +03:00
|
|
|
s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 6: // END
|
|
|
|
|
s_exit_f(&s); // TODO: always ??, check that it is enough
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 7: // RET
|
|
|
|
|
// TODO
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 8: // DROP
|
|
|
|
|
s_drop_var(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 9: // DUP
|
|
|
|
|
{ // guess
|
|
|
|
|
struct Var v = deep_copy_var(*s.vp);
|
|
|
|
|
s_put_var(&s, v);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 10: // SWAP
|
|
|
|
|
{ // guess
|
|
|
|
|
struct Var v = *s.vp;
|
|
|
|
|
*s.vp = *(s.vp - 1);
|
|
|
|
|
*(s.vp - 1) = v;
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 11: // ELEM
|
|
|
|
|
{
|
|
|
|
|
struct Var array = s_take_var(&s);
|
|
|
|
|
struct Var index = s_take_var(&s);
|
|
|
|
|
if (array.type != ARRAY_T) {
|
|
|
|
|
failure("ERROR: elem, previous element is not array", h, l);
|
|
|
|
|
}
|
|
|
|
|
if (index.type != INT_T) {
|
|
|
|
|
failure("ERROR: elem, last element is not int", h, l);
|
|
|
|
|
}
|
|
|
|
|
s_put_var(&s, array.value.array_v[index.value.int_v]);
|
|
|
|
|
|
|
|
|
|
free_var(array);
|
|
|
|
|
free_var(index);
|
|
|
|
|
// FIXME: deal vith deletion of shallow copies of locals
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-10-12 00:37:28 +03:00
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
// fprintf (f, "%s\t", lds[h-2]);
|
|
|
|
|
switch (l) {
|
|
|
|
|
// case 0: fprintf (f, "G(%d)", INT); break;
|
|
|
|
|
// case 1: fprintf (f, "L(%d)", INT); break;
|
|
|
|
|
// case 2: fprintf (f, "A(%d)", INT); break;
|
|
|
|
|
// case 3: fprintf (f, "C(%d)", INT); break;
|
2024-10-12 00:37:28 +03:00
|
|
|
default:
|
|
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
|
switch (l) {
|
2024-10-12 00:37:28 +03:00
|
|
|
case 0: { // CJMPz 0x%.8x
|
|
|
|
|
// FIXME: TODO: jump by top stack condition ??
|
2024-10-20 16:42:57 +03:00
|
|
|
char* new_ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
2024-10-12 00:37:28 +03:00
|
|
|
if (s_take_i(&s) != 0) { // FIXME: bools ??, other vars ??
|
|
|
|
|
s.ip = new_ip;
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
|
|
|
|
case 1: { // CJMPnz 0x%.8x
|
|
|
|
|
// FIXME: TODO: jump by top stack condition ??i
|
2024-10-20 16:42:57 +03:00
|
|
|
char* new_ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
2024-10-12 00:37:28 +03:00
|
|
|
if (s_take_i(&s) == 0) { // FIXME: bools ??, other vars ??
|
|
|
|
|
s.ip = new_ip;
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
2024-10-12 00:37:28 +03:00
|
|
|
}
|
|
|
|
|
case 2: // BEGIN %d %d
|
2024-10-20 16:42:57 +03:00
|
|
|
s_enter_f(&s, s.prev_ip/*ip from call*/, ip_read_int(&s.ip), ip_read_int(&s.ip));
|
2024-10-12 00:37:28 +03:00
|
|
|
// TODO: is func enter ?
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 3: // CBEGIN %d %d
|
2024-10-20 16:42:57 +03:00
|
|
|
s_enter_f(&s, s.prev_ip/*ip from call*/, ip_read_int(&s.ip), ip_read_int(&s.ip));
|
2024-10-12 00:37:28 +03:00
|
|
|
// TODO: is func enter ?
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 4: // CLOSURE 0x%.8x
|
|
|
|
|
{
|
2024-10-20 16:42:57 +03:00
|
|
|
int n = ip_read_int(&s.ip);
|
2024-10-12 00:37:28 +03:00
|
|
|
for (int i = 0; i < n; i++) {
|
2024-10-20 16:42:57 +03:00
|
|
|
switch (ip_read_byte(&s.ip)) {
|
2024-10-12 00:37:28 +03:00
|
|
|
// case 0: // G(%d)
|
|
|
|
|
// case 1: // L(%d)
|
|
|
|
|
// case 2: // A(%d)
|
|
|
|
|
// case 3: // C(%d)
|
|
|
|
|
default:
|
|
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-11 17:07:04 +03:00
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 5: // CALLC %d
|
|
|
|
|
// TODO: no arguments given ??
|
|
|
|
|
// TODO: jump only ??
|
2024-10-20 16:42:57 +03:00
|
|
|
s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 6: // CALL 0x%.8x %d
|
|
|
|
|
// TODO: second arg is given params amount ??
|
|
|
|
|
// TODO: jump only ??
|
2024-10-20 16:42:57 +03:00
|
|
|
s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 7: // TAG %s
|
|
|
|
|
// TODO: ??
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 8: // ARRAY %d
|
2024-10-20 16:42:57 +03:00
|
|
|
s_put_array(&s, ip_read_int(&s.ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 9: // FAIL %d %d
|
|
|
|
|
// TODO: ??
|
2024-10-20 16:42:57 +03:00
|
|
|
failure("FAIL: %d-%d\n", ip_read_int(&s.ip), ip_read_int(&s.ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 10: // LINE %d
|
|
|
|
|
// maybe some metainfo should be collected
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-10-12 00:37:28 +03:00
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 6: // PATT pats[l]
|
|
|
|
|
// TODO: JMP if same to pattern ??
|
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
|
|
|
|
|
f_read(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 1: // CALL Lwrite
|
|
|
|
|
f_write(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 2: // CALL Llength
|
|
|
|
|
f_length(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 3: // CALL Lstring
|
|
|
|
|
f_string(&s);
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
case 4: // CALL Barray %d
|
2024-10-20 16:42:57 +03:00
|
|
|
f_array(&s, ip_read_int(&s.ip));
|
2024-10-11 17:07:04 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-10-12 00:37:28 +03:00
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-10-12 00:37:28 +03:00
|
|
|
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
|
2024-10-12 00:37:28 +03:00
|
|
|
s.prev_ip = before_op_ip;
|
2024-10-11 17:07:04 +03:00
|
|
|
}
|
|
|
|
|
while (1);
|
2024-10-12 00:37:28 +03:00
|
|
|
stop:;
|
2024-10-11 17:07:04 +03:00
|
|
|
free_state(&s);
|
|
|
|
|
}
|