//
// interp.h
// Interpreter class
// F.J. Alberti
//
// Modification history:
// FA   15/06/2001   Define Interpreter::exec() as a wrapper around Interpreter::_exec()
//                   to handle VM state changes and callstack creation/destruction notification
// FA   08/08/2001   Add the getCallStackRegisters() shared (static) method
// FA   03/09/2001   Add pc register as an instance variable in the debugger-aware version,
//                   and define the accessor method getPC()
// FA   12/11/2001   Replace SCOL_DEBUGGER_AWARE by RELEASE_DEVELOPER
//                   Add printCallStack() method
//                   Define getPC(), getBP() and getFP() as const
//

#ifndef _INTERP_H_
#define _INTERP_H_


#include "base.h"
#include "opcode.h"
#include "stack.h"

extern "C" {
#include "mbytec.h"
#include "mmemory.h"
}


// Native function type
typedef int (*Native)(mmachine);


class Interpreter {
public:
  Interpreter(mmachine _m);
  ~Interpreter();

  int exec(int opcode);
  int call();
#if defined(RELEASE_DEVELOPER)
  int32 getPC() const;
  int32 getBP() const;
  int32 getFP() const;
  void printCallStack() const;

  static bool getCallStackRegisters(const Interpreter* interp, uint frame, int32* pbp, int32* pfp);
  static bool getCallStackRegisters(uint frame, int32* pbp, int32* pfp);
#endif

  static Interpreter* current;

private:
  mmachine m;             // executing context
#if defined(RELEASE_DEVELOPER)
  int32    pc;            // program counter
  int32    fp;            // frame pointer
  int32    bp;            // base pointer of operand stack
#endif

  int _exec(int opcode);
};


inline int Interpreter::call()
{
  return exec(kCall);
}


#if defined(RELEASE_DEVELOPER)
inline int32 Interpreter::getPC() const
{
  return pc;
}


inline int32 Interpreter::getFP() const
{
  return fp;
}


inline int32 Interpreter::getBP() const
{
  return bp;
}


inline bool Interpreter::getCallStackRegisters(uint frame, int32* pbp, int32* pfp)
// Returns the bp and fp register values of frame 'frame' of the current
// executing interpreter
{
  return getCallStackRegisters(current, frame, pbp, pfp);
}
#endif


#endif // interp.h