 <5                     <4..4> (the normal ILTree) TextSpan
        //    Console.WriteLine("hello")   <5..5> BodySpan
        // 5> End Sub 4>
        // NOTE: like everything else here, we rely on the fact that (1) this class is zero-inited upon
        // allocation, and (2) a location that's zero-inited is considered invalid.

        BCSYM_Hash *GetLocalsHash();

        void SetLocalsHash(_In_ BCSYM_Hash *pValue);

        Expression **GetAddressOfExpressionLambdaBody();

        ILNode *GetLambdaBody();

        Expression *GetExpressionLambdaBody()
        {
            // This routine must stay inside BoundTrees.h so that vbdgee can compile okay. vbdgee includes the header but not the.cpp of this struct.
            VSASSERT(!IsStatementLambda, "This was not an expression lambda");
            return!IsStatementLambda? pLambdaExpression : NULL;
        }

        Type *GetExpressionLambdaReturnType();

        void SetExpressionLambdaBody(_In_ Expression *pValue);

        StatementLambdaBlock *GetStatementLambdaBody();

        void SetStatementLambdaBody(_In_ StatementLambdaBlock *pValue);

    private:
        BCSYM_Hash *pLocalsHash;
       union 
        {
            Expression *pLambdaExpression;

            StatementLambdaBlock *pLambdaStatementBlock;
        };
    };

    // Use AsUnboundLambdaExpression() accessor.
    struct UnboundLambdaExpression : Expression
    {
        BCSYM_Param           *FirstParameter;

    private:
        union
        {
            // These fields are private so we can have getter/setter methods to VSASSERT the
            // consistency of them with respect to various flag fields, e.g. IsStatementLambda, IsFunctionLambda...
            ParseTree::Expression *LambdaExpression;         // for!IsStatementLambda
            ParseTree::LambdaBodyStatement*pLambdaStatement; // for  IsStatementLambda
        };
    public:
        ParseTree::Expression *GetLambdaExpression()
        {
            VSASSERT(!IsStatementLambda, "Internal error: can't get expression of a statement lambda");
            return LambdaExpression;
        }

        void SetLambdaExpression(ParseTree::Expression *LambdaExpression)
        {
            this->LambdaExpression = LambdaExpression;
        }

        ParseTree::LambdaBodyStatement *GetLambdaStatement()
        {
            VSASSERT(IsStatementLambda || IsAsyncKeywordUsed, "Internal error: can't get statement-body of an expression lambda");
            return pLambdaStatement;
        }

        void SetLambdaStatement(ParseTree::LambdaBodyStatement *pLambdaStatement)
        {
            this->pLambdaStatement = pLambdaStatement;
        }
        

        bool                  AllowRelaxationSemantics;
        unsigned __int64      InterpretBodyFlags; //ExpressionFlags to pass to InterpretExpression of the body
        unsigned char ExactlyMatchExpressionResultType:1; // Do not apply conversions to the LambdaExpression to match delegate's return type, LambdaExpression's type should match exactly
        unsigned char IsStatementLambda:1; // Distinguish between Expression Lambdas and Statement Lambdas. Note:
                                           // for a statement lambda masquerading as an expression, this flag is false.
                                           // Thus, this flag can be used to decide whether to GetLambdaExpression() or GetLambdaStatement()
        unsigned char IsSingleLine : 1; // Is it a line-lambda?
        unsigned char IsFunctionLambda:1; // Distinguish between Sub and Function lambdas
        unsigned char IsAsyncKeywordUsed:1;
        unsigned char IsIteratorKeywordUsed:1;
        Location BodySpan;   // see comment about BodySpan in "LambdaExpression" above for its geometry

    };

        // Use sxDeferredTemp() accessor.
    struct DeferredTempExpression : Expression
    {
        unsigned Id;
        unsigned __int64      InterpretFlags; //ExpressionFlags to pass to InterpretExpression of the body
        ParseTree::Expression *InitialValue;
    };

	// ----------------------------------------------------------------------------
	// Contains the binding information for anonymous types. This would be:
	// 1. The bound property corresponding to this member.
	// 2. The bound expression.
	// 3. The temporary (if applicable) that contains the value for the bound
	//    expression.
	//
	// Expression trees cannot hold temps; thus, for expression trees, all expressions
	// must be non-temp-based.
	// ----------------------------------------------------------------------------

    struct BoundMemberInfoList
    {
        BCSYM_Property* Property;
        Expression* BoundExpression;
        Expression* Temp;

        BoundMemberInfoList() :
            Property( NULL ),
            BoundExpression( NULL ),
            Temp( NULL )
        {

        }
    };

    // Use AsAnonymousTypeExpression() accessor.
    // This tree must not go to code gen. The lowering phase would rebuild it.
    // It contains bound information for anonymous types.
    struct AnonymousTypeExpression : Expression
    {
        ULONG BoundMembersCount;
        BoundMemberInfoList* BoundMembers;
        BCSYM_Proc* Constructor;
        BCSYM_GenericBinding* AnonymousTypeBinding;
    };

    struct ArrayLiteralExpression : Expression
    {
        ExpressionWithChildren * ElementList; 
        unsigned NumDominantCandidates; // if there were!=1 DominantCandidates, then Dominant will be "Object" by assumption
        unsigned Rank;
        unsigned * Dims;
    };

    struct NestedArrayLiteralExpression : Expression
    {
        ExpressionWithChildren * ElementList;
    };

    //Represents a collection initializer
    struct ColInitExpression : Expression
    {
        Expression * NewExpression;
        //A list of SX_ColInitElement nodes
        ExpressionWithChildren * Elements;
        SymbolReferenceExpression * ResultTemporary;
    };

    struct ColInitElementExpression : Expression
    {
        Expression * CallExpression;
        Expression * CopyOutArguments;
        //Stores the flags that were passed into the 
        //InterpretCallExpression call that 
        //created the expression. 
        ExpressionFlags CallInterpretationFlags; 
    };

	/*****************************************************************************/
    /*
    /* Inline functions to access the private union members of BILTREE
    /*
    /*****************************************************************************/
    inline struct Expression &  ILNode::AsExpression()
    {
        VSASSERT(this->IsExprNode(), "ILNode: using wrong node type!");
        return(*(Expression *)this);
    }
    inline struct Statement &  ILNode::AsStatement()
    {
        VSASSERT(this->IsStmtNode(), "ILNode: using wrong node type!");
        return(*(Statement *)this);
    }
