/* 
 * $Id: C-expr.h,v 1.15 2000/12/15 05:25:28 m-hirano Exp $
 * $RWC_Release: Omni-1.6 $
 * $RWC_Copyright:
 *  Omni Compiler Software Version 1.5-1.6
 *  Copyright (C) 2002 PC Cluster Consortium
 *  
 *  This software is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version
 *  2.1 published by the Free Software Foundation.
 *  
 *  Omni Compiler Software Version 1.0-1.4
 *  Copyright (C) 1999, 2000, 2001.
 *   Tsukuba Research Center, Real World Computing Partnership, Japan.
 *  
 *  Please check the Copyright and License information in the files named
 *  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
 *  Software release kit.
 *  
 *  
 *  $
 */
/* 
 * internal expression data structure 
 */
#include "C-exprcode.h"

typedef struct longlong_value {
#if (WORDS_BIGENDIAN == 1)
    int h,l;
#else
    int l,h;
#endif
} longlong;

enum symbol_type {
    S_IDENT = 0,	/* default */
    S_INTR		/* intrinsic */
};

/* symbol and symbol table */
typedef struct symbol
{
    struct symbol *s_next;		/* backet chain */
    char *s_name;
    char s_under;
    enum symbol_type s_type;
    short int s_value;
} * SYMBOL;

extern SYMBOL	f_find_symbol _ANSI_ARGS_((char *name));
extern SYMBOL	c_find_symbol _ANSI_ARGS_((char *name));

#define SYM_NAME(sp)	((sp)->s_name)
#define SYM_TYPE(sp)	((sp)->s_type)
#define SYM_VAL(sp)	((sp)->s_value)

typedef struct {
    short int ln_no;
    short int file_id;
} lineno_info;

/* de-syntax program is represented by this data structure. */
typedef struct expression_node
{
    enum expr_code e_code;
    lineno_info *e_line;		/* line number this node created */
    struct type_descriptor *e_type;	/* used for expv */
    int is_rvalue;			/* used for expv, to determine
					   rvalue (not lhs) or not. */
    union {
	void *e_gen;
	struct list_node *e_lp;
	SYMBOL e_sym;		/* e_code == NAME, TYPE, ...  */
	char *e_str;		/* e_code == STRING */
	int e_ival;		/* e_code == INT_CONSTANT */
	double e_fval;		/* e_code == FLOAT_CONSTANT */
#ifdef HAS_INT64
	_omInt64_t e_i64val;
#endif /* HAS_INT64 */
#ifdef HAS_LONGDOUBLE
	long double e_lfval;
#endif /* HAS_LONGDOUBLE */
	longlong e_llval;	/* e_code == LONGLONG_CONSTANT */
    } v;
} * expr;

#define EXPR_GEN(x)	((x)->v.e_gen)
#define EXPR_CODE(x)	((x)->e_code)	
#define EXPR_SYM(x)	((x)->v.e_sym)
#define EXPR_STR(x)	((x)->v.e_str)
#define EXPR_FLOAT(x)	((x)->v.e_fval)
#define EXPR_LIST(x)	((x)->v.e_lp)
#define EXPR_INT(x)	((int)((_omAddrInt_t)((x)->v.e_gen)))
#define EXPR_LLINT(x)	((x)->v.e_llval)
#define EXPR_LLINT_LOW(x)	((x)->v.e_llval.l)
#define EXPR_LLINT_HIGH(x)	((x)->v.e_llval.h)
#define EXPR_TYPE(x)	((BASIC_DATA_TYPE)(EXPR_INT(x)))
#define EXPR_SCLASS(x)	((STORAGE_CLASS)(EXPR_INT(x)))
#define EXPR_TYPE_QUAL(x)	((TYPE_QUAL)(EXPR_INT(x)))
#define EXPR_LINE_NO(x)	((x)->e_line->ln_no)
#define EXPR_LINE_FILE_ID(x)	((x)->e_line->file_id)
#define EXPR_LINE(x)	((x)->e_line)

#ifdef HAS_INT64
#define EXPR_INT64(x)			expr_int64_value(x)
#define EXPR_INT64_SAVE(x, i64)		expr_int64_save(x, i64)
#endif /* HAS_INT64 */

#ifdef ENABLE_QREAL
#define EXPR_QREAL_CONST(x)	((x)->v.e_gen)
#endif /* ENABLE_QREAL */

