private void VisitGlobalValues(QilList globalIterators) {
MethodInfo methGlobal;
Label lblGetGlobal, lblComputeGlobal;
bool isCached;
int idxValue;
foreach (QilIterator iter in globalIterators) {
QilParameter param = iter as QilParameter;
// Get MethodInfo for method that computes the value of this global
methGlobal = XmlILAnnotation.Write(iter).CachedIteratorDescriptor.Storage.GlobalLocation;
isCached = !iter.XmlType.IsSingleton;
// Notify the StaticDataManager of the new global value
idxValue = this.helper.StaticData.DeclareGlobalValue(iter.DebugName);
// Generate code for this method
this.helper.MethodBegin(methGlobal, iter.SourceLine, false);
lblGetGlobal = this.helper.DefineLabel();
lblComputeGlobal = this.helper.DefineLabel();
// if (runtime.IsGlobalComputed(idx)) goto LabelGetGlobal;
this.helper.LoadQueryRuntime();
this.helper.LoadInteger(idxValue);
this.helper.Call(XmlILMethods.GlobalComputed);
this.helper.Emit(OpCodes.Brtrue, lblGetGlobal);
// Compute value of global value
StartNestedIterator(iter);
if (param != null) {
Debug.Assert(iter.XmlType == TypeFactory.ItemS, "IlGen currently only supports parameters of type item*.");
// param = runtime.ExternalContext.GetParameter(localName, namespaceUri);
// if (param == null) goto LabelComputeGlobal;
LocalBuilder locParam = this.helper.DeclareLocal("$$$param", typeof(object));
this.helper.CallGetParameter(param.Name.LocalName, param.Name.NamespaceUri);
this.helper.Emit(OpCodes.Stloc, locParam);
this.helper.Emit(OpCodes.Ldloc, locParam);
this.helper.Emit(OpCodes.Brfalse, lblComputeGlobal);
// runtime.SetGlobalValue(idxValue, runtime.ChangeTypeXsltResult(idxType, value));
// Ensure that the storage type of the parameter corresponds to static type
this.helper.LoadQueryRuntime();
this.helper.LoadInteger(idxValue);
this.helper.LoadQueryRuntime();
this.helper.LoadInteger(this.helper.StaticData.DeclareXmlType(XmlQueryTypeFactory.ItemS));
this.helper.Emit(OpCodes.Ldloc, locParam);
this.helper.Call(XmlILMethods.ChangeTypeXsltResult);
this.helper.CallSetGlobalValue(typeof(object));
// goto LabelGetGlobal;
this.helper.EmitUnconditionalBranch(OpCodes.Br, lblGetGlobal);
}
// LabelComputeGlobal:
this.helper.MarkLabel(lblComputeGlobal);
if (iter.Binding != null) {
// runtime.SetGlobalValue(idxValue, (object) value);
this.helper.LoadQueryRuntime();
this.helper.LoadInteger(idxValue);
// Compute value of global value
NestedVisitEnsureStack(iter.Binding, GetItemStorageType(iter), isCached);
this.helper.CallSetGlobalValue(GetStorageType(iter));
}
else {
// Throw exception, as there is no default value for this parameter
// XmlQueryRuntime.ThrowException("...");
Debug.Assert(iter.NodeType == QilNodeType.Parameter, "Only parameters may not have a default value");
this.helper.LoadQueryRuntime();
this.helper.Emit(OpCodes.Ldstr, Res.GetString(Res.XmlIl_UnknownParam, new string[] {param.Name.LocalName, param.Name.NamespaceUri}));
this.helper.Call(XmlILMethods.ThrowException);
}
EndNestedIterator(iter);
// LabelGetGlobal:
// return (T) runtime.GetGlobalValue(idxValue);
this.helper.MarkLabel(lblGetGlobal);
this.helper.CallGetGlobalValue(idxValue, GetStorageType(iter));
this.helper.MethodEnd();
}
}