/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Copyright (c) 1989-1999 Microsoft Corporation

 Module Name:
	
	expr.hxx

 Abstract:

 	This file contains the expression class definitions.


 Notes:


 Author:

	VibhasC	Jun-06-1993	Created

 Notes:

 	This expression evaluator is used by the front and the code generator of
 	the midl compiler. It therefore must support the complete gamut of c
 	expressions.

 ----------------------------------------------------------------------------*/
#ifndef __EXPR_HXX__
#define __EXPR_HXX__
/****************************************************************************
 *	include files
 ***************************************************************************/

#include "nulldefs.h"
#include "common.hxx"
#include "listhndl.hxx"
#include "midlnode.hxx"
extern "C"
	{
	#include <stdio.h>
	
	}
#include "stream.hxx"
#include "ndrtypes.h"

#define _STRDUP( x, y ) ( (y) ? ((x) = new char[strlen(y)+1] ), strcpy( x, y ) : x = 0)

class node_skl;
class EXPR_CTXT;

typedef char  * PNAME;
typedef	__int64 EXPR_VALUE;

/****************************************************************************
 *	extern references
 ***************************************************************************/



/****************************************************************************
 *	the meat of the definitions
 ***************************************************************************/

#if 0
//
// the class heirarchy for the expression evaluator. The class heirarchy for
// the expression does not reflect the operator or evaluation precedence. The
// class heirarchy instead reflects the organisation based on the structure of
// an object of the expression class. It is upto the generator of the expression
// to ensure proper precedence. In case the expression is generated by a parser
// the precedence is automatically ensured. The back end which generates new
// expressions must therefore ensure that the precedence is properly set up. We
// will NOT check this.
//

expr_node
	expr_variable
	expr_resource
	expr_constant
	expr_operator
		expr_op_unary

			expr_u_arithmetic	// + -
			expr_u_not			// !
			expr_u_complement	// ~
			expr_deref			// *
			expr_u_address		// &
			expr_cast			// (type) 
		    expr_sizeof			// sizeof( type )
            expr_alignof        // __alignof( type )
			expr_post_incr		// foo++
			expr_pre_incr		// ++foo
			expr_post_decr		// foo--
			expr_pre_decr		// --foo
	
		expr_op_binary
	
			expr_b_arith		// * / + - %
			expr_b_logical		// || &&
			expr_relational		// > >= == != < <= 
			expr_shift			// << >>
			expr_bitwise		// |, &, ^
			expr_dot			// a.b
			expr_pointsto		// a->b
			expr_index			// []
			expr_comma			// ,
			expr_assign			// = 
			expr_proc			// ()
			expr_statement		// ;

		expr_ternary		// ?:



#endif // 0


//
// The basic expression class. This class is an abstract base class. It only 
// provides the interface to a general expression node.
// 

#define _expr_node				expr_node
#define _expr_variable			expr_variable
#define _expr_constant			expr_constant
#define _expr_named_constant	expr_named_constant
#define _expr_operator			expr_operator
#define _expr_op_unary			expr_op_unary
#define _expr_op_binary			expr_op_binary
#define _expr_u_arithmetic		expr_u_arithmetic
#define _expr_u_not				expr_u_not
#define _expr_u_complement		expr_u_complement
#define _expr_u_deref			expr_u_deref
#define _expr_u_address			expr_u_address
#define _expr_cast				expr_cast
#define _expr_sizeof			expr_sizeof
#define _expr_alignof           expr_alignof
#define _expr_pre_incr			expr_pre_incr
#define _expr_pre_decr			expr_pre_decr
#define _expr_post_incr			expr_post_incr
#define _expr_post_decr			expr_post_decr
#define _expr_b_arithmetic		expr_b_arithmetic
#define _expr_b_logical			expr_b_logical
#define _expr_relational		expr_relational
#define _expr_shift				expr_shift
#define _expr_bitwise			expr_bitwise
#define _expr_dot				expr_dot
#define _expr_pointsto			expr_pointsto
#define _expr_index				expr_index
#define _expr_comma				expr_comma
#define _expr_assign			expr_assign
#define _expr_proc_call			expr_proc_call
#define _expr_param				expr_param

//
// This is the constant expression class. For now this only has simple integral
// constants. We would need to have this class to be more explicit in that it
// needs to know the exact type of the constant according to the language
// rules and know the exact format to be able to print this out. This is 
// necessary so that the generated constant looks the same as the original
// for the user's convenience.
//

