Describes the Clr type and location of items returned by an iterator. This struct is meant to be immutable.
Ejemplo n.º 1
0
        /// <summary>
        /// Ensure that the current item is pushed onto the stack.
        /// </summary>
        public void EnsureStack()
        {
            switch (_storage.Location)
            {
            case ItemLocation.Stack:
                // Already on the stack
                return;

            case ItemLocation.Parameter:
            case ItemLocation.Local:
            case ItemLocation.Current:
                PushValue();
                break;

            case ItemLocation.Global:
                // Call method that computes the value of this global value
                _helper.LoadQueryRuntime();
                _helper.Call(_storage.GlobalLocation);
                break;

            default:
                Debug.Assert(false, "Invalid location: " + _storage.Location);
                break;
            }

            _storage = _storage.ToStack();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Create a StorageDescriptor which is the same as this one, except for the item storage type.
        /// </summary>
        public StorageDescriptor ToStorageType(Type itemStorageType)
        {
            StorageDescriptor storage = this;

            storage._itemStorageType = itemStorageType;
            return(storage);
        }
 /// <summary>
 /// Create a StorageDescriptor for an item located on the stack.
 /// </summary>
 public static StorageDescriptor Stack(Type itemStorageType, bool isCached) {
     StorageDescriptor storage = new StorageDescriptor();
     storage.location = ItemLocation.Stack;
     storage.itemStorageType = itemStorageType;
     storage.isCached = isCached;
     return storage;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Discard the current item if it is pushed onto the stack.
 /// </summary>
 public void DiscardStack()
 {
     if (_storage.Location == ItemLocation.Stack)
     {
         _helper.Emit(OpCodes.Pop);
         _storage = StorageDescriptor.None();
     }
 }
 /// <summary>
 /// Create a StorageDescriptor for an item which is a parameter to the current method.
 /// </summary>
 public static StorageDescriptor Parameter(int paramIndex, Type itemStorageType, bool isCached) {
     StorageDescriptor storage = new StorageDescriptor();
     storage.location = ItemLocation.Parameter;
     storage.locationObject = paramIndex;
     storage.itemStorageType = itemStorageType;
     storage.isCached = isCached;
     return storage;
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Create a StorageDescriptor for an item located on the stack.
        /// </summary>
        public static StorageDescriptor Stack(Type itemStorageType, bool isCached)
        {
            StorageDescriptor storage = new StorageDescriptor();

            storage._location        = ItemLocation.Stack;
            storage._itemStorageType = itemStorageType;
            storage._isCached        = isCached;
            return(storage);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Create a StorageDescriptor for an item which is a parameter to the current method.
        /// </summary>
        public static StorageDescriptor Parameter(int paramIndex, Type itemStorageType, bool isCached)
        {
            StorageDescriptor storage = new StorageDescriptor();

            storage._location        = ItemLocation.Parameter;
            storage._locationObject  = paramIndex;
            storage._itemStorageType = itemStorageType;
            storage._isCached        = isCached;
            return(storage);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Set this iterator to be the same as the specified iterator.
        /// </summary>
        public void SetIterator(IteratorDescriptor iterInfo)
        {
            if (iterInfo.HasLabelNext)
            {
                _lblNext = iterInfo.GetLabelNext();
                _hasNext = true;
            }

            _storage = iterInfo.Storage;
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Ensure that current item is saved to the specified local variable.
 /// </summary>
 public void EnsureLocal(LocalBuilder bldr)
 {
     if (_storage.LocalLocation != bldr)
     {
         // Push value onto stack and then save to bldr
         EnsureStack();
         _helper.Emit(OpCodes.Stloc, bldr);
         _storage = _storage.ToLocal(bldr);
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Set this iterator to be the same as the specified iterator.
        /// </summary>
        public void SetIterator(IteratorDescriptor iterInfo)
        {
            if (iterInfo.HasLabelNext)
            {
                this.lblNext = iterInfo.GetLabelNext();
                this.hasNext = true;
            }

            this.storage = iterInfo.Storage;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Continue iteration until it is complete.  Branch to "lblOnEnd" when iteration is complete.
        /// </summary>
        /// <remarks>
        /// goto LabelNextCtxt;
        /// LabelOnEnd:
        /// </remarks>
        public void LoopToEnd(Label lblOnEnd)
        {
            if (_hasNext)
            {
                _helper.BranchAndMark(_lblNext, lblOnEnd);
                _hasNext = false;
            }

            // After looping is finished, storage is N/A
            _storage = StorageDescriptor.None();
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Create a StorageDescriptor for an item which is the Current item in an iterator.
        /// </summary>
        public static StorageDescriptor Current(LocalBuilder locIter, Type itemStorageType)
        {
            Debug.Assert(locIter.LocalType.GetMethod("get_Current").ReturnType == itemStorageType,
                         "Type " + itemStorageType + " does not match type of Current property.");

            StorageDescriptor storage = new StorageDescriptor();

            storage._location        = ItemLocation.Current;
            storage._locationObject  = locIter;
            storage._itemStorageType = itemStorageType;
            return(storage);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// If the iterator has been fully cached, then iterate the values one-by-one.
        /// </summary>
        public void EnsureNoCache()
        {
            if (_storage.IsCached)
            {
                if (!HasLabelNext)
                {
                    // If no Next label, this must be a singleton cache
                    EnsureStack();
                    _helper.LoadInteger(0);
                    _helper.CallCacheItem(_storage.ItemStorageType);

                    _storage = StorageDescriptor.Stack(_storage.ItemStorageType, false);
                }
                else
                {
                    // int idx;
                    LocalBuilder locIdx = _helper.DeclareLocal("$$$idx", typeof(int));
                    Label        lblNext;

                    // Make sure cache is not on the stack
                    EnsureNoStack("$$$cache");

                    // idx = -1;
                    _helper.LoadInteger(-1);
                    _helper.Emit(OpCodes.Stloc, locIdx);

                    // LabelNext:
                    lblNext = _helper.DefineLabel();
                    _helper.MarkLabel(lblNext);

                    // idx++;
                    _helper.Emit(OpCodes.Ldloc, locIdx);
                    _helper.LoadInteger(1);
                    _helper.Emit(OpCodes.Add);
                    _helper.Emit(OpCodes.Stloc, locIdx);

                    // if (idx >= cache.Count) goto LabelNextCtxt;
                    _helper.Emit(OpCodes.Ldloc, locIdx);
                    CacheCount();
                    _helper.Emit(OpCodes.Bge, GetLabelNext());

                    // item = cache[idx];
                    PushValue();
                    _helper.Emit(OpCodes.Ldloc, locIdx);
                    _helper.CallCacheItem(_storage.ItemStorageType);

                    SetIterator(lblNext, StorageDescriptor.Stack(_storage.ItemStorageType, false));
                }
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Create a StorageDescriptor for an item located in a local variable.
        /// </summary>
        public static StorageDescriptor Local(LocalBuilder loc, Type itemStorageType, bool isCached)
        {
            Debug.Assert(loc.LocalType == itemStorageType ||
                         typeof(IList <>).MakeGenericType(itemStorageType).IsAssignableFrom(loc.LocalType),
                         "Type " + itemStorageType + " does not match the local variable's type");

            StorageDescriptor storage = new StorageDescriptor();

            storage._location        = ItemLocation.Local;
            storage._locationObject  = loc;
            storage._itemStorageType = itemStorageType;
            storage._isCached        = isCached;
            return(storage);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Create a StorageDescriptor for an item located in a global variable.
        /// </summary>
        public static StorageDescriptor Global(MethodInfo methGlobal, Type itemStorageType, bool isCached)
        {
            Debug.Assert(methGlobal.ReturnType == itemStorageType ||
                         typeof(IList <>).MakeGenericType(itemStorageType).IsAssignableFrom(methGlobal.ReturnType),
                         "Type " + itemStorageType + " does not match the global method's return type");

            StorageDescriptor storage = new StorageDescriptor();

            storage._location        = ItemLocation.Global;
            storage._locationObject  = methGlobal;
            storage._itemStorageType = itemStorageType;
            storage._isCached        = isCached;
            return(storage);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Each XmlQueryType has multiple legal CLR representations.  Ensure that all items returned by this iterator are in
        /// the Clr representation specified by "storageTypeDest".
        /// </summary>
        public void EnsureItemStorageType(XmlQueryType xmlType, Type storageTypeDest)
        {
            // If source type = destination type, then done
            if (_storage.ItemStorageType == storageTypeDest)
            {
                goto SetStorageType;
            }

            Debug.Assert(_storage.ItemStorageType == typeof(XPathItem) || storageTypeDest == typeof(XPathItem),
                         "EnsureItemStorageType must convert to or from Item");

            // If items are cached,
            if (_storage.IsCached)
            {
                // Check for special case of IList<XPathNavigator> -> IList<XPathItem>
                if (_storage.ItemStorageType == typeof(XPathNavigator))
                {
                    EnsureStack();
                    _helper.Call(XmlILMethods.NavsToItems);
                    goto SetStorageType;
                }

                // Check for special case of IList<XPathItem> -> IList<XPathNavigator>
                if (storageTypeDest == typeof(XPathNavigator))
                {
                    EnsureStack();
                    _helper.Call(XmlILMethods.ItemsToNavs);
                    goto SetStorageType;
                }
            }

            // Iterate over each item, and convert each to the destination type
            EnsureStackNoCache();

            // If source type is Item,
            if (_storage.ItemStorageType == typeof(XPathItem))
            {
                // Then downcast to Navigator
                if (storageTypeDest == typeof(XPathNavigator))
                {
                    _helper.Emit(OpCodes.Castclass, typeof(XPathNavigator));
                }
                else
                {
                    // Call ValueAs methods for atomic types
                    _helper.CallValueAs(storageTypeDest);
                }
                goto SetStorageType;
            }
            else if (_storage.ItemStorageType == typeof(XPathNavigator))
            {
                // No-op if converting from XPathNavigator to XPathItem
                Debug.Assert(storageTypeDest == typeof(XPathItem), "Must be converting from XPathNavigator to XPathItem");
                goto SetStorageType;
            }

            // Destination type must be item, so generate code to create an XmlAtomicValue
            _helper.LoadInteger(_helper.StaticData.DeclareXmlType(xmlType));
            _helper.LoadQueryRuntime();
            _helper.Call(XmlILMethods.StorageMethods[_storage.ItemStorageType].ToAtomicValue);

SetStorageType:
            _storage = _storage.ToStorageType(storageTypeDest);
        }
 /// <summary>
 /// Discard the current item if it is pushed onto the stack.
 /// </summary>
 public void DiscardStack() {
     if (this.storage.Location == ItemLocation.Stack) {
         this.helper.Emit(OpCodes.Pop);
         this.storage = StorageDescriptor.None();
     }
 }
        /// <summary>
        /// Each XmlQueryType has multiple legal CLR representations.  Ensure that all items returned by this iterator are in
        /// the Clr representation specified by "storageTypeDest".
        /// </summary>
        public void EnsureItemStorageType(XmlQueryType xmlType, Type storageTypeDest) {
            // If source type = destination type, then done
            if (this.storage.ItemStorageType == storageTypeDest)
                goto SetStorageType;

            Debug.Assert(this.storage.ItemStorageType == typeof(XPathItem) || storageTypeDest == typeof(XPathItem),
                         "EnsureItemStorageType must convert to or from Item");

            // If items are cached,
            if (this.storage.IsCached) {
                // Check for special case of IList<XPathNavigator> -> IList<XPathItem>
                if (this.storage.ItemStorageType == typeof(XPathNavigator)) {
                    EnsureStack();
                    this.helper.Call(XmlILMethods.NavsToItems);
                    goto SetStorageType;
                }

                // Check for special case of IList<XPathItem> -> IList<XPathNavigator>
                if (storageTypeDest == typeof(XPathNavigator)) {
                    EnsureStack();
                    this.helper.Call(XmlILMethods.ItemsToNavs);
                    goto SetStorageType;
                }
            }

            // Iterate over each item, and convert each to the destination type
            EnsureStackNoCache();

            // If source type is Item,
            if (this.storage.ItemStorageType == typeof(XPathItem)) {
                // Then downcast to Navigator
                if (storageTypeDest == typeof(XPathNavigator)) {
                    this.helper.Emit(OpCodes.Castclass, typeof(XPathNavigator));
                }
                else {
                    // Call ValueAs methods for atomic types
                    this.helper.CallValueAs(storageTypeDest);
                }
                goto SetStorageType;
            }
            else if (this.storage.ItemStorageType == typeof(XPathNavigator)) {
                // No-op if converting from XPathNavigator to XPathItem
                Debug.Assert(storageTypeDest == typeof(XPathItem), "Must be converting from XPathNavigator to XPathItem");
                goto SetStorageType;
            }

            // Destination type must be item, so generate code to create an XmlAtomicValue
            this.helper.LoadInteger(this.helper.StaticData.DeclareXmlType(xmlType));
            this.helper.LoadQueryRuntime();
            this.helper.Call(XmlILMethods.StorageMethods[this.storage.ItemStorageType].ToAtomicValue);

        SetStorageType:
            this.storage = this.storage.ToStorageType(storageTypeDest);
        }
        /// <summary>
        /// Ensure that the current item is pushed onto the stack.
        /// </summary>
        public void EnsureStack() {
            switch (this.storage.Location) {
                case ItemLocation.Stack:
                    // Already on the stack
                    return;

                case ItemLocation.Parameter:
                case ItemLocation.Local:
                case ItemLocation.Current:
                    PushValue();
                    break;

                case ItemLocation.Global:
                    // Call method that computes the value of this global value
                    this.helper.LoadQueryRuntime();
                    this.helper.Call(this.storage.GlobalLocation);
                    break;

                default:
                    Debug.Assert(false, "Invalid location: " + this.storage.Location);
                    break;
            }

            this.storage = this.storage.ToStack();
        }
 /// <summary>
 /// Ensure that current item is saved to the specified local variable.
 /// </summary>
 public void EnsureLocal(LocalBuilder bldr) {
     if (this.storage.LocalLocation != bldr) {
         // Push value onto stack and then save to bldr
         EnsureStack();
         this.helper.Emit(OpCodes.Stloc, bldr);
         this.storage = this.storage.ToLocal(bldr);
     }
 }
        /// <summary>
        /// Continue iteration until it is complete.  Branch to "lblOnEnd" when iteration is complete.
        /// </summary>
        /// <remarks>
        /// goto LabelNextCtxt;
        /// LabelOnEnd:
        /// </remarks>
        public void LoopToEnd(Label lblOnEnd) {
            if (this.hasNext) {
                this.helper.BranchAndMark(this.lblNext, lblOnEnd);
                this.hasNext = false;
            }

            // After looping is finished, storage is N/A
            this.storage = StorageDescriptor.None();
        }
        /// <summary>
        /// If the iterator has been fully cached, then iterate the values one-by-one.
        /// </summary>
        public void EnsureNoCache() {
            if (this.storage.IsCached) {
                if (!HasLabelNext) {
                    // If no Next label, this must be a singleton cache
                    EnsureStack();
                    this.helper.LoadInteger(0);
                    this.helper.CallCacheItem(this.storage.ItemStorageType);

                    this.storage = StorageDescriptor.Stack(this.storage.ItemStorageType, false);
                }
                else {
                    // int idx;
                    LocalBuilder locIdx = this.helper.DeclareLocal("$$$idx", typeof(int));
                    Label lblNext;

                    // Make sure cache is not on the stack
                    EnsureNoStack("$$$cache");

                    // idx = -1;
                    this.helper.LoadInteger(-1);
                    this.helper.Emit(OpCodes.Stloc, locIdx);

                    // LabelNext:
                    lblNext = this.helper.DefineLabel();
                    this.helper.MarkLabel(lblNext);

                    // idx++;
                    this.helper.Emit(OpCodes.Ldloc, locIdx);
                    this.helper.LoadInteger(1);
                    this.helper.Emit(OpCodes.Add);
                    this.helper.Emit(OpCodes.Stloc, locIdx);

                    // if (idx >= cache.Count) goto LabelNextCtxt;
                    this.helper.Emit(OpCodes.Ldloc, locIdx);
                    CacheCount();
                    this.helper.Emit(OpCodes.Bge, GetLabelNext());

                    // item = cache[idx];
                    PushValue();
                    this.helper.Emit(OpCodes.Ldloc, locIdx);
                    this.helper.CallCacheItem(this.storage.ItemStorageType);

                    SetIterator(lblNext, StorageDescriptor.Stack(this.storage.ItemStorageType, false));
                }
            }
        }
 /// <summary>
 /// Set this iterator's next label and storage.  This iterator will range over a set of values located in
 /// "storage".  To get the next value, jump to "lblNext".
 /// </summary>
 public void SetIterator(Label lblNext, StorageDescriptor storage) {
     this.lblNext = lblNext;
     this.hasNext = true;
     this.storage = storage;
 }
        /// <summary>
        /// Set this iterator to be the same as the specified iterator.
        /// </summary>
        public void SetIterator(IteratorDescriptor iterInfo) {
            if (iterInfo.HasLabelNext) {
                this.lblNext = iterInfo.GetLabelNext();
                this.hasNext = true;
            }

            this.storage = iterInfo.Storage;
        }
        /// <summary>
        /// Create a StorageDescriptor for an item located in a global variable.
        /// </summary>
        public static StorageDescriptor Global(MethodInfo methGlobal, Type itemStorageType, bool isCached) {
            Debug.Assert(methGlobal.ReturnType == itemStorageType ||
                         typeof(IList<>).MakeGenericType(itemStorageType).IsAssignableFrom(methGlobal.ReturnType),
                         "Type " + itemStorageType + " does not match the global method's return type");

            StorageDescriptor storage = new StorageDescriptor();
            storage.location = ItemLocation.Global;
            storage.locationObject = methGlobal;
            storage.itemStorageType = itemStorageType;
            storage.isCached = isCached;
            return storage;
        }
        /// <summary>
        /// Create a StorageDescriptor for an item which is the Current item in an iterator.
        /// </summary>
        public static StorageDescriptor Current(LocalBuilder locIter, Type itemStorageType) {
            Debug.Assert(locIter.LocalType.GetMethod("get_Current").ReturnType == itemStorageType,
                         "Type " + itemStorageType + " does not match type of Current property.");

            StorageDescriptor storage = new StorageDescriptor();
            storage.location = ItemLocation.Current;
            storage.locationObject = locIter;
            storage.itemStorageType = itemStorageType;
            return storage;
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Set this iterator's next label and storage.  This iterator will range over a set of values located in
 /// "storage".  To get the next value, jump to "lblNext".
 /// </summary>
 public void SetIterator(Label lblNext, StorageDescriptor storage)
 {
     _lblNext = lblNext;
     _hasNext = true;
     _storage = storage;
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Set this iterator to be the same as the specified iterator.
        /// </summary>
        public void SetIterator(IteratorDescriptor iterInfo)
        {
            if (iterInfo.HasLabelNext)
            {
                _lblNext = iterInfo.GetLabelNext();
                _hasNext = true;
            }

            _storage = iterInfo.Storage;
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Set this iterator's next label and storage.  This iterator will range over a set of values located in
 /// "storage".  To get the next value, jump to "lblNext".
 /// </summary>
 public void SetIterator(Label lblNext, StorageDescriptor storage)
 {
     _lblNext = lblNext;
     _hasNext = true;
     _storage = storage;
 }
        /// <summary>
        /// Create a StorageDescriptor for an item located in a local variable.
        /// </summary>
        public static StorageDescriptor Local(LocalBuilder loc, Type itemStorageType, bool isCached) {
            Debug.Assert(loc.LocalType == itemStorageType ||
                         typeof(IList<>).MakeGenericType(itemStorageType).IsAssignableFrom(loc.LocalType),
                         "Type " + itemStorageType + " does not match the local variable's type");

            StorageDescriptor storage = new StorageDescriptor();
            storage.location = ItemLocation.Local;
            storage.locationObject = loc;
            storage.itemStorageType = itemStorageType;
            storage.isCached = isCached;
            return storage;
        }
Ejemplo n.º 31
0
 /// <summary>
 /// Set this iterator's next label and storage.  This iterator will range over a set of values located in
 /// "storage".  To get the next value, jump to "lblNext".
 /// </summary>
 public void SetIterator(Label lblNext, StorageDescriptor storage)
 {
     this.lblNext = lblNext;
     this.hasNext = true;
     this.storage = storage;
 }