#include "interpreter.h"
#include "global_mem.h"
#include <stdio.h>
#include <stdlib.h>
//#include <time.h>
#include <string>
#include <sstream>
#ifdef FOR_DEBUGGER
#include "mainwindow.h"
//#include <QString>
//#include <QMessageBox>
uint8_t datastackindex = 0; //растёт вверх
uint8_t callstackindex = 0; //растёт вверх
data64bit datastack[STACKSIZE];
uint64_t callstack[STACKSIZE];
data64bit locals[LOCALSSIZE];
uint64_t *pc;
uint64_t *prog;
#endif //FOR_DEBUGGER
void myprintstr(uint64_t *prog, uint64_t addr){
char s[100];
char *ps=s;
uint64_t *tmppc=prog+addr;
while(*tmppc)
*ps++=static_cast<char>(*tmppc++);
*ps=0;
myprint(reinterpret_cast<char *>(s));
}
#ifdef FOR_DEBUGGER
void pushpar(uint64_t progpar){
PUSH(progpar);
}
int interpret() {
#else //FOR_DEBUGGER
int interpret(uint64_t *prog, uint64_t progpar) {
uint64_t *pc = prog;
uint8_t datastackindex = 0; //растёт вверх
uint8_t callstackindex = 0; //растёт вверх
data64bit datastack[STACKSIZE];
uint64_t callstack[STACKSIZE];
data64bit locals[LOCALSSIZE];
PUSH(progpar);
#endif //FOR_DEBUGGER
const void *labels[] = {
&&op_nop, /* !!! НЕ ГЕНЕРИТСЯ !!! */
&&op_add, /* OK */
&&op_sub, /* OK */
&&op_mul, /* OK */
&&op_div, /* OK */
&&op_divsigned, /* OK */
&&op_if0goto, /* OK */
&&op_goto, /* OK */
&&op_dup, /* OK */
&&op_drop, /* !!! НЕ ГЕНЕРИТСЯ !!! */
&&op_swap, /* OK */
&&op_readvar, /* OK */
&&op_writevar, /* OK */
&&op_const, /* OK */
&&op_ret, /* OK */
&&op_call, /* OK */
&&op_and, /* OK */
&&op_or, /* OK */
&&op_xor, /* OK */
&&op_eq, /* OK */
&&op_moreeq, /* OK */
&&op_moreeqsigned, /* OK */
&&op_inv, /* OK */
&&op_rst, /* OK */
&&op_shr, /* OK */
&&op_shrsigned, /* OK */
&&op_shl, /* OK */
&&op_mod, /* !!! НЕ ГЕНЕРИТСЯ !!! */
&&op_done, /* OK */
&&op_addfloat, /* OK */
&&op_subfloat, /* OK */
&&op_mulfloat, /* OK */
&&op_divfloat, /* OK */
&&op_negfloat, /* OK */
&&op_floattoint, /* OK */
&&op_inttofloat, /* OK */
&&op_eqfloat,
&&op_moreeqfloat, /* OK */
&&op_readconstvar,
&&op_writeconstvar,
&&op_incconstvar,
&&op_decconstvar
};
MAINDISPATCH;/*!*/
op_nop: {
DISPATCH;
}
op_add: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u+par2);
DISPATCH;
}
op_sub: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u-par2);
DISPATCH;
}
op_mul: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u*par2);
DISPATCH;
}
op_div: {
uint64_t par2 = POP.u;
if (par2)
TOS.u = (TOS.u/par2);
DISPATCH;
}
op_divsigned: {/*!*/
int64_t par2 = POP.i;
if (par2)
TOS.i = TOS.i/par2;
DISPATCH;
}
op_mod: {
uint64_t par2 = POP.u;
if (par2)
TOS.u = (TOS.u-((TOS.u/par2)*par2));
DISPATCH;
}
op_and: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u&par2);
DISPATCH;
}
op_or: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u|par2);
DISPATCH;
}
op_xor: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u^par2);
DISPATCH;
}
op_inv: {
TOS.u = ~TOS.u;
DISPATCH;
}
op_shr: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u>>par2);
DISPATCH;
}
op_shrsigned: {
uint64_t par2 = POP.u;
TOS.i = (TOS.i>>par2);
DISPATCH;
}
op_shl: {
uint64_t par2 = POP.u;
TOS.u = (TOS.u<<par2);
DISPATCH;
}
op_eq: {
uint64_t par2 = POP.u;
TOS.i = (TOS.u==par2)?-1:0;
DISPATCH;
}
op_moreeq: {
uint64_t par2 = POP.u;
TOS.i = (TOS.u>=par2)?-1:0;
DISPATCH;
}
op_moreeqsigned: {
int64_t par2 = POP.i;
TOS.i = (TOS.i>=par2)?-1:0;
DISPATCH;
}
op_const: {
PUSH(GETPAR);
DISPATCH;
}
op_dup: {
uint64_t par1 = TOS.u;
PUSH(par1);
DISPATCH;
}
op_drop: {
POP;
DISPATCH;
}
op_swap: {
uint64_t par2 = POP.u;
uint64_t par1 = TOS.u;
TOS.u = par2;
PUSH(par1);
DISPATCH;
}
//pointers:
//0x00000000 - global data segment (VAL)
//0x40000000 - code segment (prog)
//0x80000000 - local data segment (locals)
op_readvar: {
if (TOS.u < static_cast<uint64_t>(N)) {
TOS.u = VAL(TOS.u);
}else if ((TOS.u < 0x80000000)/*&&((TOS.u&0x3fffffff) < progsize)*/) {
TOS.u = prog[TOS.u&0x3fffffff];
}else if ((TOS.u&0x3fffffff) < LOCALSSIZE) {
TOS.u = locals[TOS.u&0x3fffffff].u;
}
DISPATCH;
}
op_writevar: {
uint64_t vardata = POP.u;
uint64_t varaddr = POP.u;
if (varaddr < static_cast<uint64_t>(N)) {
POKEVAL(varaddr, vardata);
}else if ((varaddr < 0x80000000)/*&&((varaddr&0x3fffffff) < progsize)*/) {
prog[varaddr&0x3fffffff] = vardata; //по идее не нужно
}else if ((varaddr&0x3fffffff) < LOCALSSIZE) {
locals[varaddr&0x3fffffff].u = vardata;
}
DISPATCH;
}
op_goto: {
pc = prog+((*pc)&0x3fffffff); //нельзя GETPAR - делает pc++
DISPATCH;
}
op_if0goto: {
if (!POP.u) {
pc = prog+((*pc)&0x3fffffff); //нельзя GETPAR - делает pc++
}else {
pc++;
}
DISPATCH;
}
op_call: {
uint64_t callpc = GETPAR;
PUSHCALLSTACK(reinterpret_cast<uint64_t>(pc));
pc = prog+(callpc&0x3fffffff);
DISPATCH;
}
op_ret: {
pc = reinterpret_cast<uint64_t*>(POPCALLSTACK);
DISPATCH;
}
op_addfloat: {
double par2 = POP.d;
TOS.d = TOS.d+par2;
DISPATCH;
}
op_subfloat: {
double par2 = POP.d;
TOS.d = TOS.d - par2;
DISPATCH;
}
op_mulfloat: {
double par2 = POP.d;
TOS.d = TOS.d * par2;
DISPATCH;
}
op_divfloat: {
double par2 = POP.d;
TOS.d = TOS.d / par2;
DISPATCH;
}
op_negfloat: {
TOS.d = -TOS.d;
DISPATCH;
}
op_floattoint: {
TOS.i = static_cast<int64_t>(rint(TOS.d));
DISPATCH;
}
op_inttofloat: {
TOS.d = TOS.i;
DISPATCH;
}
op_eqfloat: {
uint64_t par2 = POP.u; //.u - чтобы не получать warning о сравнении 2х double
TOS.i = (TOS.u==par2)?-1:0;
DISPATCH;
}
op_moreeqfloat: {
double par2 = POP.d;
TOS.i = (TOS.d>=par2)?-1:0;
DISPATCH;
}
op_done: {
return static_cast<int>(stcSMData[0].current_value.i);
}
op_readconstvar:{
uint64_t addr=GETPAR;
if (addr < static_cast<uint64_t>(N)) {
PUSH(VAL(addr));
}else if ((addr < 0x80000000)/*&&((TOS.u&0x3fffffff) < progsize)*/) {
PUSH(prog[addr]);
}else if ((addr&0x3fffffff) < LOCALSSIZE) {
PUSH(locals[addr].u);
}
DISPATCH;
}
op_writeconstvar:{
uint64_t vardata = POP.u;
uint64_t varaddr = GETPAR;
if (varaddr < static_cast<uint64_t>(N)) {
POKEVAL(varaddr, vardata);
}else if ((varaddr < 0x80000000)/*&&((varaddr&0x3fffffff) < progsize)*/) {
prog[varaddr&0x3fffffff] = vardata; //по идее не нужно
}else if ((varaddr&0x3fffffff) < LOCALSSIZE) {
locals[varaddr&0x3fffffff].u = vardata;
}
DISPATCH;
}
op_incconstvar:{
uint64_t addr = GETPAR;
if (addr < static_cast<uint64_t>(N)) {
POKEVAL(addr, VAL(addr)+1);
}else if ((addr < 0x80000000)/*&&((varaddr&0x3fffffff) < progsize)*/) {
prog[addr&0x3fffffff]++; //по идее не нужно
}else if ((addr&0x3fffffff) < LOCALSSIZE) {
locals[addr&0x3fffffff].u++;
}
DISPATCH;
}
op_decconstvar:{
uint64_t addr = GETPAR;
if (addr < static_cast<uint64_t>(N)) {
POKEVAL(addr, VAL(addr)-1);
}else if ((addr < 0x80000000)/*&&((varaddr&0x3fffffff) < progsize)*/) {
prog[addr&0x3fffffff]--; //по идее не нужно
}else if ((addr&0x3fffffff) < LOCALSSIZE) {
locals[addr&0x3fffffff].u--;
}
DISPATCH;
}
op_rst: {
uint64_t op = GETPAR;
double par1;
uint64_t upar1;
switch (op) {
//case RST_NOP: //fn_nop:
// break;
case RST_SIN: //fn_sin:{
TOS.d=sin(TOS.d);
break;
case RST_COS: //fn_cos:{
TOS.d=cos(TOS.d);
break;
case RST_ATAN: //fn_atan:{
TOS.d=atan(TOS.d);
break;
case RST_ATAN2: //fn_atan2:{
par1 = POP.d;
TOS.d = atan2(TOS.d,par1);
break;
case RST_EXP: //fn_exp:{
TOS.d=exp(TOS.d);
break;
case RST_LOG: //fn_log:{
TOS.d=log(TOS.d);
break;
case RST_SQRT: //fn_sqrt:{
TOS.d=sqrt(TOS.d);
break;
case RST_ABS: //fn_abs:{
TOS.d=abs(TOS.d);
break;
case RST_ACOS: //fn_acos:{
TOS.d=acos(TOS.d);
break;
case RST_ACOSH: //fn_acosh:{
TOS.d=acosh(TOS.d);
break;
case RST_ASIN: //fn_asin:{
TOS.d=asin(TOS.d);
break;
case RST_ASINH: //fn_asinh:{
TOS.d=asinh(TOS.d);
break;
case RST_ATANH: //fn_atanh:{
TOS.d=atanh(TOS.d);
break;
case RST_CBRT: //fn_cbrt:{
TOS.d=cbrt(TOS.d);
break;
case RST_CEIL: //fn_ceil:{
TOS.d=ceil(TOS.d);
break;
case RST_COSH: //fn_cosh:{
TOS.d=cosh(TOS.d);
break;
case RST_HYPOT: //fn_hypot:{
par1 = POP.d;
TOS.d=hypot(TOS.d,par1);
break;
case RST_ISFINITE: //fn_isfinite:{
TOS.i=(isfinite(TOS.d)?-1:0);
break;
case RST_ISINF: //fn_isinf:{
TOS.i=(isinf(TOS.d)?-1:0);
break;
case RST_ISNAN: //fn_isnan:{
TOS.i=(isnan(TOS.d)?-1:0);
break;
case RST_J0: //fn_j0:{
//TOS.d=j0(TOS.d);
break;
case RST_J1: //fn_j1:{
//TOS.d=j1(TOS.d);
break;
case RST_JN: //fn_jn:{
par1 = POP.d;
//TOS.d=jn(static_cast<int>(TOS.i),par1);
break;
case RST_LOG10: //fn_log10:{
TOS.d=log10(TOS.d);
break;
case RST_LOG1P: //fn_log1p:{
TOS.d=log1p(TOS.d);
break;
case RST_LOGB: //fn_logb:{
TOS.d=logb(TOS.d);
break;
case RST_MAX: //fn_max:{
par1 = POP.d;
TOS.d=(TOS.d>par1?TOS.d:par1);
break;
case RST_MIN: //fn_min:{
par1 = POP.d;
TOS.d=(TOS.d<par1?TOS.d:par1);
break;
case RST_RINT: //fn_rint:{
TOS.d=rint(TOS.d);
break;
case RST_SINH: //fn_sinh:{
TOS.d=sinh(TOS.d);
break;
case RST_TAN: //fn_tan:{
TOS.d=tan(TOS.d);
break;
case RST_TANH: //fn_tanh:{
TOS.d=tanh(TOS.d);
break;
case RST_Y0: //fn_y0:{
//TOS.d=y0(TOS.d);
break;
case RST_Y1: //fn_y1:{
//TOS.d=y1(TOS.d);
break;
case RST_YN: //fn_yn:{
par1 = POP.d;
//TOS.d=yn(static_cast<int>(TOS.i),par1);
break;
case RST_POW: //fn_pow:{
par1 = POP.d;
TOS.d=pow(TOS.d,par1);
break;
case RST_PRINT: //fn_print:{
upar1 = POP.u;
myprintstr(prog, upar1);
break;
default: ;
}
DISPATCH;
}
}
#ifndef FOR_DEBUGGER
uint64_t *loadscript(int state_index, char *waspath) {
uint64_t *prog;
FILE *fileProg;
stringstream strToInt;
string stateIndex;
string path = waspath;
strToInt << state_index; // перевод из числа в строку
strToInt >> stateIndex; //
path += stateIndex;
path += ".bin";
int size;
fileProg = fopen(path.c_str(), "r");
if (fileProg) {
fseek(fileProg,0,SEEK_END);
size = ftell(fileProg);
fseek(fileProg,0,SEEK_SET);
prog = reinterpret_cast<uint64_t*>(malloc(size));
fread(prog, 1, size, fileProg);
fclose(fileProg);
} else {
prog = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
prog[0] = CMD_DONE;
}
return prog;
}
#endif //FOR_DEBUGGER