typedef enum _pformat {
	VALUE_TYPE_STRING,
	VALUE_TYPE_WSTRING,
	VALUE_TYPE_CHAR,
	VALUE_TYPE_WCHAR,

	VALUE_TYPE_NUMERIC,
	VALUE_TYPE_NUMERIC_U,
	VALUE_TYPE_NUMERIC_LONG,
	VALUE_TYPE_NUMERIC_ULONG,

	VALUE_TYPE_HEX,
	VALUE_TYPE_HEX_U,
	VALUE_TYPE_HEX_LONG,
	VALUE_TYPE_HEX_ULONG,

	VALUE_TYPE_OCTAL,
	VALUE_TYPE_OCTAL_U,
	VALUE_TYPE_OCTAL_LONG,
	VALUE_TYPE_OCTAL_ULONG,

	VALUE_TYPE_BOOL,

	VALUE_TYPE_FLOAT,
	VALUE_TYPE_DOUBLE,

// RKK64
// value types for int64

    VALUE_TYPE_UNDEFINED,
	} PFORMAT;

struct SExprValue
    {
    PFORMAT format;
    union
        {
        signed char         ch;
        signed short        sh;
        signed int          n;
        signed long         l;

        unsigned char       uch;
        unsigned short      ush;
        unsigned int        un;
        unsigned long       ul;

        __int64             hy;
        float               f;
        double              d;

        BOOL                b;
        wchar_t             wch;
        } ;
    };

typedef node_skl *	ETYPE;

class expr_node
	{
protected:

	//
	// the type of the expression. All expression nodes need to have a type
	// since a variable / constant will have a type and so will an operation
	// on those variables / constants.

	node_skl		*	pType;
	BOOL				fConstant	: 1;
    BOOL                fFloatExpr  : 1;


	//
	// The constructor. Each expression node is instantiated using a type
	// If the type is unknown at the time of instantiation, then an error type
	// is the type of the expression. Therefore we provide a overloaded
	// constructor for both these situations.
	//

public:

						expr_node()
							{
							SetType( (node_skl *)0 );
							fConstant = TRUE;
                            fFloatExpr = FALSE;
							};

						expr_node( node_skl * pT )
							{
							SetType( pT );
							fConstant = TRUE;
                            fFloatExpr = FALSE;
							};

    virtual void        CopyTo( expr_node* lhs );

    virtual expr_node*  Clone() { return new expr_node; };

	//
	// set the type of the expression.
	//

	void				SetType( node_skl * pT )
							{
							pType = pT;
							}

	//
	// get the type of the expression.
	//

	virtual
	node_skl		*	GetType( void )
							{
							return pType;
							}
	
	//
	// get the type of the expression. Force it to be determined
	// if it is unknown
	//

	node_skl		*	AlwaysGetType( void )
							{
							node_skl	*	pType = GetType();

							if ( !pType )
								{
								DetermineType();
								pType = GetType();
								}
							return pType;
							}
	
	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType()
							{
							}

	//
	// set the "constness" of the expression.
	//

	void				SetConstant( BOOL	fCon = TRUE )
							{
							fConstant = fCon;
							}

    void                SetFloatExpr( BOOL f = TRUE )
                            {
                            fFloatExpr = f;
                            }
	//
	// queries.
	//

	virtual
	BOOL				IsAVariable()
							{
							return FALSE;
							}
	virtual
	BOOL				IsResource()
							{
							return FALSE;
							}
	virtual
	BOOL				IsConstant()
							{
							return fConstant;
							}
	virtual
	BOOL				IsOperator()
							{
							return FALSE;
							}

	virtual
	BOOL				IsUnaryOperator()
							{
							return FALSE;
							}
	virtual
	BOOL				IsBinaryOperator()
							{
							return FALSE;
							}

	virtual
	BOOL				IsArithmeticOperator()
							{
							return FALSE;
							}
	virtual
	BOOL				IsLogicalOperator()
							{
							return FALSE;
							}

	virtual
	BOOL				IsBitwiseOperator()
							{
							return FALSE;
							}
	virtual
	BOOL				IsRelationalOperator()
							{
							return FALSE;
							}
	virtual
	BOOL				IsShiftOperator()
							{
							return FALSE;
							}

    //
    // test if the expression is a string constant
    //
    virtual
    BOOL                IsStringConstant (void)
                            {
                            return FALSE;
                            }
	
    BOOL                IsFloatExpr( void )
                            {
                            return fFloatExpr;
                            }
	//
	// others. 
	//

	virtual
	expr_node		*	GetLeft()
							{
							return 0;
							}

	virtual
	expr_node		*	GetRight()
							{
							return 0;
							}
	virtual
	OPERATOR			GetOperator()
							{
							return OP_ILLEGAL;
							}

	virtual
	EXPR_VALUE			GetValue()
							{
							return 0;
							}

    virtual
    BOOL                GetExprValue( SExprValue& v )
                            {
                            v.format = VALUE_TYPE_UNDEFINED;
                            return TRUE;
                            }
    //
    // Make (or add to) a list of var nodes of an expr
    //
    virtual
    short               MakeListOfVars( ITERATOR & pList );

    virtual
    short               MakeListOfDerefedVars( ITERATOR&  )
                            {
                            return 0;
                            }

// gaj - this is a dummy routine
	virtual
	EXPR_VALUE			Evaluate()
							{
							return GetValue();
							}
// gaj - end of dummy routines

	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * )
							{
							}

	void				PrintWithPrefix( ISTREAM * pS, char * Prefix );

	void				DecorateWithPrefix( char * Prefix = NULL );

	//
	// This is an overloaded virtual only for the proc_call node.
	//

	virtual
	void				PrintCall( ISTREAM * pS,
								   short ,
								   BOOL  )
							{
							Print( pS );
							}

	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

	// private allocator
	void				*	operator new ( size_t size )
								{
								return AllocateOnceNew( size );
								}
	void					operator delete( void * ptr )
								{
								AllocateOnceDelete( ptr );
								}

	};


