//---------------------------------------------------------------------
// <copyright file="ScalarOps.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  [....]
// @backupOwner [....]
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics;
using System.Data.Common;
using System.Data.Metadata.Edm;

namespace System.Data.Query.InternalTrees
{
    #region Constants

    /// <summary>
    /// Base class for all constant Ops
    /// </summary>
    internal abstract class ConstantBaseOp : ScalarOp
    {
        #region private state
        private readonly object m_value;
        #endregion

        #region constructors
        protected ConstantBaseOp(OpType opType, TypeUsage type, object value)
            : base(opType, type)
        {
            m_value = value;
        }

        /// <summary>
        /// Constructor overload for rules
        /// </summary>
        /// <param name="opType"></param>
        protected ConstantBaseOp(OpType opType)
            : base(opType)
        {
        }
        #endregion

        #region public properties and methods
        /// <summary>
        /// Get the constant value
        /// </summary>
        internal virtual Object Value { get { return m_value; } }

        /// <summary>
        /// 0 children
        /// </summary>
        internal override int Arity { get { return 0; } }

        /// <summary>
        /// Two CostantBaseOps are equivalent if they are of the same 
        /// derived type and have the same type and value. 
        /// </summary>
        /// <param name="other">the other Op</param>
        /// <returns>true, if these are equivalent (not a strict equality test)</returns>
        internal override bool IsEquivalent(Op other)
        {
            ConstantBaseOp otherConstant = other as ConstantBaseOp;
            return 
                otherConstant != null && 
                this.OpType == other.OpType &&
                otherConstant.Type.EdmEquals(this.Type) && 
                ((otherConstant.Value == null && this.Value == null) || otherConstant.Value.Equals(this.Value));
        }
        #endregion
    }

    /// <summary>
    /// Represents an external constant
    /// </summary>
    internal sealed class ConstantOp : ConstantBaseOp
    {
        #region constructors
        internal ConstantOp(TypeUsage type, object value)
            : base(OpType.Constant, type, value)
        {
            Debug.Assert(value != null, "ConstantOp with a null value?");
        }
        private ConstantOp() : base(OpType.Constant) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly ConstantOp Pattern = new ConstantOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    /// <summary>
    /// Represents null constants
    /// </summary>
    internal sealed class NullOp : ConstantBaseOp
    {
        #region constructors
        internal NullOp(TypeUsage type)
            : base(OpType.Null, type, null)
        {
        }
        private NullOp() : base(OpType.Null) { }
        #endregion

        #region public apis

        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NullOp Pattern = new NullOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    /// <summary>
    /// Represents internally generated constants
    /// </summary>
    internal sealed class InternalConstantOp : ConstantBaseOp
    {
        #region constructors
        internal InternalConstantOp(TypeUsage type, object value)
            : base(OpType.InternalConstant, type, value)
        {
            Debug.Assert(value != null, "InternalConstantOp with a null value?");
        }
        private InternalConstantOp() : base(OpType.InternalConstant) { }
        #endregion

        #region public apis

        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly InternalConstantOp Pattern = new InternalConstantOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    /// <summary>
    /// Represents an internally generated constant that is used to serve as a null sentinel, 
    /// i.e. to be checked whether it is null.
    /// </summary>
    internal sealed class NullSentinelOp : ConstantBaseOp
    {
        #region constructors
        internal NullSentinelOp(TypeUsage type, object value)
            : base(OpType.NullSentinel, type, value)
        {
        }
        private NullSentinelOp() : base(OpType.NullSentinel) { }
        #endregion

