/*     
      BYTE CODE INTERPRETER . Magma 1.0 . 1996 . Sylvain HUET

         mbytec.cpp : routine d'interpretation
*/
// Modification history:
//
//$ FA(24/03/2001): Replace Minterpreter2() by Interpreter::exec()
//$ FA(24/03/2001): Minterpreter2() becomes a wrapper around Interpreter::exec()
//$ FA(26/03/2001): Set to NULL all 'bytecod' entries that are inlined inside switch
//$ FA(26/03/2001): Inline bytecodes that refer directly to OFFHINDEX
//$ FA(26/03/2001): Rewrote MBint(), MBgoto(), MBelse(), and MBstr()
//$ FA(26/03/2001): Modify MBexec(), MBexec2() and MBret() to save/restore pc register
//$ FA(28/03/2001): Modify bytecode fetching: pc is a pointer to a byte
//$ FA(01/04/2001): Test if opcode is within range only for the debug version
//$ FA(01/04/2001): Introduction of fp register as a replacement for m->h. Saving the
//                  value of m->h upon calling Interpreter::exec() and restoring
//                  it on return became obsolete and hence this code has been removed
//$ FA(01/04/2001): LifePeriod increased to 1000000 (10 times)
//$ FA(05/04/2001): Take into account new variable and field access opcodes
//$ FA(06/04/2001): Modify fetch macro to refer to the beginning of code through 'bp'
//$ FA(12/04/2001): Inline OPCOM and OPCOMV
//$ FA(12/04/2001): Bytecodes are all inlined: modify value of constant MaxOpcode
//                  and eliminate 'bytecod' table
//$ FA(17/04/2001): Move Interpreter::exec() and related constants to file interp.cpp
//                  (This file will be eliminated in the future)
//$ FA(12/11/2001): Define printCallStack() utility function as a wrapper for
//                  Interpreter::printCallStack()


//$ FA(24/03/2001): Use old C header files
extern "C" {
  #include "mmemory.h"
  #include "mbytec.h"
}
//$ FA(24/03/2001): Use Interpreter class
#include "interp.h"
//

int merrlog(int line, char *file, int ret)
{
	MMechostr(MSKRUNTIME,"line %d in %s\n",line,file);
	return ret;
}


//$ FA(24/03/2001): Minterpreter2 becomes a wrapper around Interpreter::exec()
int Minterpreter2(mmachine m, int bcinit)
{
  Interpreter interp(m);

  return interp.exec(bcinit);
}
//

int Minterpreter(mmachine m)
{
  return Minterpreter2(m, kCall);
}


/* affichage du code d'erreur */
int Mprinterror(int i)
{
  if (i==MERRMEM) MMechostr(MSKRUNTIME,"out of memory\n");
  if (i==-2/*MERRTYP*/) MMechostr(MSKRUNTIME,"syntax error\n");
  if (i==MERRRET) MMechostr(MSKRUNTIME,"return error (wrong bytecode)\n");
  if (i==MERRNUL) MMechostr(MSKRUNTIME,"division by zero error\n");
  if (i==MERRNF) MMechostr(MSKRUNTIME,"file or function not found\n");
  if (i==MERRLINK) MMechostr(MSKRUNTIME,"link error\n");
  if (i==MERRTOOLARGE) MMechostr(MSKRUNTIME,"index too large\n");
  if (i==MERREP) MMechostr(MSKRUNTIME,"empty prototype\n");
  if (i==MERRFILE) MMechostr(MSKRUNTIME,"cannot write file\n");
  if (i==MERRCLOSE) MMechostr(MSKRUNTIME,"closed machine\n");
  return 0;
}

//$ FA(12/11/2001): Wrapper around Interpreter::printCallStack() method
#if defined(RELEASE_DEVELOPER)
void printCallStack(void)
{
  if (Interpreter::current)
    Interpreter::current->printCallStack();
  else
    MMechostr(MSKTRACE, "[]\n");
}
#endif