#pragma prefast(push)
#pragma prefast(disable: 25094, "No destructors in the ILNode")
    inline struct ExecutableBlock &  ILNode::AsExecutableBlock()
    {
        VSASSERT(this->IsExecutableBlockNode(), "ILNode: using wrong node type!");
        return(*(ExecutableBlock *)this);
    }
#pragma prefast(pop)
    inline struct ProcedureBlock &  ILNode::AsProcedureBlock()
    {
        VSASSERT(this->IsExecutableBlockNode(), "ILNode: using wrong node type!");
        VSASSERT((strcmp(s_szBiltreeWhichSubStruct[this->bilop], "ProcedureBlock") == 0) ||
                 (strcmp(s_szBiltreeWhichSubStruct[this->bilop], "sbProcDef") == 0),
                 "ILNode: using wrong node type!");
        return(*(ProcedureBlock *)this);
    }

    inline struct StatementLambdaBlock & ILNode::AsStatementLambdaBlock()
    {
        VSASSERT(this->IsExecutableBlockNode(), "ILNode: using wrong node type!");
        VSASSERT(strcmp(s_szBiltreeWhichSubStruct[this->bilop], "StatementLambdaBlock") == 0,
                 "ILNode: using wrong node type!");
        return(*(StatementLambdaBlock *)this);

    }

    inline struct IfSelectBlock &  ILNode::AsIfSelectBlock()
    {
        VSASSERT(this->IsExecutableBlockNode(), "ILNode: using wrong node type!");
        VSASSERT(this->bilop == SB_IF || this->bilop == SB_SELECT,
                 "ILNode: using wrong node type!");
        return(*(IfSelectBlock *)this);
    }
    inline struct IfGroup &  ILNode::AsIfGroup()
    {
        VSASSERT(this->IsExecutableBlockNode(), "ILNode: using wrong node type!");
        VSASSERT(!strcmp(s_szBiltreeWhichSubStruct[this->bilop], "IfGroup"),
                 "ILNode: using wrong node type!");
        return(*(IfGroup *)this);
    }
    inline