/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/*
 *  JavaScript Interpreter
 *  The JavaScript Interpreter is used for executing JavaScript programs
 *  in EWB that control user events on buttons, restrict inputs on textlines
 *  and so on.
 *
 *  Developmened by: Institute of Artificial Intelligence & Robotics
 *                   of Xi'an Jiaotong University
 *
 *  Create by:      Tian Wenqiang
 *  Last modified:  2001-11-13 19:51
 */
/* this file define the types need by JavaScript Interpreter */

#ifndef _JS_TYPES_P_H_
#define _JS_TYPES_P_H_

/* Macros */
/* Type tags stored in the low bits of a jsVal. */
#define JS_VAL_OBJECT           0x0      /* untagged reference to object */
#define JS_VAL_INT              0x1      /* tagged 31-bit integer value */
#define JS_VAL_DOUBLE           0x4      /* tagged reference to double */
#define JS_VAL_STRING           0x6      /* tagged reference to string */
#define JS_VAL_BOOLEAN          0x2      /* tagged boolean value */

/* Type tag bitfield length and derived macros. */
#define JS_VAL_TAGBITS          3
#define JS_VAL_TAGMASK          ((1L << (JS_VAL_TAGBITS)) - 1)
#define JS_VAL_TAG(v)           ((v) & JS_VAL_TAGMASK)
#define JS_VAL_SETTAG(v, t)     ((v) | (t))
#define JS_VAL_CLRTAG(v)        ((v) & ~(jsVal_t) JS_VAL_TAGMASK)

/* Well-known JS values. */
#define JS_VAL_VOID             JS_INT_TO_VAL(0 -  JS_VAL_INT_POW2(30))
#define JS_VAL_NULL             JS_OBJECT_TO_VAL(0)
#define JS_VAL_ZERO             JS_INT_TO_VAL(0)
#define JS_VAL_ONE              JS_INT_TO_VAL(1)
#define JS_VAL_FALSE            JS_BOOLEAN_TO_VAL(0)
#define JS_VAL_TRUE             JS_BOOLEAN_TO_VAL(1)

/* Predicates for type testing. */
#define JS_VAL_IS_OBJECT(v)      (JS_VAL_TAG(v) == JS_VAL_OBJECT)
#define JS_VAL_IS_NUMBER(v)      (JS_VAL_IS_INT(v) || JS_VAL_IS_DOUBLE(v))
#define JS_VAL_IS_INT(v)         (((v) & JS_VAL_INT) && (v) != JS_VAL_VOID)
#define JS_VAL_IS_DOUBLE(v)      (JS_VAL_TAG(v) == JS_VAL_DOUBLE)
#define JS_VAL_IS_STRING(v)      (JS_VAL_TAG(v) == JS_VAL_STRING)
#define JS_VAL_IS_BOOLEAN(v)     (JS_VAL_TAG(v) == JS_VAL_BOOLEAN)
#define JS_VAL_IS_NULL(v)        ((v) == JS_VAL_NULL)
#define JS_VAL_IS_VOID(v)        ((v) == JS_VAL_VOID)
#define JS_VAL_IS_PRIMITIVE(v)   (!JS_VAL_IS_OBJECT(v) || JS_VAL_IS_NULL(v))

/* Objects, strings, and doubles are GC'ed. */
#define JS_VAL_IS_GCTHING(v)    (!((v) & JS_VAL_INT) && !JS_VAL_IS_BOOLEAN(v))
#define JS_VAL_TO_GCTHING(v)    ((void *) JS_VAL_CLRTAG(v))
#define JS_VAL_TO_OBJECT(v)     ((JSScriptable *) JS_VAL_TO_GCTHING(v))
#define JS_VAL_TO_DOUBLE(v)     ((jsDouble_t *) JS_VAL_TO_GCTHING(v))
#define JS_VAL_TO_STRING(v)     ((jsString_t) JS_VAL_TO_GCTHING(v))
#define JS_OBJECT_TO_VAL(obj)   ((jsVal_t) (obj))
#define JS_DOUBLE_TO_VAL(dp)    JS_VAL_SETTAG((jsVal_t) (dp), JS_VAL_DOUBLE)
#define JS_STRING_TO_VAL(str)   JS_VAL_SETTAG((jsVal_t) (str), JS_VAL_STRING)

/* Domain limits for the jsVal int type. */
#define JS_VAL_INT_POW2(n)      ((jsVal_t) 1 << (n))
#define JS_VAL_INT_MIN          ((jsVal_t) 1 - JS_VAL_INT_POW2(30))
#define JS_VAL_INT_MAX          (JS_VAL_INT_POW2(30) - 1)
#define JS_INT_FITS_IN_VAL(i)   ((unsigned long)((i) + JS_VAL_INT_MAX)  \
                                        <= 2 * JS_VAL_INT_MAX)
#define JS_VAL_TO_INT(v)        ((jsInt_t) (v) >> 1)
#define JS_INT_TO_VAL(i)        (((jsVal_t) (i) << 1) | JS_VAL_INT)
#define JS_VAL_TO_NUMBER(v)     (JS_VAL_IS_INT(v) ?                     \
                                        (jsDouble_t) JS_VAL_TO_INT(v) : \
                                        *JS_VAL_TO_DOUBLE(v))

/* Convert between boolean and jsVal. */
#define JS_VAL_TO_BOOLEAN(v)    ((jsBool_t)((v) >> JS_VAL_TAGBITS))
#define JS_BOOLEAN_TO_VAL(b)    JS_VAL_SETTAG((jsVal_t)(b) << JS_VAL_TAGBITS, \
                                        JS_VAL_BOOLEAN)

#endif  /* _JS_VAL_H_ */