//
// This class represents a variable in an expression.
// This expression node is instantiated for variables specified as fields of
// a struct/union or as parameters. Contrast this to the resource class which
// is VERY similar but only corresponds to the internally generated and used
// variables in the stub routines.
//

class expr_variable	: public expr_node
	{
private:

	//
	// the name of the variable.
	//

	PNAME				pIDName;
    char *              pPrefix;

public:

	//
	// the constructor expects the object to be instantiated using a name.
	// Sometimes one needs to instantiate a variable using the type too.
	//

						expr_variable( PNAME p )
							{
							SetName( p );
							SetType( (node_skl *)0 );
							SetConstant( FALSE );
							SetPrefix( NULL );
							}

						expr_variable( PNAME p, node_skl * pT );

    virtual void        CopyTo( expr_node* lhs );
    virtual expr_node*  Clone() { return new expr_variable(0); };
	
	// get the type
	virtual
	node_skl 	*		GetType();

	//
	// set methods.
	//

	void				SetName( PNAME p )
							{
							pIDName = p;
							}

	void				SetPrefix( char * p )
							{
							pPrefix = p;
							}

	//
	// get methods
	//

	PNAME				GetName()
							{
							return pIDName;
							}
	
	char *				GetPrefix()
							{
							return pPrefix;
							}
	//
	// is this a variable expression.
	//

	virtual
	BOOL				IsAVariable()
							{
							return TRUE;
							}

	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

    //
    // Make (or add to) a list of var nodes of an expr
    //
    virtual
    short               MakeListOfVars( ITERATOR & pList );

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

	};

//
// This class represents a variable in an expression.
// This expression node is instantiated for variables specified as fields of
// a struct/union or as parameters. Contrast this to the resource class which
// is VERY similar but only corresponds to the internally generated and used
// variables in the stub routines.
//

class expr_named_constant	: public expr_variable
	{
public:

	//
	// the constructor expects the object to be instantiated using a name.
	// Sometimes one needs to instantiate a variable using the type too.
	//

						expr_named_constant( PNAME p = 0)
								: expr_variable( p )
							{
							SetConstant( TRUE );
							}

						expr_named_constant( PNAME p, node_skl * pT )
								: expr_variable( p, pT )
							{
							SetConstant( TRUE );
							}

    virtual expr_node*      Clone() { return new expr_named_constant; };

	BOOL				IsAVariable()
							{
							return FALSE;
							}

	//
	// if it is a constant id or label, we can return the value
	//

	virtual
	EXPR_VALUE			GetValue();

	// similarly for expression
	expr_node	*		GetExpr();

    //
    // Make (or add to) a list of var nodes of an expr
    //
    virtual
    short               MakeListOfVars( ITERATOR & pList );

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

	};

//
// value type masks indicate the value type set by the user / determined from
// the value of the constant.
//

#define VALUE_T_MASK_CLEAR		(0x00)
#define VALUE_T_MASK_CHAR		(0x01)
#define VALUE_T_MASK_SHORT		(0x02)
#define VALUE_T_MASK_LONG 		(0x04)
#define VALUE_T_MASK_UCHAR		(0x10)
#define VALUE_T_MASK_USHORT		(0x20)
#define VALUE_T_MASK_ULONG		(0x40)