        #region public apis
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NullSentinelOp Pattern = new NullSentinelOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    /// <summary>
    /// Represents a constant predicate (with a value of either true or false)
    /// </summary>
    internal sealed class ConstantPredicateOp : ConstantBaseOp
    {
        #region constructors
        internal ConstantPredicateOp(TypeUsage type, bool value)
            : base(OpType.ConstantPredicate, type, value)
        {
        }
        private ConstantPredicateOp()
            : base(OpType.ConstantPredicate)
        { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly ConstantPredicateOp Pattern = new ConstantPredicateOp();

        /// <summary>
        /// Value of the constant predicate
        /// </summary>
        internal new bool Value { get { return (bool)base.Value; } }

        /// <summary>
        /// Is this the true predicate
        /// </summary>
        internal bool IsTrue { get { return this.Value; } }

        /// <summary>
        /// Is this the 'false' predicate
        /// </summary>
        internal bool IsFalse { get { return this.Value == false; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    #endregion

    /// <summary>
    /// A reference to an existing variable
    /// </summary>
    internal sealed class VarRefOp : ScalarOp
    {
        #region private state
        private Var m_var;
        #endregion

        #region constructors
        internal VarRefOp(Var v) : base(OpType.VarRef, v.Type)
        {
            m_var = v;
        }
        private VarRefOp() : base(OpType.VarRef) { }
        #endregion

        #region public methods
        /// <summary>
        /// Singleton used for pattern matching
        /// </summary>
        internal static readonly VarRefOp Pattern = new VarRefOp();

        /// <summary>
        /// 0 children
        /// </summary>
        internal override int Arity { get { return 0; } }

        /// <summary>
        /// Two VarRefOps are equivalent, if they reference the same Var
        /// </summary>
        /// <param name="other">the other Op</param>
        /// <returns>true, if these are equivalent</returns>
        internal override bool IsEquivalent(Op other)
        {
            VarRefOp otherVarRef = other as VarRefOp;
            return (otherVarRef != null && otherVarRef.Var.Equals(this.Var));
        }

        /// <summary>
        /// The Var that this Op is referencing
        /// </summary>
        internal Var Var { get { return m_var; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents an arbitrary function call
    /// </summary>
    internal sealed class FunctionOp : ScalarOp
    {
        #region private state
        private EdmFunction m_function;
        #endregion

        #region constructors
        internal FunctionOp(EdmFunction function)
            : base(OpType.Function, function.ReturnParameter.TypeUsage)
        {
            m_function = function;
        }
        private FunctionOp() : base(OpType.Function) { }
        #endregion

        #region public methods
        /// <summary>
        /// Singleton instance used for patterns in transformation rules
        /// </summary>
        internal static readonly FunctionOp Pattern = new FunctionOp();

        /// <summary>
        /// The function that's being invoked
        /// </summary>
        internal EdmFunction Function { get { return m_function; } }

        /// <summary>
        /// Two FunctionOps are equivalent if they reference the same EdmFunction
        /// </summary>
        /// <param name="other">the other Op</param>
        /// <returns>true, if these are equivalent</returns>
        internal override bool IsEquivalent(Op other)
        {
            FunctionOp otherFunctionOp = other as FunctionOp;
            return (otherFunctionOp != null && otherFunctionOp.Function.EdmEquals(this.Function));
        }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents a property access
    /// </summary>
    internal sealed class PropertyOp : ScalarOp
    {
        #region private state
        private EdmMember m_property;
        #endregion

        #region constructors
        internal PropertyOp(TypeUsage type, EdmMember property)
            : base(OpType.Property, type)
        {
            Debug.Assert((property is EdmProperty) || (property is RelationshipEndMember) || (property is NavigationProperty), "Unexpected EdmMember type");
            m_property = property;
        }
        private PropertyOp() : base(OpType.Property) { }
        #endregion

        #region public methods
        /// <summary>
        /// Used for patterns in transformation rules
        /// </summary>
        internal static readonly PropertyOp Pattern = new PropertyOp();

        /// <summary>
        /// 1 child - the instance
        /// </summary>
        internal override int Arity { get { return 1; } }

		/// <summary>
        /// The property metadata
        /// </summary>
        internal EdmMember PropertyInfo { get { return m_property; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
	    #endregion
    }

    /// <summary>
    /// Represents a TREAT AS operation
    /// </summary>
    internal sealed class TreatOp : ScalarOp
    {
        #region private state
        private bool m_isFake;
        #endregion

        #region constructors
        internal TreatOp(TypeUsage type, bool isFake)
            : base(OpType.Treat, type)
        {
            m_isFake = isFake;
        }
        private TreatOp() : base(OpType.Treat) { }
        #endregion

        #region public methods
        /// <summary>
        /// Used as patterns in transformation rules
        /// </summary>
        internal static readonly TreatOp Pattern = new TreatOp();

        /// <summary>
        /// 1 child - instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Is this a "fake" treat?
        /// </summary>
        internal bool IsFakeTreat { get { return m_isFake; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// An IS OF operation
    /// </summary>
    internal sealed class IsOfOp : ScalarOp
    {
        #region private state
        private TypeUsage m_isOfType;
        private bool m_isOfOnly;
        #endregion

        #region constructors
        internal IsOfOp(TypeUsage isOfType, bool isOfOnly, TypeUsage type)
            : base(OpType.IsOf, type)
        {
            m_isOfType = isOfType;
            m_isOfOnly = isOfOnly;
        }
        private IsOfOp() : base(OpType.IsOf) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern used for transformation rules
        /// </summary>
        internal static readonly IsOfOp Pattern = new IsOfOp();

        /// <summary>
        /// 1 child - instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// The type being checked for
        /// </summary>
        internal TypeUsage IsOfType { get { return m_isOfType; } }

        internal bool IsOfOnly { get { return m_isOfOnly; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Cast operation. Convert a type instance into an instance of another type
    /// </summary>
    internal sealed class CastOp : ScalarOp
    {
        #region constructors
        internal CastOp(TypeUsage type) : base(OpType.Cast, type) { }
        private CastOp() : base(OpType.Cast) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly CastOp Pattern = new CastOp();

        /// <summary>
        /// 1 child - instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// An internal cast operation. (Softly) Convert a type instance into an instance of another type
    /// 
    /// This Op is intended to capture "promotion" semantics. (ie) int16 promotes to an int32; Customer promotes to Person
    /// etc. This Op is intended to shield the PlanCompiler from having to reason about 
    /// the promotion semantics; and is intended to make the query tree very 
    /// explicit
    /// 
    /// </summary>
    internal sealed class SoftCastOp : ScalarOp
    {
        #region constructors
        internal SoftCastOp(TypeUsage type) : base(OpType.SoftCast, type) { }
        private SoftCastOp() : base(OpType.SoftCast) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly SoftCastOp Pattern = new SoftCastOp();

        /// <summary>
        /// 1 child - input expression
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents a comparision operation (LT, GT etc.)
    /// </summary>
    internal sealed class ComparisonOp : ScalarOp
    {
        #region constructors
        internal ComparisonOp(OpType opType, TypeUsage type)
            : base(opType, type)
        {
        }
        private ComparisonOp(OpType opType) : base(opType) { }
        #endregion

        #region public methods
        /// <summary>
        /// Patterns for use in transformation rules
        /// </summary>
        internal static readonly ComparisonOp PatternEq = new ComparisonOp(OpType.EQ);

        /// <summary>
        /// 2 children - left, right
        /// </summary>
        internal override int Arity { get { return 2; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents a string comparison operation
    /// </summary>
    internal sealed class LikeOp : ScalarOp
    {
        #region constructors
        internal LikeOp(TypeUsage boolType)
            : base(OpType.Like, boolType) { }
        private LikeOp() : base(OpType.Like) { }
        #endregion

        #region public surface
        /// <summary>
        /// Pattern for use in transformation rules
        /// </summary>
        internal static readonly LikeOp Pattern = new LikeOp();

        /// <summary>
        /// 3 children - string, pattern , escape
        /// </summary>
        internal override int Arity { get { return 3; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents a conditional operation - and,or,not, is null
    /// A little hacky - since it represents and/or/not as optypes - could I not
    /// have done the same with the comparison operators?
    /// </summary>
    internal sealed class ConditionalOp : ScalarOp
    {
        #region constructors
        internal ConditionalOp(OpType optype, TypeUsage type) : base(optype, type)
        {
        }
        private ConditionalOp(OpType opType) : base(opType) { }
        #endregion

        #region public methods
        /// <summary>
        /// Patterns for use in transformation rules
        /// </summary>
        internal static readonly ConditionalOp PatternAnd = new ConditionalOp(OpType.And);
        internal static readonly ConditionalOp PatternOr = new ConditionalOp(OpType.Or);
        internal static readonly ConditionalOp PatternNot = new ConditionalOp(OpType.Not);
        internal static readonly ConditionalOp PatternIsNull = new ConditionalOp(OpType.IsNull);

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// ANSI switched Case expression.
    /// </summary>
    internal sealed class CaseOp : ScalarOp
    {
        #region constructors
        internal CaseOp(TypeUsage type) : base(OpType.Case, type) { }
        private CaseOp() : base(OpType.Case) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for use in transformation rules
        /// </summary>
        internal static readonly CaseOp Pattern = new CaseOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Basic Aggregates
    /// </summary>
    internal sealed class AggregateOp : ScalarOp
    {
        #region private state
        private EdmFunction m_aggFunc;
        private bool m_distinctAgg;
        #endregion

        #region constructors
        internal AggregateOp(EdmFunction aggFunc, bool distinctAgg)
            : base(OpType.Aggregate, aggFunc.ReturnParameter.TypeUsage)
        {
            m_aggFunc = aggFunc;
            m_distinctAgg = distinctAgg;
        }
        private AggregateOp() : base(OpType.Aggregate) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly AggregateOp Pattern = new AggregateOp();

        /// <summary>
        /// The Aggregate function's metadata
        /// </summary>
        internal EdmFunction AggFunc { get { return m_aggFunc; } }

        /// <summary>
        /// Is this a "distinct" aggregate
        /// </summary>
        internal bool IsDistinctAggregate { get { return m_distinctAgg; } }

        /// <summary>
        /// Yes; this is an aggregate
        /// </summary>
        internal override bool IsAggregateOp {get{return true;}}

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents an arbitrary nest operation - can be used anywhere
    /// </summary>
    internal sealed class CollectOp : ScalarOp
    {
        #region constructors
        internal CollectOp(TypeUsage type) : base(OpType.Collect, type) { }
        private CollectOp() : base(OpType.Collect) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for use in transformation rules
        /// </summary>
        internal static readonly CollectOp Pattern = new CollectOp();

        /// <summary>
        /// 1 child - instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Almost identical to a PropertyOp - the only difference being that we're dealing with an 
    /// "extended" property (a rel property) this time
    /// </summary>
    internal sealed class RelPropertyOp : ScalarOp
    {
        #region private state
        private readonly RelProperty m_property;
        #endregion

        #region constructors
        private RelPropertyOp() : base(OpType.RelProperty) { }

        internal RelPropertyOp(TypeUsage type, RelProperty property)
            : base(OpType.RelProperty, type)
        {
            m_property = property;
        }
        #endregion

        #region public APIs
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly RelPropertyOp Pattern = new RelPropertyOp();

        /// <summary>
        /// 1 child - the entity instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Get the property metadata
        /// </summary>
        public RelProperty PropertyInfo { get { return m_property; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }

        #endregion
    }

    /// <summary>
    /// Base class for DiscriminatedNewEntityOp and NewEntityOp
    /// </summary>
    internal abstract class NewEntityBaseOp : ScalarOp
    {
        #region private state
        private readonly bool m_scoped;
        private readonly EntitySet m_entitySet;
        private readonly List<RelProperty> m_relProperties; // list of relationship properties for which we have values
        #endregion

        #region constructors
        internal NewEntityBaseOp(OpType opType, TypeUsage type, bool scoped, EntitySet entitySet, List<RelProperty> relProperties)
            : base(opType, type)
        {
            Debug.Assert(scoped || entitySet == null, "entitySet cann't be set of constructor isn't scoped");
            Debug.Assert(relProperties != null, "expected non-null list of rel-properties");
            m_scoped = scoped;
            m_entitySet = entitySet;
            m_relProperties = relProperties;
        }

        protected NewEntityBaseOp(OpType opType) : base(opType) { }
        #endregion

        #region public APIs
        /// <summary>
        /// True if the entity constructor is scoped to a particular entity set or null (scoped as "unscoped").
        /// False if the scope is not yet known. Scope is determined in PreProcessor.
        /// </summary>
        internal bool Scoped { get { return m_scoped; } }

        /// <summary>
        /// Get the entityset (if any) associated with this constructor
        /// </summary>
        internal EntitySet EntitySet { get { return m_entitySet; } }

        /// <summary>
        /// get the list of relationship properties (if any) specified for this constructor
        /// </summary>
        internal List<RelProperty> RelationshipProperties { get { return m_relProperties; } }
        #endregion
    }

    /// <summary>
    /// A new entity instance constructor
    /// </summary>
    internal sealed class NewEntityOp : NewEntityBaseOp
    {
        #region constructors
        private NewEntityOp() : base(OpType.NewEntity) { }

        internal NewEntityOp(TypeUsage type, List<RelProperty> relProperties, bool scoped, EntitySet entitySet)
            : base(OpType.NewEntity, type, scoped, entitySet, relProperties)
        {
        }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NewEntityOp Pattern = new NewEntityOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// A new instance creation
    /// </summary>
    internal sealed class NewInstanceOp : ScalarOp
    {
        #region constructors
        internal NewInstanceOp(TypeUsage type) : base(OpType.NewInstance, type) 
        {
            Debug.Assert(!type.EdmType.Abstract, "cannot create new instance of abstract type");
            Debug.Assert(!TypeSemantics.IsEntityType(type), "cannot use this Op for entity construction");
        }
        private NewInstanceOp() : base(OpType.NewInstance) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NewInstanceOp Pattern = new NewInstanceOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Polymorphic new instance creation (takes all properties of all types in the hierarchy + discriminator)
    /// </summary>
    internal sealed class DiscriminatedNewEntityOp : NewEntityBaseOp 
    {
        #region Private state
        private readonly ExplicitDiscriminatorMap m_discriminatorMap;
        #endregion

        #region Constructors
        internal DiscriminatedNewEntityOp(TypeUsage type, ExplicitDiscriminatorMap discriminatorMap,
            EntitySet entitySet, List<RelProperty> relProperties) 
            : base(OpType.DiscriminatedNewEntity, type, true, entitySet, relProperties)
        {
            Debug.Assert(null != discriminatorMap, "null discriminator map");
            m_discriminatorMap = discriminatorMap;
        }
        private DiscriminatedNewEntityOp() : base(OpType.DiscriminatedNewEntity) { }
        #endregion 

        #region "Public" members
        internal static readonly DiscriminatedNewEntityOp Pattern = new DiscriminatedNewEntityOp();

        /// <summary>
        /// Gets discriminator and type information used in construction of type.
        /// </summary>
        internal ExplicitDiscriminatorMap DiscriminatorMap
        {
            get { return m_discriminatorMap; }
        }

        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents a new record constructor
    /// </summary>
    internal sealed class NewRecordOp : ScalarOp
    {
        #region private state
        private List<EdmProperty> m_fields; // list of fields with specified values
        #endregion

        #region constructors
        /// <summary>
        /// Basic constructor. All fields have a value specified
        /// </summary>
        /// <param name="type"></param>
        internal NewRecordOp(TypeUsage type) : base(OpType.NewRecord, type)
        {
            m_fields = new List<EdmProperty>(TypeHelpers.GetEdmType<RowType>(type).Properties);
        }
        /// <summary>
        /// Alternate form of the constructor. Only some fields have a value specified
        /// The arguments to the corresponding Node are exactly 1-1 with the fields
        /// described here.
        /// The missing fields are considered to be "null"
        /// </summary>
        /// <param name="type"></param>
        /// <param name="fields"></param>
        internal NewRecordOp(TypeUsage type, List<EdmProperty> fields)
            : base(OpType.NewRecord, type)
        {
#if DEBUG
            foreach (EdmProperty p in fields)
            {
                Debug.Assert(Object.ReferenceEquals(p.DeclaringType, this.Type.EdmType));
            }
#endif
            m_fields = fields;
        }
        private NewRecordOp() : base(OpType.NewRecord) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NewRecordOp Pattern = new NewRecordOp();

        /// <summary>
        /// Determine if a value has been provided for the specified field.
        /// Returns the position of this field (ie) the specific argument in the Node's
        /// children. If no value has been provided for this field, then simply
        /// return false
        /// </summary>
        /// <param name="field"></param>
        /// <param name="fieldPosition"></param>
        /// <returns></returns>
        internal bool GetFieldPosition(EdmProperty field, out int fieldPosition)
        {
            Debug.Assert(Object.ReferenceEquals(field.DeclaringType, this.Type.EdmType),
                "attempt to get invalid field from this record type");

            fieldPosition = 0;
            for (int i = 0; i < m_fields.Count; i++)
            {
                if (m_fields[i] == field)
                {
                    fieldPosition = i;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// List of all properties that have values specified
        /// </summary>
        internal List<EdmProperty> Properties { get { return m_fields; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    internal sealed class NewMultisetOp : ScalarOp
    {
        #region constructors
        internal NewMultisetOp(TypeUsage type) : base(OpType.NewMultiset, type) { }
        private NewMultisetOp() : base(OpType.NewMultiset) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NewMultisetOp Pattern = new NewMultisetOp();

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents arithmetic operators - Plus,Minus,Multiply,Divide,Modulo,UnaryMinus
    /// </summary>
    internal sealed class ArithmeticOp : ScalarOp
    {
        #region constructors
        internal ArithmeticOp(OpType opType, TypeUsage type)
            : base(opType, type) { }
        #endregion

        #region public methods

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    ///
    /// </summary>
    internal sealed class RefOp : ScalarOp
    {
        #region private state
        private EntitySet m_entitySet;
        #endregion

        #region constructors
        internal RefOp(EntitySet entitySet, TypeUsage type)
            : base(OpType.Ref, type)
        {
            m_entitySet = entitySet;
        }
        private RefOp() : base(OpType.Ref) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly RefOp Pattern = new RefOp();

        /// <summary>
        /// 1 child - key
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// The EntitySet to which the reference refers
        /// </summary>
        internal EntitySet EntitySet { get { return m_entitySet; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents an EXISTS subquery?
    /// </summary>
    internal sealed class ExistsOp : ScalarOp
    {
        #region constructors
        internal ExistsOp(TypeUsage type)
            : base(OpType.Exists, type)
        {
        }
        private ExistsOp() : base(OpType.Exists) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly ExistsOp Pattern = new ExistsOp();

        /// <summary>
        /// 1 child - collection input
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Represents an Element() op - extracts the scalar value from a collection
    /// </summary>
    internal sealed class ElementOp : ScalarOp
    {
        #region constructors
        internal ElementOp(TypeUsage type) : base(OpType.Element, type) { }
        private ElementOp() : base(OpType.Element) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly ElementOp Pattern = new ElementOp();

        /// <summary>
        /// 1 child - collection instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// extracts the key from a ref
    /// </summary>
    internal sealed class GetRefKeyOp : ScalarOp
    {
        #region constructors
        internal GetRefKeyOp(TypeUsage type) : base(OpType.GetRefKey, type) { }
        private GetRefKeyOp() : base(OpType.GetRefKey) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly GetRefKeyOp Pattern = new GetRefKeyOp();

        /// <summary>
        /// 1 child - ref instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Extracts the ref from an entity instance
    /// </summary>
    internal sealed class GetEntityRefOp : ScalarOp
    {
        #region constructors
        internal GetEntityRefOp(TypeUsage type) : base(OpType.GetEntityRef, type) { }
        private GetEntityRefOp() : base(OpType.GetEntityRef) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly GetEntityRefOp Pattern = new GetEntityRefOp();

        /// <summary>
        /// 1 child - entity instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Gets the target entity pointed at by a reference
    /// </summary>
    internal sealed class DerefOp : ScalarOp
    {
        #region constructors
        internal DerefOp(TypeUsage type) : base(OpType.Deref, type) { }
        private DerefOp() : base(OpType.Deref) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly DerefOp Pattern = new DerefOp();

        /// <summary>
        /// 1 child - entity instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }

    /// <summary>
    /// Navigate a relationship, and get the reference(s) of the target end
    /// </summary>
    internal sealed class NavigateOp : ScalarOp
    {
        #region private state
        private readonly RelProperty m_property;
        #endregion

        #region constructors
        internal NavigateOp(TypeUsage type, RelProperty relProperty)
            : base(OpType.Navigate, type) 
        {
            m_property = relProperty;
        }
        private NavigateOp() : base(OpType.Navigate) { }
        #endregion

        #region public methods
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly NavigateOp Pattern = new NavigateOp();

        /// <summary>
        /// 1 child - entity instance
        /// </summary>
        internal override int Arity { get { return 1; } }

        /// <summary>
        /// The rel property that describes this nvaigation
        /// </summary>
        internal RelProperty RelProperty { get { return m_property; } }

        /// <summary>
        /// The relationship we're traversing
        /// </summary>
        internal RelationshipType Relationship { get { return m_property.Relationship; } }
        /// <summary>
        /// The starting point of the traversal
        /// </summary>
        internal RelationshipEndMember FromEnd { get { return m_property.FromEnd; } }
        /// <summary>
        /// The end-point of the traversal
        /// </summary>
        internal RelationshipEndMember ToEnd { get { return m_property.ToEnd; } }

        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal override void Accept(BasicOpVisitor v, Node n) { v.Visit(this, n); }

        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
}
