/// <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> /// 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; }
/// <summary> /// Internal helper initializor. /// </summary> private void Init(IteratorDescriptor iterParent, GenerateHelper helper) { this.helper = helper; this.iterParent = iterParent; }
/// <summary> /// Create an IteratorDescriptor that is nested in a parent iterator. /// </summary> public IteratorDescriptor(IteratorDescriptor iterParent) { Init(iterParent, iterParent.helper); }
/// <summary> /// Internal helper initializor. /// </summary> private void Init(IteratorDescriptor iterParent, GenerateHelper helper) { _helper = helper; _iterParent = iterParent; }
/// <summary> /// Create an IteratorDescriptor that is nested in a parent iterator. /// </summary> public IteratorDescriptor(IteratorDescriptor iterParent) { Init(iterParent, iterParent._helper); }
/// <summary> /// Create IteratorDescriptor for each global value. This pre-visit is necessary because a global early /// in the list may reference a global later in the list and therefore expect its IteratorDescriptor to already /// be initialized. /// </summary> private void PrepareGlobalValues(QilList globalIterators) { MethodInfo methGlobal; IteratorDescriptor iterInfo; foreach (QilIterator iter in globalIterators) { Debug.Assert(iter.NodeType == QilNodeType.Let || iter.NodeType == QilNodeType.Parameter); // Get metadata for method which computes this global's value methGlobal = XmlILAnnotation.Write(iter).FunctionBinding; Debug.Assert(methGlobal != null, "Metadata for global value should have already been computed"); // Create an IteratorDescriptor for this global value iterInfo = new IteratorDescriptor(_helper); // Iterator items will be stored in a global location iterInfo.Storage = StorageDescriptor.Global(methGlobal, GetItemStorageType(iter), !iter.XmlType.IsSingleton); // Associate IteratorDescriptor with parameter XmlILAnnotation.Write(iter).CachedIteratorDescriptor = iterInfo; } }
/// <summary> /// End construction of the current iterator. /// </summary> private void EndNestedIterator(QilNode nd) { Debug.Assert(_iterCurr.Storage.Location == ItemLocation.None || _iterCurr.Storage.ItemStorageType == GetItemStorageType(nd) || _iterCurr.Storage.ItemStorageType == typeof(XPathItem) || nd.XmlType.TypeCode == XmlTypeCode.None, "QilNodeType " + nd.NodeType + " cannot be stored using type " + _iterCurr.Storage.ItemStorageType + "."); // If the nested iterator was constructed in branching mode, if (_iterCurr.IsBranching) { // Then if branching hasn't already taken place, do so now if (_iterCurr.Storage.Location != ItemLocation.None) { _iterCurr.EnsureItemStorageType(nd.XmlType, typeof(bool)); _iterCurr.EnsureStackNoCache(); if (_iterCurr.CurrentBranchingContext == BranchingContext.OnTrue) _helper.Emit(OpCodes.Brtrue, _iterCurr.LabelBranch); else _helper.Emit(OpCodes.Brfalse, _iterCurr.LabelBranch); _iterCurr.Storage = StorageDescriptor.None(); } } // Save current iterator as nested iterator _iterNested = _iterCurr; // Update current iterator to be parent iterator _iterCurr = _iterCurr.ParentIterator; }
/// <summary> /// Start construction of a new nested iterator. If this.iterCurr == null, then the new iterator /// is a top-level, or root iterator. Otherwise, the new iterator will be nested within the /// current iterator. /// </summary> private void StartNestedIterator(QilNode nd) { IteratorDescriptor iterParent = _iterCurr; // Create a new, nested iterator if (iterParent == null) { // Create a "root" iterator info that has no parernt _iterCurr = new IteratorDescriptor(_helper); } else { // Create a nested iterator _iterCurr = new IteratorDescriptor(iterParent); } _iterNested = null; }
/// <summary> /// Generate code for the specified function. /// </summary> private void Function(QilFunction ndFunc) { MethodInfo methFunc; int paramId; IteratorDescriptor iterInfo; bool useWriter; // Annotate each function parameter with a IteratorDescriptor foreach (QilIterator iter in ndFunc.Arguments) { Debug.Assert(iter.NodeType == QilNodeType.Parameter); // Create an IteratorDescriptor for this parameter iterInfo = new IteratorDescriptor(_helper); // Add one to parameter index, as 0th parameter is always "this" paramId = XmlILAnnotation.Write(iter).ArgumentPosition + 1; // The ParameterInfo for each argument should be set as its location iterInfo.Storage = StorageDescriptor.Parameter(paramId, GetItemStorageType(iter), !iter.XmlType.IsSingleton); // Associate IteratorDescriptor with Let iterator XmlILAnnotation.Write(iter).CachedIteratorDescriptor = iterInfo; } methFunc = XmlILAnnotation.Write(ndFunc).FunctionBinding; useWriter = (XmlILConstructInfo.Read(ndFunc).ConstructMethod == XmlILConstructMethod.Writer); // Generate query code from QilExpression tree _helper.MethodBegin(methFunc, ndFunc.SourceLine, useWriter); foreach (QilIterator iter in ndFunc.Arguments) { // DebugInfo: Sequence point just before generating code for the bound expression if (_qil.IsDebug && iter.SourceLine != null) _helper.DebugSequencePoint(iter.SourceLine); // Calculate default value of this parameter if (iter.Binding != null) { Debug.Assert(iter.XmlType == TypeFactory.ItemS, "IlGen currently only supports default values in parameters of type item*."); paramId = (iter.Annotation as XmlILAnnotation).ArgumentPosition + 1; // runtime.MatchesXmlType(param, XmlTypeCode.QName); Label lblLocalComputed = _helper.DefineLabel(); _helper.LoadQueryRuntime(); _helper.LoadParameter(paramId); _helper.LoadInteger((int)XmlTypeCode.QName); _helper.Call(XmlILMethods.SeqMatchesCode); _helper.Emit(OpCodes.Brfalse, lblLocalComputed); // Compute default value of this parameter StartNestedIterator(iter); NestedVisitEnsureStack(iter.Binding, GetItemStorageType(iter), /*isCached:*/!iter.XmlType.IsSingleton); EndNestedIterator(iter); _helper.SetParameter(paramId); _helper.MarkLabel(lblLocalComputed); } } StartNestedIterator(ndFunc); // If function did not push results to writer, then function will return value(s) (rather than void) if (useWriter) NestedVisit(ndFunc.Definition); else NestedVisitEnsureStack(ndFunc.Definition, GetItemStorageType(ndFunc), !ndFunc.XmlType.IsSingleton); EndNestedIterator(ndFunc); _helper.MethodEnd(); }