class expr_constant	: public expr_node
	{
private:

	//
	// store the original format. If the original format is a null then 
	// the expression is printed out in the manner suitable for the type of
	// the expression. If the original format is present, then the user 
	// declared this expression in this format and she wants it back in the
	// header/stub file also in the same format.

	PFORMAT					Format;

    union 
	    {
	    char				C;
	    short				S;
	    long				L;
        __int64             I64;
	    float				F;
	    double				D;
	    unsigned char		UC;
	    unsigned short		US;
	    unsigned long		UL;
        unsigned __int64    UI64;
	    unsigned char*      pC;
	    wchar_t*	        pWC;
	    } Value;

	//
	// get and set the format of the constant.
	//

	void					SetFormat( PFORMAT p )
								{
								Format = p;
								}

public:

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_constant(this); }

	PFORMAT					GetFormat() const
								{
								return Format;
								}
	//
	// Different constructors are available for the different kind of constants
	// that are possible.
	//

							expr_constant( char C, 
											PFORMAT pF = VALUE_TYPE_CHAR )
								{
								SetFormat( pF );
								Value.I64 = C;
								}

							expr_constant( short S, 
											PFORMAT pF = VALUE_TYPE_NUMERIC )
								{
								SetFormat( pF );
								Value.I64 = S;
								}

							expr_constant( long L, 
											PFORMAT pF = VALUE_TYPE_NUMERIC )
								{
								SetFormat( pF );
								Value.I64 = L;
								}

							expr_constant( __int64 I64, 
											PFORMAT pF = VALUE_TYPE_NUMERIC )
								{
								SetFormat( pF );
								Value.I64 = I64;
								}

							expr_constant( float F, 
											PFORMAT pF = VALUE_TYPE_FLOAT )
								{
								SetFormat( pF );
								Value.F = F;
								}

							expr_constant( double D, 
											PFORMAT pF = VALUE_TYPE_DOUBLE )
								{
								SetFormat( pF );
								Value.D = D;
								}

							expr_constant( unsigned char UC, 
											PFORMAT pF = VALUE_TYPE_NUMERIC_U )
								{
								SetFormat( pF );
								Value.I64 = UC;
								}

							expr_constant( unsigned short US, 
											PFORMAT pF = VALUE_TYPE_NUMERIC_U )
								{
								SetFormat( pF );
								Value.I64 = US;
								}

							expr_constant( unsigned long UL, 
											PFORMAT pF = VALUE_TYPE_NUMERIC )
								{
								SetFormat( pF );
								Value.I64 = UL;
								}

							expr_constant( unsigned __int64 UI64, 
											PFORMAT pF = VALUE_TYPE_NUMERIC )
								{
								SetFormat( pF );
								Value.I64 = (__int64)UI64;
								}

							expr_constant( char *pC,  
											PFORMAT pF = VALUE_TYPE_STRING )
								{
								SetFormat( pF );
								Value.UI64 = (unsigned __int64)pC;
								}

							expr_constant( wchar_t *pWC,  
											PFORMAT pF = VALUE_TYPE_WSTRING )
								{
								SetFormat( pF );
								Value.UI64 = (unsigned __int64)pWC;
								}

                            expr_constant( const expr_constant *p)
                                {
                                SetFormat( p->GetFormat() );
                                Value = p->Value;
                                }
	//
	// queries.
	//

// gaj - return constant value assuming it is long for now...
	virtual
	EXPR_VALUE				GetValue();

    BOOL                    GetExprValue( SExprValue& v )
                                {
                                // currently only floats and double use this code path
                                // fix this when expr evaluator is revamped
                                v.format = VALUE_TYPE_UNDEFINED;
                                if (Format == VALUE_TYPE_FLOAT)
                                    {
                                    v.format = Format;
                                    v.f = Value.F;
                                    }
                                else if (Format == VALUE_TYPE_DOUBLE)
                                    {
                                    v.format = Format;
                                    v.d = Value.D;
                                    }
                                return TRUE;
                                }
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

    //
    // test if the expression is a string constant
    //
    virtual
    BOOL                IsStringConstant (void)
                            {
                            return (Format == VALUE_TYPE_STRING || Format == VALUE_TYPE_WSTRING);
                            }
	};

//
// some convenient helper functions to get vanilla constant 0 and constant 1
//

extern	expr_constant	*  GetConstant0();

extern	expr_constant	*  GetConstant1();



//
// the operator classes. These classes are group into unary binary and
// ternary expression classes. 
//

class expr_operator	: public expr_node
	{
private:
	OPERATOR				Operator;
public:

	//
	// the constructor of an abstract base class does nothing.
	//

							expr_operator( OPERATOR Op )
								{
								SetOperator( Op );
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_operator( OP_ILLEGAL ); };
	//
	// get and set functions.
	//

	void					SetOperator( OPERATOR Op )
								{
								Operator = Op;
								}

	OPERATOR				GetOperator()
								{
								return Operator;
								}
	//
	// queries.
	//

	virtual
	BOOL					IsOperator()
								{
								return TRUE;
								}

	void					PrintSubExpr( expr_node *, ISTREAM * pS );

	};


//
// unary operator classes.
//

