/* 
 * $Id: C-expr.h,v 1.18 2000/10/12 04:12:07 msato 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 
 */

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_TYPE,
    S_CLASS,
    S_KEYWORD,
    S_QUAL,
    S_PARAM,	/* for tea pragma */
    S_GCC	/* gcc extension */
};

/* symbol and symbol table */
typedef struct symbol {
    struct symbol *s_next;		/* backet chain */
    char *s_name;
    enum symbol_type s_type;	/* symbol type, KEYWORD, NAME, etc ... */
    short int s_value;
} * SYMBOL;

#define SYM_NAME(sp)	((sp)->s_name)

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 */
    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 */
	long e_lival;
	double e_fval;		/* e_code == FLOAT_CONSTANT */
#ifdef HAS_LONGDOUBEL
	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_LINT(x)	((x)->v.e_lival)
#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(x)	((x)->e_line)
#define EXPR_LINE_NO(x)	((x)->e_line->ln_no)
#define EXPR_LINE_FILE_ID(x)	((x)->e_line->file_id)

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

#define LIST_NEXT(lp)	((lp)->l_next)
#define LIST_ITEM(lp)	((lp)->l_item)
#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)))))

#define EMPTY_LIST list0(LIST)

/* 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_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_LINT_VALUE(x)	((x)->v.e_lival)
#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)))

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')