/* list data structure, which is ended with NULL */
typedef struct list_node
{
    struct list_node *l_next;
    expr l_item;
    struct list_node *l_last;
    int l_nItems;
    struct list_node **l_array;
} *list;

#define LIST_NEXT(lp)	((lp)->l_next)
#define LIST_ITEM(lp)	((lp)->l_item)
#define LIST_LAST(lp)	((lp)->l_last)
#define LIST_N_ITEMS(lp)	((lp)->l_nItems)
#define LIST_ARRAY(lp)	((lp)->l_array)
#define FOR_ITEMS_IN_LIST(lp,x) \
  if(x != NULL) for(lp = EXPR_LIST(x); lp != NULL ; lp = LIST_NEXT(lp))

#define EXPR_ARG1(x)	LIST_ITEM(EXPR_LIST(x))
#define EXPR_ARG2(x)	LIST_ITEM(LIST_NEXT(EXPR_LIST(x)))
#define EXPR_ARG3(x)	LIST_ITEM(LIST_NEXT(LIST_NEXT(EXPR_LIST(x))))
#define EXPR_ARG4(x) LIST_ITEM(LIST_NEXT(LIST_NEXT(LIST_NEXT(EXPR_LIST(x)))))

/* typed value returned as a result of evaluation. */
typedef expr expv;

#define EXPV_GEN(x)	((x)->v.e_gen)
#define EXPV_CODE(x)	((x)->e_code)
#define EXPV_TYPE(x)	((x)->e_type)
#define EXPV_IS_RVALUE(x)	((x)->is_rvalue)
#define EXPV_LIST(x)	((x)->v.e_lp)
#define EXPV_LEFT(x) 	((x)->v.e_lp->l_item)
#define EXPV_RIGHT(x) \
((x)->v.e_lp->l_next != NULL?(x)->v.e_lp->l_next->l_item:NULL)
#define EXPV_NAME(x)	((x)->v.e_sym)
#define EXPV_STR(x)	((x)->v.e_str)
#define EXPV_INT_VALUE(x)	((int)((_omAddrInt_t)((x)->v.e_gen)))
#define EXPV_UINT_VALUE(x)	((unsigned int)((_omAddrInt_t)((x)->v.e_gen)))
#define EXPV_ULINT_VALUE(x)	((unsigned)(x)->v.e_lival)
#define EXPV_FLOAT_VALUE(x)	((x)->v.e_fval)
#define EXPV_LLINT_VALUE(x)	((x)->v.e_llval)
#define EXPV_LLINT_HIGH(x)	((x)->v.e_llval.h)
#define EXPV_LLINT_LOW(x)	((x)->v.e_llval.l)
#define EXPV_ANY(t,x)		((t)((_omAddrInt_t)((x)->v.e_gen)))

#ifdef HAS_INT64
#define EXPV_INT64_VALUE(x)		EXPR_INT64(x)
#define EXPV_INT64_SAVE_VALUE(x, i64)	EXPR_INT64_SAVE(x, i64)
#endif /* HAS_INT64 */

#ifdef ENABLE_QREAL
#define EXPV_QREAL_CONST(x)	EXPR_QREAL_CONST(x)
#endif /* ENABLE_QREAL */

extern struct expr_code_info 
{
    char code_info;
    char *code_name;
    char *operator_name;
} expr_code_info[];

#define EXPR_CODE_NAME(code)	expr_code_info[code].code_name
#define EXPR_CODE_SYMBOL(code)   expr_code_info[code].operator_name

/* code info */
/* T : terminal
 * L : list
 * B : binary operator
 * U : unary opertor 
 */
#define EXPR_CODE_INFO(code)	expr_code_info[code].code_info
#define EXPR_CODE_IS_TERMINAL(code) (expr_code_info[code].code_info == 'T')
#define EXPR_CODE_IS_LIST(code) (expr_code_info[code].code_info == 'L')
#define EXPR_CODE_IS_BINARY(code) (expr_code_info[code].code_info == 'B')
#define EXPR_CODE_IS_UNARY(code) (expr_code_info[code].code_info == 'U')

#define EXPR_CODE_IS_TERMINAL_OR_CONST(code) \
((EXPR_CODE_IS_TERMINAL(code)) || \
 ((code) == F_COMPLEX_CONSTANT) || \
 ((code) == COMPLEX_CONSTANT))