class expr_op_unary	: public expr_operator
	{
private:
	expr_node			*	pLeft;

public:

	//
	// the constructor. This class is instantiated by supplying operator and
	// the left had side expression values.
	//

							expr_op_unary( OPERATOR Op, expr_node *pL) : 
												expr_operator(Op)
								{
								SetLeft( pL );
								if ( pL ) SetConstant( pL->IsConstant() );
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_op_unary( OP_ILLEGAL, 0 ); };
	//
	// get and set routines.
	//

	expr_node *			SetLeft( expr_node * pL )
								{
								return ( pLeft = pL );
								}

	virtual
	expr_node			*	GetLeft()
								{
								return pLeft;
								}

	//
	// queries.
	//

	virtual
	BOOL					IsUnaryOperator()
								{
								return TRUE;
								}

	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

    //
    // Make (or add to) a list of var nodes of an expr
    //
    virtual
    short               MakeListOfVars( ITERATOR & pList );

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

    virtual
    short               MakeListOfDerefedVars( ITERATOR& List )
                            {
                            if( GetLeft() )
                                return GetLeft()->MakeListOfDerefedVars( List );
                            return 0;
                            }

	};


//
// binary operator class. Each binary operator node takes a left and right
// expression connected by the binary operator.
//

class expr_op_binary	: public expr_operator
	{
private:

	expr_node			*	pLeft;
	expr_node			*	pRight;

public:

	//
	// this class is instantiated by specifying the left/right and the
	// operator.
	//

							expr_op_binary( OPERATOR		Op,
											expr_node	*	pL,
											expr_node	*	pR ) :
												expr_operator( Op )
								{
								SetLeft( pL );
								SetRight( pR );
								SetConstant( ( (pL) ? pL->IsConstant() : TRUE ) &&
											 ( (pR) ? pR->IsConstant() : TRUE ) );
								}
	
    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_op_binary( OP_ILLEGAL, 0, 0 ); };
	//
	// get and set.
	//

	virtual
	expr_node 		*		SetLeft( expr_node *p )
								{
								return (pLeft = p);
								}

	virtual
	expr_node		*		SetRight( expr_node *p )
								{
								return (pRight = p);
								}

	virtual
	expr_node		*		GetLeft()
								{
								return pLeft;
								}

	virtual
	expr_node		*		GetRight()
								{
								return pRight;
								}

	//
	// queries.
	//

	virtual
	BOOL					IsBinaryOperator()
								{
								return TRUE;
								}
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

	virtual
	void					PrintCall( ISTREAM * pS,
									   short LeftMargin,
									   BOOL	fInProc );
    //
    // Make (or add to) a list of var nodes of an expr
    //
    virtual
    short               MakeListOfVars( ITERATOR & pList );

    virtual
    short               MakeListOfDerefedVars( ITERATOR& List );

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

	};


//
// this is the unary arithmetic class. Corresponding to the unary arithmetic
// operators + and -.
//

class expr_u_arithmetic	: public expr_op_unary
	{
public:
							expr_u_arithmetic( OPERATOR	Op,
									   		   expr_node * pL ) : 
													expr_op_unary(Op, pL)
								{
								}
    virtual expr_node*      Clone() { return new expr_u_arithmetic( OP_ILLEGAL, 0 ); };
	//
	// queries.
	//

	virtual
	BOOL					IsArithmeticOperator()
								{
								return TRUE;
								}
    //
    // test if the expression is a string constant
    //
    virtual
    BOOL                IsStringConstant (void)
                            {
                            return 	GetLeft()->IsStringConstant();
                            }

	virtual
	EXPR_VALUE			GetValue();

    BOOL                GetExprValue( SExprValue& v );

	};


//
// this is the unary not operator class.
//

class expr_u_not	: public expr_op_unary
	{
public:
							expr_u_not( expr_node * pL ) :
											 expr_op_unary(OP_UNARY_NOT, pL )
								{
								}

    virtual expr_node*      Clone() { return new expr_u_not( 0 ); };
	//
	// queries.
	//

	virtual
	BOOL					IsLogicalOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE			GetValue();

	};


//
// the unary complement class.
//

class expr_u_complement	: public expr_op_unary
	{
public:
						expr_u_complement( expr_node *pL ) :
								expr_op_unary(OP_UNARY_COMPLEMENT, pL)
							{
							}
    virtual expr_node*      Clone() { return new expr_u_complement( 0 ); };
	//
	// queries.
	//

	virtual
	BOOL				IsBitwiseOperator()
							{
							return TRUE;
							}

	virtual
	EXPR_VALUE			GetValue();

	};

//
// unary derefence operator 
//

class expr_u_deref	: public expr_op_unary
	{
public:
							expr_u_deref( expr_node *pL ) :
									expr_op_unary(OP_UNARY_INDIRECTION, pL)
								{
								SetConstant( FALSE );
								}
							expr_u_deref( OPERATOR op, expr_node *pL ) :
									expr_op_unary(op, pL)
								{
								SetConstant( FALSE );
								}

    virtual expr_node*      Clone() { return new expr_u_deref( 0 ); };
    virtual
    short               MakeListOfDerefedVars( ITERATOR& List );

	};

//
//
class expr_u_address	: public expr_op_unary
	{
public:
							expr_u_address( expr_node *pL ) :
									expr_op_unary(OP_UNARY_AND, pL)
								{
								SetConstant( FALSE );
								}

    virtual expr_node*      Clone() { return new expr_u_address( 0 ); };
	};


