#ifndef VM
#define VM

//
// Virtual Machine
//
typedef int             ptr_t; // An index into the "data" array.
typedef unsigned char   byte;

class VirtualMachin
  {
  //
  // Constants
  //
  #define STACK_SIZE  20

  //
  // Member Data
  //
  private:
    byte*   code;       // Code memory (read only)
    ptr_t   codeSize;   // Points to the last byte (always 0xFE)
    byte*   data;       // Data Memory
    ptr_t   dataSize;   // Points to the last byte (always 0xFF)

    ptr_t   pc;         // Program Counter points to the next instruction to be executed.
    long    stack[STACK_SIZE];
    long*   sp;         // TOS = sp[0], TOS-1 = sp[1]
    long*   fullStack;  // = &stack[STACK_SIZE-1]

  //
  // Methods
  //
  public:
    VirtualMachin( char*  code, ptr_t  codeSize, char*  data, ptr_t   dataSize );
    void  step();

  //
  // Macros
  //
  #define PUSH(x) ( sp<fullStack ? *(++sp) = (x) : 0 )
  #define POP() ( sp>=stack ? *(sp--) : 0 )

  private:
    long  VirtualMachin::getArg( byte  where );
  };

#endif