/*
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 */
/* $Id$ */
/* EXPRESSION DESCRIPTOR */

/*	What we want to define is the struct expr, but since it contains
	a union of various goodies, we define them first; so be patient.
*/

/* classes of value */
#define Const	1
#define Name	2
#define Label	3

struct value	{
	int vl_class;		/* Const, Name or Label	*/
	arith vl_value;		/* constant value or offset */
	union {
		struct idf *vl_idf;	/* external name */
		label vl_lbl;		/* compiler-generated label */
	} vl_data;
};

struct string	{
	char *sg_value;		/* row of bytes repr. the constant */
	int sg_len;		/* length of the row */
};

struct oper	{
	struct type *op_type;	/* resulting type of the operation	*/
	struct expr *op_left;
	int op_oper;			/* the symbol of the operator	*/
	struct expr *op_right;
};

/* The following constants indicate the class of the expression: */
#define	Value	0		/* it is a value known at load time */
#define	String	1		/* it is a string constant  */
#define	Float	2		/* it is a floating point constant	*/
#define	Oper	3		/* it is a run-time expression */
#define	Type	4		/* only its type is relevant */

struct expr	{
	char *ex_file;		/* the file it (probably) comes from */
	unsigned int ex_line;	/* the line it (probably) comes from */
	struct type *ex_type;
	short ex_lvalue;
	short ex_flags;
	int ex_class;
	int ex_depth;
	union	{
		struct value ex_value;
		struct string ex_string;
		flt_arith ex_fl_arith;
		struct oper ex_oper;
	} ex_object;
};

/* some abbreviated selections	*/
#define EX_VALUE	ex_object.ex_value
#define VL_CLASS	EX_VALUE.vl_class
#define	VL_VALUE	EX_VALUE.vl_value
#define	VL_IDF		EX_VALUE.vl_data.vl_idf
#define	VL_LBL		EX_VALUE.vl_data.vl_lbl
#define	SG_VALUE	ex_object.ex_string.sg_value
#define SG_LEN		ex_object.ex_string.sg_len
#define	FL_ARITH	ex_object.ex_fl_arith
#define	OP_TYPE		ex_object.ex_oper.op_type
#define	OP_LEFT		ex_object.ex_oper.op_left
#define	OP_OPER		ex_object.ex_oper.op_oper
#define	OP_RIGHT	ex_object.ex_oper.op_right

/*	some bits for the ex_flag field, to keep track of various
	interesting properties of an expression.
*/
#define	EX_SIZEOF	0x001		/* contains sizeof operator */
#define	EX_CAST		0x002		/* contains cast */
#define	EX_LOGICAL	0x004		/* contains logical operator */
#define	EX_COMMA	0x008		/* contains expression comma */
#define	EX_PARENS	0x010		/* the top level is parenthesized */
#define EX_SIDEEFFECTS	0x020		/* expression has side effects */
#define	EX_READONLY	0x040		/* read only variabele */
#define	EX_VOLATILE	0x080		/* volatile variabele */
#define	EX_ILVALUE	0x100		/* an illegal lvalue e.g. f().x */
#define	EX_ERROR	0x200		/* the expression is wrong */
#define	EX_PTRDIFF	0x400		/* subtracting 2 pointers in expr. */

#define	NILEXPR		((struct expr *)0)

/* some useful tests */
#define	ISNAME(e)	((e)->ex_class == Value && (e)->VL_CLASS == Name)
#define	ISCOMMA(e)	((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)

extern struct expr *intexpr(), *new_oper();

/* ALLOCDEF "expr" 20 */