//
// the unary cast operator
//
class expr_cast	: public expr_op_unary
	{
	node_skl*   pCastType;
    bool        fEmitModifiers;

public:
							expr_cast( node_skl * pT, expr_node *pL ) : 
											expr_op_unary(OP_UNARY_CAST, pL),
                                            fEmitModifiers( true )
								{
								pCastType = pT;
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_cast( 0, 0 ); };
	//
	// Given an output steam, output the expression.
	//
    virtual
    void                SetEmitModifiers(bool fModifier = true) { fEmitModifiers = fModifier; }
    virtual
    bool                GetEmitModifiers() { return fEmitModifiers; }

	virtual
	void				Print( ISTREAM * pS );

	virtual
	node_skl	*		GetType()
							{
							return pCastType;
							}
	
	virtual
	EXPR_VALUE			GetValue();


	};

//
// the unary sizeof operator.
//

class expr_sizeof : public expr_op_unary
	{
	node_skl	*			pType;

public:
							expr_sizeof( node_skl *pT) :
									    expr_op_unary( OP_UNARY_SIZEOF,NULL ) 
								{
								pType = pT;
								}

							expr_sizeof( expr_node *pL ) :
										expr_op_unary( OP_UNARY_SIZEOF,pL )
								{
								pType = pL->GetType();
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_sizeof( (node_skl*)0 ); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

    virtual
    short               MakeListOfVars( ITERATOR & pList );

	virtual
	EXPR_VALUE			GetValue();


	};

//
// the unary __alignof operator.
//

class expr_alignof : public expr_op_unary
	{
	node_skl	*			pType;

public:
							expr_alignof( node_skl *pT) :
									    expr_op_unary( OP_UNARY_ALIGNOF, NULL ) 
								{
								pType = pT;
								}

							expr_alignof( expr_node *pL ) :
										expr_op_unary( OP_UNARY_ALIGNOF, pL )
								{
								pType = pL->GetType();
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_alignof( (node_skl*)0 ); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

    virtual
    short               MakeListOfVars( ITERATOR & pList );

	virtual
	EXPR_VALUE			GetValue();


	};

//
// unary pre-increment operator.
//
class expr_pre_incr	: public expr_op_unary
	{
public:
							expr_pre_incr( expr_node *pL ) :
										expr_op_unary(OP_PRE_INCR, pL)
								{
								SetType( pL->GetType());
								}
    virtual expr_node*      Clone() { return new expr_pre_incr(0); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );


	};

//
// unary pre-decrement operator.
//
class expr_pre_decr	: public expr_op_unary
	{
public:
							expr_pre_decr( expr_node *pL ):
										expr_op_unary(OP_PRE_DECR, pL)
								{
								SetType( pL->GetType());
								}
    virtual expr_node*      Clone() { return new expr_pre_decr(0); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );


	};

//
// unary post-increment operator.
//
class expr_post_incr	: public expr_op_unary
	{
public:
							expr_post_incr( expr_node *pL ):
										expr_op_unary(OP_POST_INCR, pL)
								{
								SetType( pL->GetType());
								}
    virtual expr_node*      Clone() { return new expr_post_incr(0); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );


	};

//
// unary post-decrement operator.
//
class expr_post_decr	: public expr_op_unary
	{
public:
							expr_post_decr( expr_node *pL ):
										expr_op_unary(OP_POST_DECR, pL)
								{
								SetType( pL->GetType());
								}
    virtual expr_node*      Clone() { return new expr_post_decr(0); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );


	};

//
// binary arithmetic operators.
//

class expr_b_arithmetic	: public expr_op_binary
	{
public:

							expr_b_arithmetic(	OPERATOR Op,
												expr_node *pL,
												expr_node *pR ):
										expr_op_binary( Op, pL, pR )
								{
								}

    virtual expr_node*      Clone() { return new expr_b_arithmetic(OP_ILLEGAL,0,0); };
	//
	// queries.
	//

	virtual
	BOOL					IsArithmeticOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE				GetValue();

    BOOL                    GetExprValue( SExprValue& v );

	};

//
// binary logical operators.
//

class expr_b_logical	: public expr_op_binary
	{
public:

							expr_b_logical(	OPERATOR Op,
												expr_node *pL,
												expr_node *pR ):
										expr_op_binary( Op, pL, pR )
								{
								}

    virtual expr_node*      Clone() { return new expr_b_logical(OP_ILLEGAL,0,0); };
	//
	// queries.
	//

	virtual
	BOOL					IsLogicalOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE				GetValue();


	};

//
// relational operators.
//

class expr_relational	: public expr_op_binary
	{
public:

							expr_relational(	OPERATOR Op,
												expr_node *pL,
												expr_node *pR ):
										expr_op_binary( Op, pL, pR )
								{
								}

    virtual expr_node*      Clone() { return new expr_relational(OP_ILLEGAL,0,0); };
	//
	// queries.
	//

	virtual
	BOOL					IsRelationalOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE			GetValue();


	};

//
// shift operators.
//

class expr_shift	: public expr_op_binary
	{
public:

							expr_shift(	OPERATOR Op,
												expr_node *pL,
												expr_node *pR ):
										expr_op_binary( Op, pL, pR )
								{
								}

    virtual expr_node*      Clone() { return new expr_shift(OP_ILLEGAL,0,0); };
	//
	// queries.
	//

	virtual
	BOOL					IsShiftOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE				GetValue();


	};

//
// bitwise operators.
//

class expr_bitwise	: public expr_op_binary
	{
public:

							expr_bitwise(	OPERATOR Op,
												expr_node *pL,
												expr_node *pR ):
										expr_op_binary( Op, pL, pR )
								{
								}

    virtual expr_node*      Clone() { return new expr_bitwise(OP_ILLEGAL,0,0); };
	//
	// queries.
	//

	virtual
	BOOL					IsBitwiseOperator()
								{
								return TRUE;
								}

	virtual
	EXPR_VALUE				GetValue();


	};

//
// dot operator.
//

class expr_dot	: public expr_op_binary
	{
public:

							expr_dot( expr_node *pL, expr_node *pR ):
										expr_op_binary( OP_DOT, pL, pR )
								{
								}
    virtual expr_node*      Clone() { return new expr_dot(0,0); };
	};

//
// pointsto operator.
//

class expr_pointsto	: public expr_op_binary
	{
public:

							expr_pointsto( expr_node *pL, expr_node *pR ):
										expr_op_binary( OP_POINTSTO, pL, pR )
								{
								}
    virtual expr_node*      Clone() { return new expr_pointsto(0,0); };
	};

//
// array element operator.
//

class expr_index	: public expr_op_binary
	{
public:

							expr_index( expr_node *pL, expr_node *pR );

    virtual expr_node*      Clone() { return new expr_index(0,0); };
	//
	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );

	virtual
	void				PrintCall( ISTREAM * pS,
								   short LeftMargin,
								   BOOL fInProc );


	};

//
// comma operator.
//

class expr_comma	: public expr_op_binary
	{
public:

							expr_comma( expr_node *pL, expr_node *pR ):
										expr_op_binary( OP_COMMA, pL, pR )
								{
								}
    virtual expr_node*      Clone() { return new expr_comma(0,0); };
	};

//
// assign operator.
//

class expr_assign	: public expr_op_binary
	{
public:

							expr_assign( expr_node *pL, expr_node *pR ):
										expr_op_binary( OP_ASSIGN, pL, pR )
								{
								}
    virtual expr_node*      Clone() { return new expr_assign(0,0); };
	virtual
	void					PrintCall( ISTREAM * pS,
									   short LeftMargin,
									   BOOL fInProc );


	};

//
// proc operator.
//

class expr_proc_call	: public expr_op_unary
	{
private:
	PNAME					pName;
	short					NoOfParams;

	//
	// Set the first parameter of the function. This is a private method
	// because the world should use the SetParam function which will take care
	// of inserting the new param expression in the correct (last) place in the
	// parameter list.
	//

	class expr_param	*	SetFirstParam( class expr_param * p )
								{
								return (class expr_param *)SetLeft(
												(class expr_node *) p );
								}

public:

							expr_proc_call(PNAME pN,
									  expr_node *pParamList):
										expr_op_unary(OP_FUNCTION,pParamList)
								{
								SetName( pN );
								SetNoOfParams( 0 );
								}

							expr_proc_call( PNAME pN ) : 
										expr_op_unary(OP_FUNCTION, 0)
								{
								SetName( pN );
								SetNoOfParams( 0 );
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_proc_call(0); };
	//
	// get and set functions.
	//

	void					SetName( PNAME pN )
								{
								pName = pN;
								}

	PNAME					GetName()
								{
								return pName;
								}

	unsigned short			SetNoOfParams( unsigned short N )
								{
								return (NoOfParams = N);
								}

	unsigned short			GetNoOfParams()
								{
								return NoOfParams;
								}
	unsigned short			IncrNoOfParams()
								{
								return (++NoOfParams);
								}
	//
	// This method is used to get at the first param of a function. After
	// that GetNextParam calls are made on the param node itself. This will
	// be our most frequent usage, eg in the printing of the expression.
	//

	class expr_param	*	GetFirstParam()
								{
								return (class expr_param *)GetLeft();
								}

	//
	// This method will insert the parameter expression at the end of the
	// parameter list. This is done so that an procedure call expression
	// can be created in the natural (left to right) order.
	//

	class expr_param	*	SetParam( class expr_param * pParam );

    class expr_param   *   SetParam( expr_node * pExpr );

	//
	// Given an output steam, output the expression. This does not
	// generate a semi-colon.
	//

	virtual
	void				Print( ISTREAM * pS );


	//
	// This call generates a call with a semi-colon
	//

	virtual
	void				PrintCall( ISTREAM * pS, short InitMargin, BOOL fInProc );

	};

class expr_param	: public expr_op_binary
	{
private:
	PNAME					pName;
public:

							expr_param(expr_node *pParamExpr ):
									expr_op_binary(OP_PARAM,pParamExpr, 0)
								{
                                pName = NULL;
								}

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_param(0); };
	//
	// queries.
	//

	//
	// This method gets the next parameter in the parameter list. To emit the
	// parameter expressions for a procedure, get the first parameter on the
	// expr_proc_call node and then make GetNextParam calls on the parameter
	// till the call returns a null.
	//

	expr_param	*			GetNextParam()
								{
								return (expr_param *)GetRight();
								}
	
	//
	// This method sets the next param expression to be the one specified. This
	// method does not traverse the list of params and insert at the end !!.
	//

	expr_param	*			SetNextParam( expr_param * p )
								{
								return (expr_param *)SetRight( p );
								}

	//
	// This method traverses to the end of the parameter list and inserts a new
	// param expression at the end .Use this method when a procedure call
	// expression is being generated. The way to do this is to create a 
	// expr_proc_call node and make as many SetParam calls to it as there are
	// parameter expressions. They will all get inserted into the parameter list
	// in the left to right (natural) order, with each new param expression
	// going to the end of the list.
	//

	expr_param	*			SetLastPeerParam( expr_param * pN );


	// Given an output steam, output the expression.
	//

	virtual
	void				Print( ISTREAM * pS );


	virtual
	void				PrintCall( ISTREAM * pS,
								   short LeftMargin,
								   BOOL fInProc );

	};



