/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
/* MiniC expression definitions 
** Andy Lowry, Apr 1989
** SCCS Info: @(#)expr.h	1.2 3/13/90
**/

/* We define a structure for representing arbitrary C expressions...
** typedefs for EXPR, CTYPE and S_ENTRY must already exist (we define
** the structure to which EXPR is typedef'ed here).
**/

typedef enum e_opcode {		/* all the expresion operator codes */
  OP_OP1,			/* expression = 1st operand, used for */
				/* leaves of expression tree */
  OP_DEREF,			/* '*' unary - dereference op1 pointer */
  OP_ADDR,			/* '&' unary - address of op1 */
  OP_NEGATE,			/* '-' unary - negation of op1 */
  OP_LNOT,			/* '!' unary - logical complement of op1 */
  OP_BITNOT,			/* '~' unary - bitwise logical */
				/* complement of op1 */
  OP_PREINCR,			/* '++' unary prefix - increment then */
				/* get value of op1 */ 
  OP_PREDECR,			/* '--' unary prefix - decrement then */
				/* get value of op1 */
  OP_POSTINCR,			/* '++' unary postfix - get value then */
				/* increment op1 */
  OP_POSTDECR,			/* '--' unary postfix - get value then */
				/* decrement op1 */
  OP_SIZEOF,			/* 'sizeof' unary - applied to expr or */
				/* type found in op1 */
  OP_CAST,			/* (type) unary - cast op2 as type op1 */
  OP_MULT,			/* '*' binary - product of op1 and op2 */
  OP_DIV,			/* '/' binary - quotient of op1 by op2 */
  OP_MOD,			/* '%' binary - remainder of op1 by op2 */
  OP_PLUS,			/* '+' binary - sum of op1 and op2 */
  OP_MINUS,			/* '-' binary - difference of op2 by op1 */
  OP_RSHIFT,			/* '>>' binary - op1 shifted right op2 bits */
  OP_LSHIFT,			/* '<<' binary - op1 shifted left op2 bits */
  OP_LT,			/* '<' binary - test if op1 less than op2 */
  OP_GT,			/* '>' binary - test if op1 greater */
				/* than op2 */
  OP_LE,			/* '<=' binary - test if op1 less than */
				/* or equal to op2 */
  OP_GE,			/* '>=' binary - test if op1 greater */
				/* than or equal to op2 */
  OP_EQ,			/* '==' binary - test if op1 and op2 */
				/* are equal */
  OP_NE,			/* '!= binary - test if op1 and op2 */
				/* are not equal */
  OP_BITAND,			/* '&' binary - bitwise logical and of */
				/* op1 and op2  */
  OP_BITXOR,			/* '^' binary - bitwise logical */
				/* exclusive or of op1 and op2 */
  OP_BITIOR,			/* '|' binary - bitwise logical */
				/* inclusive or of op1 and op2 */
  OP_LAND,			/* '&&' binary - logical and of op1 */
				/* and op2 */
  OP_LIOR,			/* '||' binary - logical inclusive or */
				/* of op1 and op2 */
  OP_COND,			/* '?..:' ternary - if op1 is true */
				/* then value is op2 else op3 */
  OP_ASSIGN,			/* '=' binary - assign op2 to op1 */
  OP_ADD_ASSIGN,		/* '+=' binary - add op2 to op1 */
  OP_SUB_ASSIGN,		/* '-=' binary - subtract op2 from op1 */
  OP_MULT_ASSIGN,		/* '*=' binary - multipy op1 by op2 */
  OP_DIV_ASSIGN,		/* '/=' binary - divide op1 by op2 */
  OP_MOD_ASSIGN,		/* '%=' binary - reduce op1 modulo op2 */
  OP_RSHIFT_ASSIGN,		/* '>>=' binary - shift op1 right op2 bits */
  OP_LSHIFT_ASSIGN,		/* '<<=' binary - shift op1 left op2 bits */
  OP_AND_ASSIGN,		/* '&=' binary - bitwise logical and */
				/* op2 into op1  */
  OP_XOR_ASSIGN,		/* '&=' binary - bitwise logical */
				/* exclusive or op2 into op1 */
  OP_IOR_ASSIGN,		/* '|=' binary - bitwise logical */
				/* inclusive or op2 into op1 */
  OP_COMMA,			/* ',' binary - evaluate op1 and op2, */
				/* value is op2 */
  OP_AREF,			/* array reference - use op2 to index */
				/* into op1 array */
  OP_MEMBER,			/* ith member of op1 (struct or union) */
				/* where i is given by op2 ('.' is */
				/* represented directly with */
				/* OP_MEMBER, while '->' becomes an */
				/* OP_MEMBER operating on an OP_DEREF */
				/* expression) */
} E_OPCODE;

typedef enum e_optype {		/* types of operands we know */
  OT_INT,			/* integer constant */
  OT_REAL,			/* real constant */
  OT_STRING,			/* string constant */
  OT_VAR,			/* variable reference */
  OT_FUNCALL,			/* function call */
  OT_EXPR,			/* another expression */
  OT_TYPE,			/* type specification */
} E_OPTYPE;

typedef struct e_arglist {	/* arguments for a function call */
  EXPR *arg;			/* this argument */
  struct e_arglist *next;	/* remaining args */
} E_ARGLIST;

typedef struct e_operand {	/* an operand in an expression */
  E_OPTYPE optype;		/* operand type */
  union {			/* optype-dependent data */
    long intconst;		/* integer constant */
    double realconst;		/* real constant */
    char *strconst;		/* string constant */
    S_ENTRY *var;		/* variable reference */
    struct {
      S_ENTRY *fn;		/* called function */
      E_ARGLIST *args;		/* function arguments */
    } funcall;
    EXPR *exp;			/* subexpression */
    CTYPE *type;		/* type (needed for sizeof & cast */
				/* operators) */ 
  } data;
} E_OPERAND;

struct expr {			/* typedef'ed as EXPR */
  E_OPCODE opcode;		/* opcode for this expression */
  short flags;			/* flags describing this expression */
  CTYPE *type;			/* type of this expression */
  E_OPERAND *op1,*op2,*op3;	/* up to 3 operands (needed for ?: operator) */
  short refcount;		/* number of things pointing to us */
};

/* expression flags... */
#define E_CONSTANT 0x0001	/* a compile-time constant expression */
#define E_LVALUE 0x0002		/* the expression can be assigned to */

