/*  -
   Copyright (C) 2006 Weongyo Jeong (weongyo@gmail.com)

This file is part of ROVM.

ROVM is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

ROVM is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#ifndef _ROVM_CORE_H
#define _ROVM_CORE_H

/**
   @file core.h
   @breif ROVM 에서 실제 virtual machine 과 관련된 루틴들의 헤더.
*/

typedef struct rovm_stack RvValue;
typedef struct rovm_stack rovm_stack_t;

#define ROVM_EVALUE_TYPEDEF     /**< el.h 와의 충돌 방지를 위해.  */

/** Value 값이 없을 경우 이를 반환하게 된다.  */
#define NULL_VALUE              (RvValue *) 0

/**
   @defgroup ROVM 가상 머신
   @{
*/

enum rovm_stack_type
  {
#define DEF_TYPE(ENUM, NAME, TYPE, SIZE)   ENUM ,
#include "type.def"
#undef DEF_TYPE
    /** 현재 ROVM Server 상에서 Stack Type 의 총 갯수를 의미한다.  총 갯수는
    type.def 파일에 정의되어 있는 DEF_TYPE 의 갯수이다.  */
    MAX_STACK_TYPE
  };

#define STACK_TYPE(NODE)                ((NODE)->type)
#define SET_STACK_TYPE(NODE, TYPE)      (NODE)->type = TYPE
#define STACK_IS_STRINGVALUE(NODE)      ((NODE)->is_stringvalue)
#define STACK_IS_ARRAYVALUE(NODE)       ((NODE)->is_arrayvalue)
#define SET_STACK_V_BOOLEAN(NODE)       ((NODE)->v._uchar)
#define SET_STACK_V_CHAR(NODE)          ((NODE)->v._char)
#define SET_STACK_V_SHORT(NODE)         ((NODE)->v._short)
#define SET_STACK_V_INT(NODE)           ((NODE)->v._int)
#define SET_STACK_V_FLOAT(NODE)         ((NODE)->v._float)
#define SET_STACK_V_DOUBLE(NODE)        ((NODE)->v._double)
#define SET_STACK_V_ADDR(NODE)          ((NODE)->v._addr)
#define SET_STACK_V_OBJREF(NODE)        (SET_STACK_V_ADDR (NODE))
#define SET_STACK_V_STRINGREF(NODE)     (SET_STACK_V_ADDR (NODE))
#define SET_STACK_V_ARRAYREF(NODE)      (SET_STACK_V_ADDR (NODE))
#define SET_STACK_VALUE(NODE, TYPE, VAL)        \
  SET_STACK_V_##TYPE (NODE) = VAL;              \
  SET_STACK_TYPE (NODE, STACK_TYPE_##TYPE);

#define GET_STACK_V_BOOLEAN(NODE)       ((NODE)->v._uchar)
#define GET_STACK_V_CHAR(NODE)          ((NODE)->v._char)
#define GET_STACK_V_SHORT(NODE)         ((NODE)->v._short)
#define GET_STACK_V_INT(NODE)           ((NODE)->v._int)
#define GET_STACK_V_FLOAT(NODE)         ((NODE)->v._float)
#define GET_STACK_V_DOUBLE(NODE)        ((NODE)->v._double)
#define GET_STACK_V_ADDR(NODE)          ((NODE)->v._addr)
#define GET_STACK_V_OBJREF(NODE)        ((RvObject *) GET_STACK_V_ADDR (NODE))
#define GET_STACK_V_STRINGREF(NODE)     ((RvObject *) GET_STACK_V_ADDR (NODE))
#define GET_STACK_V_ARRAYREF(NODE)      ((RvObject *) GET_STACK_V_ADDR (NODE))

#define GET_STACK_VALUE(TYPE, NODE)             GET_STACK_V_##TYPE (NODE)


/**
   가상 머신이 사용하는 스택을 표현하는 구조체로써 이 하나가 하나의 스택 slot 을
   나타낸다.

   @note 현재 2005년 1월 29일 설계로는 ROVM 과 관련된 모든 메모리 관련 부분들은
         struct ticket 구조체가 가지고 있는 것으로 설계가 되어 있다.  즉 ROVM
         이 사용하는 모든 메모리 객체는 ticket 구조체에 모두 들어 있으며 이를
         통해서 접근이 되도록 설계가 되어 있다는 것이다.

         이렇게 하는 이유는 VM 을 설계하다보면 여기 저기로 흩어질 수 있는 메모리
         관리 부분을 한 곳으로 집중하기 위해서이다.
 */
struct rovm_stack
{
  /**
     스택의 type 을 나타내기 위해서 사용되는 변수이다.  현재 스택의 type 으로는
     아래와 같은 것이 정의되어 있다.

       - STACK_TYPE_NUMBER
       - STACK_TYPE_OBJREF

     이것이 정의된 이유는 연산과정에서 발생할 수 있는 objref + number 과 같은
     비정상적인 패턴에 대한 exception 을 발생시키기 위해서이다.
   */
  unsigned type : 8;

  /* 아래의 두 flag 는 TYPE 이 STACK_TYPE_ARRAYREF 일 경우 일 때만 특별히
     설정되는 것으로 아래의 값의 _addr 이 특별하게 다루어질 필요가 있음을 가르킵니다.  */
  unsigned is_stringvalue : 1;
  unsigned is_arrayvalue : 1;

  /** 아직 사용되지 않으며, 예약된 bit.  */
  unsigned unused : 24;

  /**
     실제 값을 담게 되는 union 구조체.

     @note (20060129) 아직 확정된 것이 존재하지 않기 때문에, 내용은 다소 변경될
           수 있다.  또한 아래에서 사용한 type 의 경우, 머신마다 컴파일러 마다
           크기가 다르기 때문에 이에 대한 통일된 모형이 아직 존재하지 않아, 다른
           머신 혹은 컴파일러에서 빌드시 제대로 프로그램이 안돌아갈 소지가 다분하다.
   */
  union
  {
    unsigned char _uchar;       /**< 1 바이트 boolean 형일 경우.  */
    char _char;                 /**< 1 바이트 char 형일 경우.  */
    short _short;               /**< 2 바이트 short 형일 경우.  */
    int _int;                   /**< 4 바이트 integer 형일 경우.  */
    float _float;               /**< 4 바이트 float 형일 경우.  */
    double _double;             /**< 8 바이트 double 형일 경우.  */
    void *_addr;                /**< 주소 형식의 값일 경우.  */
  } v;
};

struct ticket;
extern int rovmcore_main (request_rec *, struct ticket *, rc_opcode_t *, rc_size_t);

/**
   @}
*/

#endif