//
// ternary operator class. Each ternary operator node takes a relational, left and right
// expression connected by the ternary operator.
//

class expr_ternary	: public expr_operator
	{
private:

	expr_node			*	pLeft;
	expr_node			*	pRight;
	expr_node			*	pRelational;

public:

	//
	// this class is instantiated by specifying the left/right and the
	// operator.
	//

							expr_ternary( OPERATOR		Op,
											expr_node	*	pRel,
											expr_node	*	pL,
											expr_node	*	pR ) : 
													expr_operator( Op )
								{
								SetRelational( pRel );
								SetLeft( pL );
								SetRight( pR );
								SetConstant( ( (pL) ? pL->IsConstant() : TRUE ) &&
											 ( (pR) ? pR->IsConstant() : TRUE ) &&
											 ( (pRel) ? pRel->IsConstant() : TRUE ) );
								}
	
    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone();
	//
	// get and set.
	//

	virtual
	expr_node 		*		SetRelational( expr_node *p )
								{
								return (pRelational = p);
								}

	virtual
	expr_node 		*		SetLeft( expr_node *p )
								{
								return (pLeft = p);
								}

	virtual
	expr_node		*		SetRight( expr_node *p )
								{
								return (pRight = p);
								}

	virtual
	expr_node		*		GetRelational()
								{
								return pRelational;
								}
	virtual
	expr_node		*		GetLeft()
								{
								return pLeft;
								}


	virtual
	expr_node		*		GetRight()
								{
								return pRight;
								}

	//
	// queries.
	//

	virtual
	BOOL					IsBinaryOperator()
								{
								return TRUE;
								}
	//
	// Given an output steam, output the expression.
	//

	void				Print( ISTREAM * pS );

	virtual
	EXPR_VALUE			GetValue();


	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

    virtual
    short               MakeListOfVars( ITERATOR & pList );

	};


// gaj - these are added for now to satisfy the grammar

class expr_init_list:	public expr_node
	{
private:
	class expr_init_list	*	pSibling;
	class expr_node			*	pExpr;

public:
							expr_init_list( expr_node * pE )
								{
								pExpr = pE;
								SetConstant( pE->IsConstant() );
								};

    virtual void            CopyTo( expr_node* lhs );

    virtual expr_node*      Clone() { return new expr_init_list(0); };

	virtual
	void					LinkSibling( class expr_init_list * pIL )
								{
								pSibling = pIL;
								}

	// assume only the first value here...
	virtual
	EXPR_VALUE				GetValue()
								{
								return pExpr->GetValue();
								}

	//
	// Given an output steam, output the expression.
	//

	virtual
	void					Print( ISTREAM * pS )
								{
								pExpr->Print( pS );
								}

	//
	// determine the type of the expression
	//

	virtual
	void				DetermineType();

	//
	// analyze the expression
	//
	virtual
	void				ExprAnalyze( EXPR_CTXT * pExprCtxt );

	};


class expr_error:	public expr_node
	{
public:
    virtual expr_node*      Clone() { return new expr_error; };
	};

#endif // __EXPR_HXX__
