Remove confusing trailing dot
[mono.git] / mcs / class / System.XML / System.Xml.XPath / Expression.cs
1 //
2 // System.Xml.XPath.XPathExpression support classes
3 //
4 // Author:
5 //   Piers Haken (piersh@friskit.com)
6 //
7 // (C) 2002 Piers Haken
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System;
31 using System.IO;
32 using System.Collections;
33 using System.Xml;
34 using System.Xml.XPath;
35 using System.Xml.Xsl;
36 using System.Globalization;
37 using Mono.Xml.XPath;
38
39 using NSResolver = System.Xml.IXmlNamespaceResolver;
40
41 namespace System.Xml.XPath
42 {
43         internal static class ExpressionCache
44         {
45                 static readonly Hashtable table_per_ctx = new Hashtable ();
46                 static object dummy = new object ();
47                 static object cache_lock = new object ();
48
49                 public static XPathExpression Get (string xpath, IStaticXsltContext ctx)
50                 {
51                         object ctxkey = ctx != null ? ctx : dummy;
52
53                         lock (cache_lock) {
54                                 WeakReference wr = table_per_ctx [ctxkey] as WeakReference;
55                                 if (wr == null)
56                                         return null;
57                                 Hashtable table = wr.Target as Hashtable;
58                                 if (table == null) {
59                                         table_per_ctx [ctxkey] = null;
60                                         return null;
61                                 }
62
63                                 wr = table [xpath] as WeakReference;
64                                 if (wr != null) {
65                                         XPathExpression e = wr.Target as XPathExpression;
66                                         if (e != null)
67                                                 return e;
68                                         table [xpath] = null;
69                                 }
70                         }
71                         return null;
72                 }
73
74                 public static void Set (string xpath, IStaticXsltContext ctx, XPathExpression exp)
75                 {
76                         object ctxkey = ctx != null ? ctx : dummy;
77
78                         Hashtable table = null;
79                         lock (cache_lock) {
80                                 WeakReference wr = table_per_ctx [ctxkey] as WeakReference;
81                                 if (wr != null && wr.IsAlive)
82                                         table = (Hashtable) wr.Target;
83                                 if (table == null) {
84                                         table = new Hashtable ();
85                                         table_per_ctx [ctxkey] = new WeakReference (table);
86                                 }
87                                 table [xpath] = new WeakReference (exp);
88                         }
89                 }
90         }
91
92 #if XPATH_DEBUG
93         internal class CompiledExpression : Test.Xml.XPath.XPathExpression
94 #else
95         internal class CompiledExpression : XPathExpression
96 #endif
97         {
98                 protected NSResolver _nsm;
99                 protected Expression _expr;
100                 XPathSorters _sorters;
101                 string rawExpression;
102
103                 public CompiledExpression (string raw, Expression expr)
104                 {
105                         _expr = expr.Optimize ();
106                         rawExpression = raw;
107                 }
108                 private CompiledExpression (CompiledExpression other)
109                 {
110                         _nsm = other._nsm;
111                         _expr = other._expr;
112                         rawExpression = other.rawExpression;
113                 }
114 #if XPATH_DEBUG
115                 public override Test.Xml.XPath.XPathExpression Clone () { return new CompiledExpression (this); }
116 #else
117                 public override XPathExpression Clone () { return new CompiledExpression (this); }
118 #endif
119                 
120                 public Expression ExpressionNode { get { return _expr; }}
121
122                 public override void SetContext (XmlNamespaceManager nsManager)
123                 {
124                         _nsm = nsManager;
125                 }
126
127                 public override void SetContext (IXmlNamespaceResolver nsResolver)
128                 {
129                         _nsm = nsResolver;
130                 }
131
132                 internal NSResolver NamespaceManager { get { return _nsm; } }
133                 public override String Expression { get { return rawExpression; }}
134                 public override XPathResultType ReturnType { get { return _expr.ReturnType; }}
135
136                 public object Evaluate (BaseIterator iter)
137                 {
138                         if (_sorters != null)
139                                 return EvaluateNodeSet (iter);
140
141 #if false
142                         return _expr.Evaluate (iter);
143 #else
144                         try {
145                                 return _expr.Evaluate (iter);
146                         }
147                         catch (XPathException) {
148                                 throw;
149                         }
150                         catch (XsltException) {
151                                 throw;
152                         }
153                         catch (Exception e) {
154                                 throw new XPathException ("Error during evaluation", e);
155                         }
156 #endif
157                 }
158                 public XPathNodeIterator EvaluateNodeSet (BaseIterator iter)
159                 {
160 #if false
161                         try
162                         {
163 #endif
164                                 BaseIterator iterResults = _expr.EvaluateNodeSet (iter);
165                                 if (_sorters != null)
166                                         return _sorters.Sort (iterResults);
167                                 return iterResults;
168 #if false
169                         }
170                         catch (XPathException)
171                         {
172                                 throw;
173                         }
174                         catch (Exception e)
175                         {
176                                 throw new XPathException ("Error during evaluation", e);
177                         }
178 #endif
179                 }
180                 public double EvaluateNumber (BaseIterator iter)
181                 {
182 #if true
183                         return _expr.EvaluateNumber (iter);
184 #else
185                         try
186                         {
187                                 return _expr.EvaluateNumber (iter);
188                         }
189                         catch (XPathException)
190                         {
191                                 throw;
192                         }
193                         catch (Exception e)
194                         {
195                                 throw new XPathException ("Error during evaluation", e);
196                         }
197 #endif
198                 }
199                 public string EvaluateString (BaseIterator iter)
200                 {
201 #if true
202                         return _expr.EvaluateString (iter);
203 #else
204                         try
205                         {
206                                 return _expr.EvaluateString (iter);
207                         }
208                         catch (XPathException)
209                         {
210                                 throw;
211                         }
212                         catch (Exception e)
213                         {
214                                 throw new XPathException ("Error during evaluation", e);
215                         }
216 #endif
217                 }
218                 public bool EvaluateBoolean (BaseIterator iter)
219                 {
220 #if true
221                         return _expr.EvaluateBoolean (iter);
222 #else
223                         try
224                         {
225                                 return _expr.EvaluateBoolean (iter);
226                         }
227                         catch (XPathException)
228                         {
229                                 throw;
230                         }
231                         catch (Exception e)
232                         {
233                                 throw new XPathException ("Error during evaluation", e);
234                         }
235 #endif
236                 }
237
238                 public override void AddSort (Object obj, IComparer cmp)
239                 {
240                         if (_sorters == null)
241                                 _sorters = new XPathSorters ();
242                         _sorters.Add (obj, cmp);
243                 }
244                 public override void AddSort(object expr, XmlSortOrder orderSort, XmlCaseOrder orderCase, string lang, XmlDataType dataType)
245                 {
246                         if (_sorters == null)
247                                 _sorters = new XPathSorters ();
248                         _sorters.Add (expr, orderSort, orderCase, lang, dataType);
249                 }
250
251         }
252
253         class XPathSortElement
254         {
255                 public XPathNavigator Navigator;
256                 public object [] Values;
257         }
258
259         class XPathSorters : IComparer
260         {
261                 readonly ArrayList _rgSorters = new ArrayList ();
262
263                 public void Add (object expr, IComparer cmp)
264                 {
265                         _rgSorters.Add (new XPathSorter (expr, cmp));
266                 }
267
268                 public void Add (object expr, XmlSortOrder orderSort, XmlCaseOrder orderCase, string lang, XmlDataType dataType)
269                 {
270                         _rgSorters.Add (new XPathSorter (expr, orderSort, orderCase, lang, dataType));
271                 }
272
273                 public void CopyFrom (XPathSorter [] sorters)
274                 {
275                         _rgSorters.Clear ();
276                         _rgSorters.AddRange (sorters);
277                 }
278
279                 public BaseIterator Sort (BaseIterator iter)
280                 {
281                         ArrayList rgElts = ToSortElementList (iter);
282                         return Sort (rgElts, iter.NamespaceManager);
283                 }
284
285                 ArrayList ToSortElementList (BaseIterator iter)
286                 {
287                         ArrayList rgElts = new ArrayList ();
288                         int cSorters = _rgSorters.Count;
289                         while (iter.MoveNext ())
290                         {
291                                 XPathSortElement elt = new XPathSortElement ();
292                                 elt.Navigator = iter.Current.Clone ();
293                                 elt.Values = new object [cSorters];
294                                 for (int iSorter = 0; iSorter < _rgSorters.Count; ++iSorter)
295                                 {
296                                         XPathSorter sorter = (XPathSorter) _rgSorters [iSorter];
297                                         elt.Values [iSorter] = sorter.Evaluate (iter);
298                                 }
299                                 rgElts.Add (elt);
300                         }
301                         return rgElts;
302                 }
303
304                 public BaseIterator Sort (ArrayList rgElts, NSResolver nsm)
305                 {
306                         rgElts.Sort (this);
307                         XPathNavigator [] rgResults = new XPathNavigator [rgElts.Count];
308                         for (int iResult = 0; iResult < rgElts.Count; ++iResult)
309                         {
310                                 XPathSortElement elt = (XPathSortElement) rgElts [iResult];
311                                 rgResults [iResult] = elt.Navigator;
312                         }
313                         return new ListIterator (rgResults, nsm);
314                 }
315
316                 int IComparer.Compare (object o1, object o2)
317                 {
318                         XPathSortElement elt1 = (XPathSortElement) o1;
319                         XPathSortElement elt2 = (XPathSortElement) o2;
320                         for (int iSorter = 0; iSorter < _rgSorters.Count; ++iSorter)
321                         {
322                                 XPathSorter sorter = (XPathSorter) _rgSorters [iSorter];
323                                 int cmp = sorter.Compare (elt1.Values [iSorter], elt2.Values [iSorter]);
324                                 if (cmp != 0)
325                                         return cmp;
326                         }
327                         switch (elt1.Navigator.ComparePosition (elt2.Navigator)) {
328                         case XmlNodeOrder.Same:
329                                 return 0;
330                         case XmlNodeOrder.After:
331                                 return 1;
332                         default:
333                                 return -1;
334                         }
335                 }
336         }
337
338         class XPathSorter
339         {
340                 readonly Expression _expr;
341                 readonly IComparer _cmp;
342                 readonly XmlDataType _type;
343
344                 public XPathSorter (object expr, IComparer cmp)
345                 {
346                         _expr = ExpressionFromObject (expr);
347                         _cmp = cmp;
348                         _type = XmlDataType.Text;
349                 }
350
351                 public XPathSorter (object expr, XmlSortOrder orderSort, XmlCaseOrder orderCase, string lang, XmlDataType dataType)
352                 {
353                         _expr = ExpressionFromObject (expr);
354                         _type = dataType;
355                         if (dataType == XmlDataType.Number)
356                                 _cmp = new XPathNumberComparer (orderSort);
357                         else
358                                 _cmp = new XPathTextComparer (orderSort, orderCase, lang);
359                 }
360
361                 static Expression ExpressionFromObject (object expr)
362                 {
363                         if (expr is CompiledExpression)
364                                 return ((CompiledExpression) expr).ExpressionNode;
365                         if (expr is string)
366                                 return new XPathParser ().Compile ((string)expr);
367                         
368                         throw new XPathException ("Invalid query object");
369                 }
370
371                 public object Evaluate (BaseIterator iter)
372                 {
373                         if (_type == XmlDataType.Number)
374                                 return _expr.EvaluateNumber (iter);
375                         return _expr.EvaluateString (iter);
376                 }
377
378                 public int Compare (object o1, object o2)
379                 {
380                         return _cmp.Compare (o1, o2);
381                 }
382
383                 class XPathNumberComparer : IComparer
384                 {
385                         int _nMulSort;
386
387                         public XPathNumberComparer (XmlSortOrder orderSort)
388                         {
389                                 _nMulSort = (orderSort == XmlSortOrder.Ascending) ? 1 : -1;
390                         }
391
392                         int IComparer.Compare (object o1, object o2)
393                         {
394                                 double num1 = (double) o1;
395                                 double num2 = (double) o2;
396                                 if (num1 < num2)
397                                         return -_nMulSort;
398                                 if (num1 > num2)
399                                         return _nMulSort;
400                                 if (num1 == num2)
401                                         return 0;
402                                 if (double.IsNaN (num1))
403                                         return (double.IsNaN (num2)) ? 0 : -_nMulSort;
404                                 return _nMulSort;
405                         }
406                 }
407
408                 class XPathTextComparer : IComparer
409                 {
410                         int _nMulSort;
411                         int _nMulCase;
412                         XmlCaseOrder _orderCase;
413                         CultureInfo _ci;
414
415                         public XPathTextComparer (XmlSortOrder orderSort, XmlCaseOrder orderCase, string strLang)
416                         {
417                                 _orderCase = orderCase;
418                                 // FIXME: We have to set this in
419                                 // reverse order since currently
420                                 // we don't support collation.
421                                 _nMulCase = (orderCase == XmlCaseOrder.UpperFirst) ? -1 : 1;
422                                 _nMulSort = (orderSort == XmlSortOrder.Ascending) ? 1 : -1;
423
424                                 if (strLang == null || strLang == "")
425                                         _ci = CultureInfo.CurrentCulture;       // TODO: defer until evaluation?
426                                 else
427                                         _ci = new CultureInfo (strLang);
428                         }
429
430                         int IComparer.Compare (object o1, object o2)
431                         {
432                                 string str1 = (string) o1;
433                                 string str2 = (string) o2;
434                                 int cmp = String.Compare (str1, str2, true, _ci);
435                                 if (cmp != 0 || _orderCase == XmlCaseOrder.None)
436                                         return cmp * _nMulSort;
437                                 return _nMulSort * _nMulCase * String.Compare (str1, str2, false, _ci);
438                         }
439                 }
440         }
441
442         /// <summary>
443         /// Summary description for Expression.
444         /// </summary>
445         internal abstract class Expression
446         {
447                 public Expression ()
448                 {
449                 }
450                 public abstract XPathResultType ReturnType { get; }
451                 public virtual XPathResultType GetReturnType (BaseIterator iter) { return ReturnType; }
452
453                 public virtual Expression Optimize ()
454                 {
455                         return this;
456                 }
457
458                 public virtual bool HasStaticValue {
459                         get { return false; }
460                 }
461
462                 public virtual object StaticValue {
463                         get {
464                                 switch (ReturnType) {
465                                 case XPathResultType.String:
466                                         return StaticValueAsString;
467                                 case XPathResultType.Number:
468                                         return StaticValueAsNumber;
469                                 case XPathResultType.Boolean:
470                                         return StaticValueAsBoolean;
471                                 }
472                                 return null;
473                         }
474                 }
475
476                 public virtual string StaticValueAsString {
477                         get { return HasStaticValue ? XPathFunctions.ToString (StaticValue) : null; }
478                 }
479
480                 public virtual double StaticValueAsNumber {
481                         get { return HasStaticValue ? XPathFunctions.ToNumber (StaticValue) : 0; }
482                 }
483
484                 public virtual bool StaticValueAsBoolean {
485                         get { return HasStaticValue ? XPathFunctions.ToBoolean (StaticValue) : false; }
486                 }
487
488                 public virtual XPathNavigator StaticValueAsNavigator {
489                         get { return StaticValue as XPathNavigator; }
490                 }
491
492                 public abstract object Evaluate (BaseIterator iter);
493
494                 public virtual BaseIterator EvaluateNodeSet (BaseIterator iter)
495                 {
496                         XPathResultType type = GetReturnType (iter);
497                         switch (type) {
498                         case XPathResultType.NodeSet:
499                         case XPathResultType.Any:
500                         case XPathResultType.Navigator: // FIXME: It may pass not-allowed use of RTF
501                                 object o = Evaluate (iter);
502                                 XPathNodeIterator xi = o as XPathNodeIterator;
503                                 BaseIterator iterResult = null;
504                                 if (xi != null) {
505                                         iterResult = xi as BaseIterator;
506                                         if (iterResult == null)
507                                                 iterResult = new WrapperIterator (xi, iter.NamespaceManager);
508                                         return iterResult;
509                                 }
510                                 XPathNavigator nav = o as XPathNavigator;
511                                 if (nav != null) {
512                                         XPathNodeIterator xiter = nav.SelectChildren (XPathNodeType.All);
513                                         iterResult = xiter as BaseIterator;
514                                         if (iterResult == null && xiter != null)
515                                                 iterResult = new WrapperIterator (xiter, iter.NamespaceManager);
516                                 }
517                                 if (iterResult != null)
518                                         return iterResult;
519                                 if (o == null)
520                                         return new NullIterator (iter);
521                                 type = GetReturnType (o);
522                                 break;
523                         }
524                         throw new XPathException (String.Format ("expected nodeset but was {1}: {0}", ToString (), type));
525                 }
526
527                 protected static XPathResultType GetReturnType (object obj)
528                 {
529                         if (obj is string)
530                                 return XPathResultType.String;
531                         if (obj is bool)
532                                 return XPathResultType.Boolean;
533                         if (obj is XPathNodeIterator)
534                                 return XPathResultType.NodeSet;
535                         if (obj is double || obj is int)
536                                 return XPathResultType.Number;
537                         if (obj is XPathNavigator)
538                                 return XPathResultType.Navigator;
539                         throw new XPathException ("invalid node type: "+obj.GetType ().ToString ());
540                 }
541
542                 internal virtual XPathNodeType EvaluatedNodeType {
543                         get { return XPathNodeType.All; }
544                 }
545
546                 internal virtual bool IsPositional {
547                         get { return false; }
548                 }
549
550                 // For "peer and subtree" optimization. see:
551                 // http://idealliance.org/papers/dx_xmle04/papers/02-03-02/02-03-02.html
552                 internal virtual bool Peer {
553                         get { return false; }
554                 }
555
556                 public virtual double EvaluateNumber (BaseIterator iter)
557                 {
558                         object result;
559                         XPathResultType type = GetReturnType (iter);
560                         if (type == XPathResultType.NodeSet)
561                         {
562                                 result = EvaluateString (iter);
563                                 type = XPathResultType.String;
564                         }
565                         else
566                                 result = Evaluate (iter);
567
568                         if (type == XPathResultType.Any)
569                                 type = GetReturnType (result);
570
571                         switch (type) {
572                         case XPathResultType.Number:
573                                 if (result is double)
574                                         return (double)result;
575                                 else if (result is IConvertible)
576                                         return ((IConvertible) result).ToDouble (CultureInfo.InvariantCulture);
577                                 else
578                                         return (double) result; // most likely invalid cast
579                         case XPathResultType.Boolean:
580                                 return ((bool) result) ? 1.0 : 0.0;
581                         case XPathResultType.NodeSet:
582                                 return XPathFunctions.ToNumber (EvaluateString (iter));
583                         case XPathResultType.String:
584                                 return XPathFunctions.ToNumber ((string) result);
585                         case XPathResultType.Navigator:
586                                 return XPathFunctions.ToNumber (((XPathNavigator) (result)).Value);
587                         default:
588                                 throw new XPathException ("invalid node type");
589                         }
590                 }
591
592                 public virtual string EvaluateString (BaseIterator iter)
593                 {
594                         object result = Evaluate (iter);
595                         XPathResultType type = GetReturnType (iter);
596                         if (type == XPathResultType.Any)
597                                 type = GetReturnType (result);
598                         switch (type) {
599                         case XPathResultType.Number:
600                                 double d = (double) result;
601                                 return XPathFunctions.ToString (d);
602                         case XPathResultType.Boolean:
603                                 return ((bool) result) ? "true" : "false";
604                         case XPathResultType.String:
605                                 return (string) result;
606                         case XPathResultType.NodeSet:
607                         {
608                                 BaseIterator iterResult = (BaseIterator) result;
609                                 if (iterResult == null || !iterResult.MoveNext ())
610                                         return "";
611                                 return iterResult.Current.Value;
612                         }
613                         case XPathResultType.Navigator:
614                                 return ((XPathNavigator) result).Value;
615                         default:
616                                 throw new XPathException ("invalid node type");
617                         }
618                 }
619
620                 public virtual bool EvaluateBoolean (BaseIterator iter)
621                 {
622                         object result = Evaluate (iter);
623                         XPathResultType type = GetReturnType (iter);
624                         if (type == XPathResultType.Any)
625                                 type = GetReturnType (result);
626                         switch (type) {
627                         case XPathResultType.Number:
628                                 double num = Convert.ToDouble (result);
629                                 return (num != 0.0 && num != -0.0 && !Double.IsNaN (num));
630                         case XPathResultType.Boolean:
631                                 return (bool) result;
632                         case XPathResultType.String:
633                                 return ((string) result).Length != 0;
634                         case XPathResultType.NodeSet:
635                                 BaseIterator iterResult = (BaseIterator) result;
636                                 return (iterResult != null && iterResult.MoveNext ());
637                         case XPathResultType.Navigator:
638                                 return (((XPathNavigator) result).HasChildren);
639                         default:
640                                 throw new XPathException ("invalid node type");
641                         }
642                 }
643
644                 public object EvaluateAs (BaseIterator iter, XPathResultType type)
645                 {
646                         switch (type) {
647                         case XPathResultType.Boolean:
648                                 return EvaluateBoolean (iter);
649                         case XPathResultType.NodeSet:
650                                 return EvaluateNodeSet (iter);
651                         case XPathResultType.String:
652                                 return EvaluateString (iter);
653                         case XPathResultType.Number:
654                                 return EvaluateNumber (iter);
655                         }
656                         return Evaluate (iter);
657                 }
658
659                 public virtual bool RequireSorting { get { return false; } }
660         }
661
662         internal abstract class ExprBinary : Expression
663         {
664                 protected Expression _left, _right;
665
666                 public ExprBinary (Expression left, Expression right)
667                 {
668                         _left = left;
669                         _right = right;
670                 }
671
672                 public override Expression Optimize ()
673                 {
674                         _left = _left.Optimize ();
675                         _right = _right.Optimize ();
676                         return this;
677                 }
678
679                 public override bool HasStaticValue {
680                         get { return _left.HasStaticValue && _right.HasStaticValue; }
681                 }
682
683                 public override String ToString ()
684                 {
685                         return _left.ToString () + ' ' + Operator + ' ' + _right.ToString ();
686                 }
687                 protected abstract String Operator { get; }
688
689                 internal override XPathNodeType EvaluatedNodeType {
690                         get {
691                                 if (_left.EvaluatedNodeType == _right.EvaluatedNodeType)
692                                         return _left.EvaluatedNodeType;
693                                 else
694                                         return XPathNodeType.All;
695                         }
696                 }
697
698                 internal override bool IsPositional {
699                         get { return _left.IsPositional || _right.IsPositional; }
700                 }
701
702                 internal override bool Peer {
703                         get { return _left.Peer && _right.Peer; }
704                 }
705         }
706
707         internal abstract class ExprBoolean : ExprBinary
708         {
709                 public ExprBoolean (Expression left, Expression right) : base (left, right) {}
710
711                 public override Expression Optimize ()
712                 {
713                         base.Optimize ();
714                         if (!HasStaticValue)
715                                 return this;
716                         else if (StaticValueAsBoolean)
717                                 return new XPathFunctionTrue (null);
718                         else
719                                 return new XPathFunctionFalse (null);
720                 }
721
722                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
723                 public override object Evaluate (BaseIterator iter)
724                 {
725                         return EvaluateBoolean (iter);
726                 }
727                 public override double EvaluateNumber (BaseIterator iter)
728                 {
729                         return EvaluateBoolean (iter) ? 1 : 0;
730                 }
731                 
732                 public override string EvaluateString (BaseIterator iter)
733                 {
734                         return EvaluateBoolean (iter) ? "true" : "false";
735                 }
736         }
737
738         internal class ExprOR : ExprBoolean
739         {
740                 public ExprOR (Expression left, Expression right) : base (left, right) {}
741                 protected override String Operator { get { return "or"; }}
742
743                 public override bool StaticValueAsBoolean {
744                         get { return HasStaticValue ? _left.StaticValueAsBoolean || _right.StaticValueAsBoolean : false; }
745                 }
746
747                 public override bool EvaluateBoolean (BaseIterator iter)
748                 {
749                         if (_left.EvaluateBoolean (iter))
750                                 return true;
751                         return _right.EvaluateBoolean (iter);
752                 }
753         }
754
755         internal class ExprAND : ExprBoolean
756         {
757                 public ExprAND (Expression left, Expression right) : base (left, right) {}
758                 protected override String Operator { get { return "and"; }}
759
760                 public override bool StaticValueAsBoolean {
761                         get { return HasStaticValue ? _left.StaticValueAsBoolean && _right.StaticValueAsBoolean : false; }
762                 }
763
764                 public override bool EvaluateBoolean (BaseIterator iter)
765                 {
766                         if (!_left.EvaluateBoolean (iter))
767                                 return false;
768                         return _right.EvaluateBoolean (iter);
769                 }
770         }
771
772         internal abstract class EqualityExpr : ExprBoolean
773         {
774                 bool trueVal;
775                 public EqualityExpr (Expression left, Expression right, bool trueVal) : base (left, right)
776                 {
777                         this.trueVal = trueVal;
778                 }
779
780                 public override bool StaticValueAsBoolean {
781                         get {
782                                 if (!HasStaticValue)
783                                         return false;
784                                 if ((_left.ReturnType == XPathResultType.Navigator || _right.ReturnType == XPathResultType.Navigator) && _left.ReturnType == _right.ReturnType)
785                                         return (_left.StaticValueAsNavigator.IsSamePosition (
786                                         _right.StaticValueAsNavigator))
787                                          == trueVal;
788                                 if (_left.ReturnType == XPathResultType.Boolean | _right.ReturnType == XPathResultType.Boolean)
789                                         return (_left.StaticValueAsBoolean == _right.StaticValueAsBoolean) == trueVal;
790                                 if (_left.ReturnType == XPathResultType.Number | _right.ReturnType == XPathResultType.Number)
791                                         return (_left.StaticValueAsNumber == _right.StaticValueAsNumber) == trueVal;
792                                 if (_left.ReturnType == XPathResultType.String | _right.ReturnType == XPathResultType.String)
793                                         return (_left.StaticValueAsString == _right.StaticValueAsString) == trueVal;
794                                 return _left.StaticValue == _right.StaticValue == trueVal;
795                         }
796                 }
797
798                 // FIXME: Avoid extraneous evaluation
799                 public override bool EvaluateBoolean (BaseIterator iter)
800                 {
801                         XPathResultType typeL = _left.GetReturnType (iter);
802                         XPathResultType typeR = _right.GetReturnType (iter);
803
804                         // TODO: avoid double evaluations
805                         if (typeL == XPathResultType.Any)
806                                 typeL = GetReturnType (_left.Evaluate (iter));
807                         if (typeR == XPathResultType.Any)
808                                 typeR = GetReturnType (_right.Evaluate (iter));
809
810                         // Regard RTF as string
811                         if (typeL == XPathResultType.Navigator)
812                                 typeL = XPathResultType.String;
813                         if (typeR == XPathResultType.Navigator)
814                                 typeR = XPathResultType.String;
815
816                         if (typeL == XPathResultType.NodeSet || typeR == XPathResultType.NodeSet)
817                         {
818                                 Expression left, right;
819                                 if (typeL != XPathResultType.NodeSet)
820                                 {
821                                         left = _right;
822                                         right = _left;
823                                         XPathResultType typeTmp = typeL;
824                                         typeL = typeR;
825                                         typeR = typeTmp;
826                                 }
827                                 else
828                                 {
829                                         left = _left;
830                                         right = _right;
831                                 }
832                                 if (typeR == XPathResultType.Boolean)
833                                 {
834                                         return left.EvaluateBoolean (iter) == right.EvaluateBoolean (iter) == trueVal;
835                                 }
836                                 else
837                                 {
838                                         BaseIterator iterL = left.EvaluateNodeSet (iter);
839                                         if (typeR == XPathResultType.Number)
840                                         {
841                                                 double dR = right.EvaluateNumber (iter);
842                                                 while (iterL.MoveNext ())
843                                                         if (XPathFunctions.ToNumber (iterL.Current.Value) == dR == trueVal)
844                                                                 return true;
845                                         }
846                                         else if (typeR == XPathResultType.String)
847                                         {
848                                                 string strR = right.EvaluateString (iter);
849                                                 while (iterL.MoveNext ())
850                                                         if (iterL.Current.Value == strR == trueVal)
851                                                                 return true;
852                                         }
853                                         else if (typeR == XPathResultType.NodeSet)
854                                         {
855                                                 BaseIterator iterR = right.EvaluateNodeSet (iter);
856                                                 ArrayList rgNodesL = new ArrayList ();
857                                                 while (iterL.MoveNext ())
858                                                         rgNodesL.Add (XPathFunctions.ToString (iterL.Current.Value));
859                                                 while (iterR.MoveNext ())
860                                                 {
861                                                         string strR = XPathFunctions.ToString (iterR.Current.Value);
862                                                         for (int l = 0; l < rgNodesL.Count; l++)
863                                                                 if ((strR == (string) rgNodesL [l]) == trueVal)
864                                                                         return true;
865                                                 }
866                                         }
867                                         return false;
868                                 }
869                         }
870                         else if (typeL == XPathResultType.Boolean || typeR == XPathResultType.Boolean)
871                                 return _left.EvaluateBoolean (iter) == _right.EvaluateBoolean (iter) == trueVal;
872                         else if (typeL == XPathResultType.Number || typeR == XPathResultType.Number)
873                                 return _left.EvaluateNumber (iter) == _right.EvaluateNumber (iter) == trueVal;
874                         else
875                                 return _left.EvaluateString (iter) == _right.EvaluateString (iter) == trueVal;
876                 }
877         }
878         
879         internal class ExprEQ : EqualityExpr
880         {
881                 public ExprEQ (Expression left, Expression right) : base (left, right, true) {}
882                 protected override String Operator { get { return "="; }}
883         }
884
885         internal class ExprNE : EqualityExpr
886         {
887                 public ExprNE (Expression left, Expression right) : base (left, right, false) {}
888                 protected override String Operator { get { return "!="; }}
889         }
890
891         internal abstract class RelationalExpr : ExprBoolean
892         {
893                 public RelationalExpr (Expression left, Expression right) : base (left, right) {}
894
895                 public override bool StaticValueAsBoolean {
896                         get { return HasStaticValue ? Compare (_left.StaticValueAsNumber, _right.StaticValueAsNumber) : false; }
897                 }
898
899                 // FIXME: Avoid extraneous evaluation.
900                 public override bool EvaluateBoolean (BaseIterator iter)
901                 {
902                         XPathResultType typeL = _left.GetReturnType (iter);
903                         XPathResultType typeR = _right.GetReturnType (iter);
904
905                         if (typeL == XPathResultType.Any)
906                                 typeL = GetReturnType (_left.Evaluate (iter));
907                         if (typeR == XPathResultType.Any)
908                                 typeR = GetReturnType (_right.Evaluate (iter));
909
910                         // Regard RTF as string
911                         if (typeL == XPathResultType.Navigator)
912                                 typeL = XPathResultType.String;
913                         if (typeR == XPathResultType.Navigator)
914                                 typeR = XPathResultType.String;
915
916                         if (typeL == XPathResultType.NodeSet || typeR == XPathResultType.NodeSet)
917                         {
918                                 bool fReverse = false;
919                                 Expression left, right;
920                                 if (typeL != XPathResultType.NodeSet)
921                                 {
922                                         fReverse = true;
923                                         left = _right;
924                                         right = _left;
925                                         XPathResultType typeTmp = typeL;
926                                         typeL = typeR;
927                                         typeR = typeTmp;
928                                 }
929                                 else
930                                 {
931                                         left = _left;
932                                         right = _right;
933                                 }
934                                 if (typeR == XPathResultType.Boolean)
935                                 {
936                                         bool fL = left.EvaluateBoolean (iter);
937                                         bool fR = right.EvaluateBoolean (iter);
938                                         return Compare (Convert.ToDouble (fL), Convert.ToDouble (fR), fReverse);
939                                 }
940                                 else
941                                 {
942                                         BaseIterator iterL = left.EvaluateNodeSet (iter);
943                                         if (typeR == XPathResultType.Number || typeR == XPathResultType.String)
944                                         {
945                                                 double dR = right.EvaluateNumber (iter);
946                                                 while (iterL.MoveNext ())
947                                                         if (Compare (XPathFunctions.ToNumber (iterL.Current.Value), dR, fReverse))
948                                                                 return true;
949                                         }
950                                         else if (typeR == XPathResultType.NodeSet)
951                                         {
952                                                 BaseIterator iterR = right.EvaluateNodeSet (iter);
953                                                 ArrayList rgNodesL = new ArrayList ();
954                                                 while (iterL.MoveNext ())
955                                                         rgNodesL.Add (XPathFunctions.ToNumber (iterL.Current.Value));
956                                                 while (iterR.MoveNext ())
957                                                 {
958                                                         double numR = XPathFunctions.ToNumber (iterR.Current.Value);
959                                                         for (int l = 0; l < rgNodesL.Count; l++)
960                                                                 if (Compare ((double) rgNodesL [l], numR))
961                                                                         return true;
962                                                 }
963                                         }
964                                         return false;
965                                 }
966                         }
967                         else
968                                 return Compare (_left.EvaluateNumber (iter), _right.EvaluateNumber (iter));
969                 }
970                 public abstract bool Compare (double arg1, double arg2);
971                 public bool Compare (double arg1, double arg2, bool fReverse)
972                 {
973                         if (fReverse)
974                                 return Compare (arg2, arg1);
975                         else
976                                 return Compare (arg1, arg2);
977                 }
978         }
979
980         internal class ExprGT : RelationalExpr
981         {
982                 public ExprGT (Expression left, Expression right) : base (left, right) {}
983                 protected override String Operator { get { return ">"; }}
984                 public override bool Compare (double arg1, double arg2)
985                 {
986                         return arg1 > arg2;
987                 }
988         }
989
990         internal class ExprGE : RelationalExpr
991         {
992                 public ExprGE (Expression left, Expression right) : base (left, right) {}
993                 protected override String Operator { get { return ">="; }}
994                 public override bool Compare (double arg1, double arg2)
995                 {
996                         return arg1 >= arg2;
997                 }
998         }
999
1000         internal class ExprLT : RelationalExpr
1001         {
1002                 public ExprLT (Expression left, Expression right) : base (left, right) {}
1003                 protected override String Operator { get { return "<"; }}
1004                 public override bool Compare (double arg1, double arg2)
1005                 {
1006                         return arg1 < arg2;
1007                 }
1008         }
1009
1010         internal class ExprLE : RelationalExpr
1011         {
1012                 public ExprLE (Expression left, Expression right) : base (left, right) {}
1013                 protected override String Operator { get { return "<="; }}
1014                 public override bool Compare (double arg1, double arg2)
1015                 {
1016                         return arg1 <= arg2;
1017                 }
1018         }
1019
1020         internal abstract class ExprNumeric : ExprBinary
1021         {
1022                 public ExprNumeric (Expression left, Expression right) : base (left, right) {}
1023                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
1024
1025                 public override Expression Optimize ()
1026                 {
1027                         base.Optimize ();
1028                         return !HasStaticValue ?
1029                                 (Expression) this :
1030                                 new ExprNumber (StaticValueAsNumber);
1031                 }
1032
1033                 public override object Evaluate (BaseIterator iter)
1034                 {
1035                         return EvaluateNumber (iter);
1036                 }
1037         }
1038
1039         internal class ExprPLUS : ExprNumeric
1040         {
1041                 public ExprPLUS (Expression left, Expression right) : base (left, right) {}
1042                 protected override String Operator { get { return "+"; }}
1043
1044                 public override double StaticValueAsNumber {
1045                         get { return HasStaticValue ? _left.StaticValueAsNumber + _right.StaticValueAsNumber: 0; }
1046                 }
1047
1048                 public override double EvaluateNumber (BaseIterator iter)
1049                 {
1050                         return _left.EvaluateNumber (iter) + _right.EvaluateNumber (iter);
1051                 }
1052         }
1053
1054         internal class ExprMINUS : ExprNumeric
1055         {
1056                 public ExprMINUS (Expression left, Expression right) : base (left, right) {}
1057                 protected override String Operator { get { return "-"; }}
1058
1059                 public override double StaticValueAsNumber {
1060                         get { return HasStaticValue ? _left.StaticValueAsNumber - _right.StaticValueAsNumber: 0; }
1061                 }
1062
1063                 public override double EvaluateNumber (BaseIterator iter)
1064                 {
1065                         return _left.EvaluateNumber (iter) - _right.EvaluateNumber (iter);
1066                 }
1067         }
1068
1069         internal class ExprMULT : ExprNumeric
1070         {
1071                 public ExprMULT (Expression left, Expression right) : base (left, right) {}
1072                 protected override String Operator { get { return "*"; }}
1073
1074                 public override double StaticValueAsNumber {
1075                         get { return HasStaticValue ? _left.StaticValueAsNumber * _right.StaticValueAsNumber: 0; }
1076                 }
1077
1078                 public override double EvaluateNumber (BaseIterator iter)
1079                 {
1080                         return _left.EvaluateNumber (iter) * _right.EvaluateNumber (iter);
1081                 }
1082         }
1083
1084         internal class ExprDIV : ExprNumeric
1085         {
1086                 public ExprDIV (Expression left, Expression right) : base (left, right) {}
1087                 protected override String Operator { get { return " div "; }}
1088
1089                 public override double StaticValueAsNumber {
1090                         get { return HasStaticValue ? _left.StaticValueAsNumber / _right.StaticValueAsNumber: 0; }
1091                 }
1092
1093                 public override double EvaluateNumber (BaseIterator iter)
1094                 {
1095                         return _left.EvaluateNumber (iter) / _right.EvaluateNumber (iter);
1096                 }
1097         }
1098
1099         internal class ExprMOD : ExprNumeric
1100         {
1101                 public ExprMOD (Expression left, Expression right) : base (left, right) {}
1102                 protected override String Operator { get { return "%"; }}
1103
1104                 public override double StaticValueAsNumber {
1105                         get { return HasStaticValue ? _left.StaticValueAsNumber % _right.StaticValueAsNumber: 0; }
1106                 }
1107
1108                 public override double EvaluateNumber (BaseIterator iter)
1109                 {
1110                         return _left.EvaluateNumber (iter) % _right.EvaluateNumber (iter);
1111                 }
1112         }
1113
1114         internal class ExprNEG : Expression
1115         {
1116                 Expression _expr;
1117                 public ExprNEG (Expression expr)
1118                 {
1119                         _expr = expr;
1120                 }
1121                 public override String ToString () { return "- " + _expr.ToString (); }
1122                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
1123
1124                 public override Expression Optimize ()
1125                 {
1126                         _expr = _expr.Optimize ();
1127                         return !HasStaticValue ?
1128                                 (Expression) this :
1129                                 new ExprNumber (StaticValueAsNumber);
1130                 }
1131
1132                 internal override bool Peer {
1133                         get { return _expr.Peer; }
1134                 }
1135
1136                 public override bool HasStaticValue {
1137                         get { return _expr.HasStaticValue; }
1138                 }
1139
1140                 public override double StaticValueAsNumber {
1141                         get { return _expr.HasStaticValue ? -1 * _expr.StaticValueAsNumber : 0; }
1142                 }
1143
1144                 public override object Evaluate (BaseIterator iter)
1145                 {
1146                         return - _expr.EvaluateNumber (iter);
1147                 }
1148                 
1149                 public override double EvaluateNumber (BaseIterator iter)
1150                 {
1151                         return - _expr.EvaluateNumber (iter);
1152                 }
1153
1154                 internal override bool IsPositional {
1155                         get { return _expr.IsPositional; }
1156                 }
1157         }
1158
1159
1160         internal abstract class NodeSet : Expression
1161         {
1162                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
1163
1164                 // For "peer and subtree" optimization. see:
1165                 // http://idealliance.org/papers/dx_xmle04/papers/02-03-02/02-03-02.html
1166                 internal abstract bool Subtree { get; }
1167         }
1168
1169         internal class ExprUNION : NodeSet
1170         {
1171                 internal Expression left, right;
1172                 public ExprUNION (Expression left, Expression right)
1173                 {
1174                         this.left = left;
1175                         this.right = right;
1176                 }
1177
1178                 public override Expression Optimize ()
1179                 {
1180                         left = left.Optimize ();
1181                         right = right.Optimize ();
1182                         return this;
1183                 }
1184
1185                 public override String ToString () { return left.ToString ()+ " | " + right.ToString (); }
1186                 public override object Evaluate (BaseIterator iter)
1187                 {
1188                         BaseIterator iterLeft = left.EvaluateNodeSet (iter);
1189                         BaseIterator iterRight = right.EvaluateNodeSet (iter);
1190                         return new UnionIterator (iter, iterLeft, iterRight);
1191                 }
1192
1193                 internal override XPathNodeType EvaluatedNodeType {
1194                         get { return left.EvaluatedNodeType == right.EvaluatedNodeType ? left.EvaluatedNodeType : XPathNodeType.All; }
1195                 }
1196
1197                 internal override bool IsPositional {
1198                         get { return left.IsPositional || right.IsPositional; }
1199                 }
1200
1201                 internal override bool Peer {
1202                         get { return left.Peer && right.Peer; }
1203                 }
1204
1205                 internal override bool Subtree {
1206                         get {
1207                                 NodeSet nl = left as NodeSet;
1208                                 NodeSet nr = right as NodeSet;
1209                                 return nl != null && nr != null && nl.Subtree && nr.Subtree;
1210                         }
1211                 }
1212         }
1213
1214         internal class ExprSLASH : NodeSet
1215         {
1216                 public Expression left;
1217                 public NodeSet right;
1218                 public ExprSLASH (Expression left, NodeSet right)
1219                 {
1220                         this.left = left;
1221                         this.right = right;
1222                 }
1223
1224                 public override Expression Optimize ()
1225                 {
1226                         left = left.Optimize ();
1227                         right = (NodeSet) right.Optimize ();
1228                         return this;
1229                 }
1230
1231                 public override String ToString () { return left.ToString ()+ "/" + right.ToString (); }
1232                 public override object Evaluate (BaseIterator iter)
1233                 {
1234                         // Peer and subtree optimization. see
1235                         // http://idealliance.org/papers/dx_xmle04/papers/02-03-02/02-03-02.html
1236                         BaseIterator iterLeft = left.EvaluateNodeSet (iter);
1237                         if (left.Peer && right.Subtree)
1238                                 return new SimpleSlashIterator (iterLeft, right);
1239                         BaseIterator si = new SlashIterator (iterLeft, right);
1240                         return new SortedIterator (si);
1241                 }
1242
1243                 public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
1244
1245                 internal override XPathNodeType EvaluatedNodeType {
1246                         get { return right.EvaluatedNodeType; }
1247                 }
1248
1249                 internal override bool IsPositional {
1250                         get { return left.IsPositional || right.IsPositional; }
1251                 }
1252
1253                 internal override bool Peer {
1254                         get { return left.Peer && right.Peer; }
1255                 }
1256
1257                 internal override bool Subtree {
1258                         get {
1259                                 NodeSet n = left as NodeSet;
1260                                 return n != null && n.Subtree && right.Subtree;
1261                         }
1262                 }
1263         }
1264         
1265         internal class ExprSLASH2 : NodeSet {
1266                 public Expression left;
1267                 public NodeSet right;
1268                         
1269                 static NodeTest DescendantOrSelfStar = new NodeTypeTest (Axes.DescendantOrSelf, XPathNodeType.All);
1270
1271                 public ExprSLASH2 (Expression left, NodeSet right)
1272                 {
1273                         this.left = left;
1274                         this.right = right;
1275                 }
1276
1277                 public override Expression Optimize ()
1278                 {
1279                         left = left.Optimize ();
1280                         right = (NodeSet) right.Optimize ();
1281                         // Path A//B is equal to 
1282                         // A/descendant-or-self::node()/child::B, which is
1283                         // equivalent to A/descendant::B. Unlike '//', '/'
1284                         // could be optimized by SimpleSlashIterator.
1285                         NodeTest rnt = right as NodeTest;
1286                         if (rnt != null && rnt.Axis.Axis == Axes.Child) {
1287                                 NodeNameTest nameTest = rnt as NodeNameTest;
1288                                 if (nameTest != null)
1289                                         return new ExprSLASH (left,
1290                                                 new NodeNameTest (nameTest, Axes.Descendant));
1291                                 NodeTypeTest typeTest = rnt as NodeTypeTest;
1292                                 if (typeTest != null)
1293                                         return new ExprSLASH (left,
1294                                                 new NodeTypeTest (typeTest, Axes.Descendant));
1295                         }
1296                         return this;
1297                 }
1298
1299                 public override String ToString () { return left.ToString ()+ "//" + right.ToString (); }
1300                 public override object Evaluate (BaseIterator iter)
1301                 {
1302                         BaseIterator il = left.EvaluateNodeSet (iter);
1303                         if (left.Peer && !left.RequireSorting)
1304                                 il = new SimpleSlashIterator (
1305                                         il, DescendantOrSelfStar);
1306                         else {
1307                                 BaseIterator bb = new SlashIterator (il, DescendantOrSelfStar);
1308                                 il = left.RequireSorting ? new SortedIterator (bb) : bb;
1309                         }
1310
1311                         // FIXME: there could be chances to introduce sort-less
1312                         // iterator, but no one could do it yet.
1313                         SlashIterator b = new SlashIterator (il, right);
1314                         return new SortedIterator (b);
1315                 }
1316
1317                 public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
1318
1319                 internal override XPathNodeType EvaluatedNodeType {
1320                         get { return right.EvaluatedNodeType; }
1321                 }
1322
1323                 internal override bool IsPositional {
1324                         get { return left.IsPositional || right.IsPositional; }
1325                 }
1326
1327                 internal override bool Peer {
1328                         get { return false; }
1329                 }
1330
1331                 internal override bool Subtree {
1332                         get {
1333                                 NodeSet n = left as NodeSet;
1334                                 return n != null && n.Subtree && right.Subtree;
1335                         }
1336                 }
1337         }
1338
1339         internal class ExprRoot : NodeSet
1340         {
1341                 public override String ToString () { return ""; }
1342                 public override object Evaluate (BaseIterator iter)
1343                 {
1344                         if (iter.CurrentPosition == 0) {
1345                                 iter = (BaseIterator) iter.Clone ();
1346                                 iter.MoveNext ();
1347                         }
1348                         XPathNavigator navRoot = iter.Current.Clone ();
1349                         navRoot.MoveToRoot ();
1350                         return new SelfIterator (navRoot, iter.NamespaceManager);
1351                 }
1352
1353                 internal override XPathNodeType EvaluatedNodeType {
1354                         get { return XPathNodeType.Root; }
1355                 }
1356
1357                 internal override bool Peer {
1358                         get { return true; }
1359                 }
1360
1361                 internal override bool Subtree {
1362                         get { return false; }
1363                 }
1364         }
1365
1366         internal enum Axes
1367         {
1368                 Ancestor,
1369                 AncestorOrSelf,
1370                 Attribute,
1371                 Child,
1372                 Descendant,
1373                 DescendantOrSelf,
1374                 Following,
1375                 FollowingSibling,
1376                 Namespace,
1377                 Parent,
1378                 Preceding,
1379                 PrecedingSibling,
1380                 Self,
1381         }
1382
1383         internal class AxisSpecifier
1384         {
1385                 protected Axes _axis;
1386                 public AxisSpecifier (Axes axis)
1387                 {
1388                         _axis = axis;
1389                 }
1390                 public XPathNodeType NodeType
1391                 {
1392                         get
1393                         {
1394                                 switch (_axis) {
1395                                 case Axes.Namespace:
1396                                         return XPathNodeType.Namespace;
1397                                 case Axes.Attribute:
1398                                         return XPathNodeType.Attribute;
1399                                 default:
1400                                         return XPathNodeType.Element;
1401                                 }
1402                         }
1403                 }
1404                 public override string ToString ()
1405                 {
1406                         switch (_axis) {
1407                         case Axes.Ancestor:
1408                                 return "ancestor";
1409                         case Axes.AncestorOrSelf:
1410                                 return "ancestor-or-self";
1411                         case Axes.Attribute:
1412                                 return "attribute";
1413                         case Axes.Child:
1414                                 return "child";
1415                         case Axes.Descendant:
1416                                 return "descendant";
1417                         case Axes.DescendantOrSelf:
1418                                 return "descendant-or-self";
1419                         case Axes.Following:
1420                                 return "following";
1421                         case Axes.FollowingSibling:
1422                                 return "following-sibling";
1423                         case Axes.Namespace:
1424                                 return "namespace";
1425                         case Axes.Parent:
1426                                 return "parent";
1427                         case Axes.Preceding:
1428                                 return "preceding";
1429                         case Axes.PrecedingSibling:
1430                                 return "preceding-sibling";
1431                         case Axes.Self:
1432                                 return "self";
1433                         default:
1434                                 throw new IndexOutOfRangeException ();
1435                         }
1436                 }
1437                 public Axes Axis { get { return _axis; }}
1438                 public BaseIterator Evaluate (BaseIterator iter)
1439                 {
1440                         switch (_axis) {
1441                         case Axes.Ancestor:
1442                                 return new AncestorIterator (iter);
1443                         case Axes.AncestorOrSelf:
1444                                 return new AncestorOrSelfIterator (iter);
1445                         case Axes.Attribute:
1446                                 return new AttributeIterator (iter);
1447                         case Axes.Child:
1448                                 return new ChildIterator (iter);
1449                         case Axes.Descendant:
1450                                 return new DescendantIterator (iter);
1451                         case Axes.DescendantOrSelf:
1452                                 return new DescendantOrSelfIterator (iter);
1453                         case Axes.Following:
1454                                 return new FollowingIterator (iter);
1455                         case Axes.FollowingSibling:
1456                                 return new FollowingSiblingIterator (iter);
1457                         case Axes.Namespace:
1458                                 return new NamespaceIterator (iter);
1459                         case Axes.Parent:
1460                                 return new ParentIterator (iter);
1461                         case Axes.Preceding:
1462                                 return new PrecedingIterator (iter);
1463                         case Axes.PrecedingSibling:
1464                                 return new PrecedingSiblingIterator (iter);
1465                         case Axes.Self:
1466                                 return new SelfIterator (iter);
1467                         default:
1468                                 throw new IndexOutOfRangeException ();
1469                         }
1470                 }
1471         }
1472
1473         internal abstract class NodeTest : NodeSet
1474         {
1475                 protected AxisSpecifier _axis;
1476                 public NodeTest (Axes axis)
1477                 {
1478                         _axis = new AxisSpecifier (axis);
1479                 }
1480                 public abstract bool Match (NSResolver nsm, XPathNavigator nav);
1481                 public AxisSpecifier Axis { get { return _axis; }}
1482                 public override object Evaluate (BaseIterator iter)
1483                 {
1484                         BaseIterator iterAxis = _axis.Evaluate (iter);
1485                         return new AxisIterator (iterAxis, this);
1486                 }
1487                 
1488                 public abstract void GetInfo (out string name, out string ns, out XPathNodeType nodetype, NSResolver nsm);
1489
1490                 public override bool RequireSorting {
1491                         get {
1492                                 switch (_axis.Axis) {
1493                                 case Axes.Ancestor:
1494                                 case Axes.AncestorOrSelf:
1495                                 case Axes.Preceding:
1496                                 case Axes.PrecedingSibling:
1497                                 case Axes.Attribute:
1498                                 case Axes.Namespace:
1499                                         return true;
1500                                 default:
1501                                         return false;
1502                                 }
1503                         }
1504
1505                 }
1506
1507                 internal override bool Peer {
1508                         get {
1509                                 switch (_axis.Axis) {
1510                                 case Axes.Ancestor:
1511                                 case Axes.AncestorOrSelf:
1512                                 case Axes.DescendantOrSelf:
1513                                 case Axes.Descendant:
1514                                 case Axes.Preceding:
1515                                 case Axes.Following:
1516                                         return false;
1517                                 default:
1518                                         return true;
1519                                 }
1520                         }
1521                 }
1522
1523                 internal override bool Subtree {
1524                         get {
1525                                 switch (_axis.Axis) {
1526                                 case Axes.Parent:
1527                                 case Axes.Ancestor:
1528                                 case Axes.AncestorOrSelf:
1529                                 case Axes.Preceding:
1530                                 case Axes.PrecedingSibling:
1531                                 case Axes.Following:
1532                                 case Axes.FollowingSibling:
1533                                         return false;
1534                                 default:
1535                                         return true;
1536                                 }
1537                         }
1538
1539                 }
1540
1541                 internal override XPathNodeType EvaluatedNodeType {
1542                         get { return _axis.NodeType; }
1543                 }
1544         }
1545
1546         internal class NodeTypeTest : NodeTest
1547         {
1548                 public readonly XPathNodeType type;
1549                 protected String _param;
1550                 public NodeTypeTest (Axes axis) : base (axis)
1551                 {
1552                         this.type = _axis.NodeType;
1553                 }
1554                 public NodeTypeTest (Axes axis, XPathNodeType type) : base (axis)
1555                 {
1556                         this.type = type;
1557                 }
1558                 // FIXME: Better description
1559                 public NodeTypeTest (Axes axis, XPathNodeType type, String param) : base (axis)
1560                 {
1561                         this.type = type;
1562                         _param = param;
1563                         if (param != null && type != XPathNodeType.ProcessingInstruction)
1564                                 throw new XPathException ("No argument allowed for "+ToString (type)+"() test");        // TODO: better description
1565                 }
1566
1567                 // for optimizer use
1568                 internal NodeTypeTest (NodeTypeTest other, Axes axis)
1569                         : base (axis)
1570                 {
1571                         type = other.type;
1572                         _param = other._param;
1573                 }
1574
1575                 public override String ToString ()
1576                 {
1577                         String strType = ToString (type);
1578                         if (type == XPathNodeType.ProcessingInstruction && _param != null)
1579                                 strType += "('" + _param + "')";
1580                         else
1581                                 strType += "()";
1582
1583                         return _axis.ToString () + "::" + strType;
1584                 }
1585
1586                 private static String ToString (XPathNodeType type)
1587                 {
1588                         switch (type) {
1589                         case XPathNodeType.Comment:
1590                                 return "comment";
1591                         case XPathNodeType.Text:
1592                                 return "text";
1593                         case XPathNodeType.ProcessingInstruction:
1594                                 return "processing-instruction";
1595                         case XPathNodeType.All:
1596                         case XPathNodeType.Attribute:
1597                         case XPathNodeType.Element:
1598                         case XPathNodeType.Namespace:
1599                                 return "node";
1600                         default:
1601                                 return "node-type [" + type.ToString () + "]";
1602                         }
1603                 }
1604
1605                 public override bool Match (NSResolver nsm, XPathNavigator nav)
1606                 {
1607                         XPathNodeType nodeType = nav.NodeType;
1608                         switch (type) {
1609                         case XPathNodeType.All:
1610                                 return true;
1611
1612                         case XPathNodeType.ProcessingInstruction:
1613                                 if (nodeType != XPathNodeType.ProcessingInstruction)
1614                                         return false;
1615                                 if (_param != null && nav.Name != _param)
1616                                         return false;
1617                                 return true;
1618                         
1619                         case XPathNodeType.Text:
1620                                 switch (nodeType) {
1621                                 case XPathNodeType.Text:
1622                                 case XPathNodeType.Whitespace:
1623                                 case XPathNodeType.SignificantWhitespace:
1624                                         return true;
1625                                 default:
1626                                         return false;
1627                                 }
1628                         default:
1629                                 return type == nodeType;
1630                         }
1631                 }
1632                 
1633                 public override void GetInfo (out string name, out string ns, out XPathNodeType nodetype, NSResolver nsm)
1634                 {
1635                         name = _param;
1636                         ns = null;
1637                         nodetype = type;
1638                 }
1639         }
1640
1641         internal class NodeNameTest : NodeTest
1642         {
1643                 protected XmlQualifiedName _name;
1644                 protected readonly bool resolvedName = false;
1645                 public NodeNameTest (Axes axis, XmlQualifiedName name, IStaticXsltContext ctx) : base (axis)
1646                 {
1647                         if (ctx != null) {
1648                                 name = ctx.LookupQName (name.ToString ());
1649                                 resolvedName = true;
1650                         }
1651                         _name = name;
1652                 }
1653                 
1654                 public NodeNameTest (Axes axis, XmlQualifiedName name, bool resolvedName) : base (axis)
1655                 {
1656                         _name = name;
1657                         this.resolvedName = resolvedName;
1658                 }
1659
1660                 // for optimized path rewrite
1661                 internal NodeNameTest (NodeNameTest source, Axes axis)
1662                         : base (axis)
1663                 {
1664                         _name = source._name;
1665                         resolvedName = source.resolvedName;
1666                 }
1667
1668                 public override String ToString () { return _axis.ToString () + "::" + _name.ToString (); }
1669                 
1670                 public XmlQualifiedName Name { get { return _name; } }
1671
1672                 public override bool Match (NSResolver nsm, XPathNavigator nav)
1673                 {
1674                         // must be the correct node type
1675                         if (nav.NodeType != _axis.NodeType)
1676                                 return false;
1677
1678                         if (_name.Name != "")
1679                         {
1680                                 // test the local part of the name first
1681                                 if (_name.Name != nav.LocalName)
1682                                         return false;
1683                         }
1684
1685                         // get the prefix for the given name
1686                         String strURI1 = "";
1687                         if (_name.Namespace != "")
1688                         {
1689                                 if (resolvedName)
1690                                         strURI1 = _name.Namespace;
1691                                 else if (nsm != null)
1692                                         strURI1 = nsm.LookupNamespace (_name.Namespace);
1693                                 if (strURI1 == null)
1694                                         throw new XPathException ("Invalid namespace prefix: "+_name.Namespace);
1695                         }
1696
1697                         // test the prefixes
1698                         return strURI1 == nav.NamespaceURI;
1699                 }
1700                 
1701                 public override void GetInfo (out string name, out string ns, out XPathNodeType nodetype, NSResolver nsm)
1702                 {
1703                         // must be the correct node type
1704                         nodetype = _axis.NodeType;
1705                         
1706                         if (_name.Name != "")
1707                                 name = _name.Name;
1708                         else
1709                                 name = null;
1710                         ns = "";
1711                         if (nsm != null && _name.Namespace != "") {
1712                                 if (resolvedName)
1713                                         ns = _name.Namespace;
1714                                 else
1715                                         ns = nsm.LookupNamespace (_name.Namespace);     // TODO: check to see if this returns null or ""
1716                                 if (ns == null)
1717                                         throw new XPathException ("Invalid namespace prefix: "+_name.Namespace);
1718                         }
1719                 }
1720         }
1721
1722         internal class ExprFilter : NodeSet
1723         {
1724                 internal Expression expr, pred;
1725                 
1726                 public ExprFilter (Expression expr, Expression pred)
1727                 {
1728                         this.expr = expr;
1729                         this.pred = pred;
1730                 }
1731
1732                 public override Expression Optimize ()
1733                 {
1734                         expr = expr.Optimize ();
1735                         pred = pred.Optimize ();
1736                         return this;
1737                 }
1738                 
1739                 internal Expression LeftHandSide {get{return expr;}}
1740                 public override String ToString () { return "(" + expr.ToString () + ")[" + pred.ToString () + "]"; }
1741                 public override object Evaluate (BaseIterator iter)
1742                 {
1743                         BaseIterator iterExpr = expr.EvaluateNodeSet (iter);
1744                         return new PredicateIterator (iterExpr, pred);
1745                 }
1746
1747                 internal override XPathNodeType EvaluatedNodeType {
1748                         get { return expr.EvaluatedNodeType; }
1749                 }
1750
1751                 internal override bool IsPositional {
1752                         get {
1753                                 if (pred.ReturnType == XPathResultType.Number)
1754                                         return true;
1755                                 return expr.IsPositional || pred.IsPositional;
1756                         }
1757                 }
1758
1759                 internal override bool Peer {
1760                         get { return expr.Peer && pred.Peer; }
1761                 }
1762
1763                 internal override bool Subtree {
1764                         get {
1765                                 NodeSet n = expr as NodeSet;
1766                                 return n != null && n.Subtree;
1767                         }
1768                 }
1769         }
1770
1771         internal class ExprNumber : Expression
1772         {
1773                 protected double _value;
1774                 public ExprNumber (double value)
1775                 {
1776                         _value = value;
1777                 }
1778                 public override String ToString () { return _value.ToString (); }
1779                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
1780
1781                 internal override bool Peer {
1782                         get { return true; }
1783                 }
1784
1785                 public override bool HasStaticValue {
1786                         get { return true; }
1787                 }
1788
1789                 public override double StaticValueAsNumber {
1790                         get { return XPathFunctions.ToNumber (_value); }
1791                 }
1792
1793                 public override object Evaluate (BaseIterator iter)
1794                 {
1795                         return _value;
1796                 }
1797                 
1798                 public override double EvaluateNumber (BaseIterator iter)
1799                 {
1800                         return _value;
1801                 }
1802
1803                 internal override bool IsPositional {
1804                         get { return false; }
1805                 }
1806         }
1807
1808         internal class BooleanConstant : Expression
1809         {
1810                 bool _value;
1811
1812                 public BooleanConstant (bool value)
1813                 {
1814                         _value = value;
1815                 }
1816
1817                 public override String ToString () { return _value ? "true()" : "false()"; }
1818                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
1819
1820                 internal override bool Peer {
1821                         get { return true; }
1822                 }
1823
1824                 public override bool HasStaticValue {
1825                         get { return true; }
1826                 }
1827
1828                 public override bool StaticValueAsBoolean {
1829                         get { return _value; }
1830                 }
1831
1832                 public override object Evaluate (BaseIterator iter)
1833                 {
1834                         return _value;
1835                 }
1836                 
1837                 public override bool EvaluateBoolean (BaseIterator iter)
1838                 {
1839                         return _value;
1840                 }
1841         }
1842
1843         internal class ExprLiteral : Expression
1844         {
1845                 protected String _value;
1846                 public ExprLiteral (String value)
1847                 {
1848                         _value = value;
1849                 }
1850                 public string Value { get { return _value; } }
1851                 public override String ToString () { return "'" + _value + "'"; }
1852                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
1853
1854                 internal override bool Peer {
1855                         get { return true; }
1856                 }
1857
1858                 public override bool HasStaticValue {
1859                         get { return true; }
1860                 }
1861
1862                 public override string StaticValueAsString {
1863                         get { return _value; }
1864                 }
1865
1866                 public override object Evaluate (BaseIterator iter)
1867                 {
1868                         return _value;
1869                 }
1870                 
1871                 public override string EvaluateString (BaseIterator iter)
1872                 {
1873                         return _value;
1874                 }
1875         }
1876
1877         internal class ExprVariable : Expression
1878         {
1879                 protected XmlQualifiedName _name;
1880                 protected bool resolvedName = false;
1881                 public ExprVariable (XmlQualifiedName name, IStaticXsltContext ctx)
1882                 {
1883                         if (ctx != null) {
1884                                 name = ctx.LookupQName (name.ToString ());
1885                                 resolvedName = true;
1886                         }
1887                         
1888                         _name = name;
1889                 }
1890                 public override String ToString () { return "$" + _name.ToString (); }
1891                 public override XPathResultType ReturnType { get { return XPathResultType.Any; }}
1892                 public override XPathResultType GetReturnType (BaseIterator iter)
1893                 {
1894                         return XPathResultType.Any;
1895                 }
1896                 
1897                 public override object Evaluate (BaseIterator iter)
1898                 {
1899                         IXsltContextVariable var = null;
1900                         
1901                         XsltContext context = iter.NamespaceManager as XsltContext;
1902                         if (context != null) {
1903                                 if (resolvedName)
1904                                         var = context.ResolveVariable (_name);
1905                                 else
1906                                         var = context.ResolveVariable (new XmlQualifiedName (_name.Name, _name.Namespace));
1907                         }
1908                         else
1909                                 throw new XPathException (String.Format ("XSLT context is required to resolve variable. Current namespace manager in current node-set '{0}' is '{1}'", iter.GetType (), iter.NamespaceManager != null ? iter.NamespaceManager.GetType () : null));
1910                         
1911                         if (var == null)
1912                                 throw new XPathException ("variable "+_name.ToString ()+" not found");
1913                         object objResult = var.Evaluate (context);
1914                         XPathNodeIterator iterResult = objResult as XPathNodeIterator;
1915                         if (iterResult != null)
1916                                 return iterResult is BaseIterator ? iterResult : new WrapperIterator (iterResult, iter.NamespaceManager);
1917                         return objResult;
1918                 }
1919
1920                 internal override bool Peer {
1921                         get { return false; }
1922                 }
1923         }
1924
1925         internal class ExprParens : Expression
1926         {
1927                 protected Expression _expr;
1928                 public ExprParens (Expression expr)
1929                 {
1930                         _expr = expr;
1931                 }
1932
1933                 public override Expression Optimize ()
1934                 {
1935                         _expr.Optimize ();
1936                         return this;
1937                 }
1938
1939                 public override bool HasStaticValue {
1940                         get { return _expr.HasStaticValue; }
1941                 }
1942
1943                 public override object StaticValue {
1944                         get { return _expr.StaticValue; }
1945                 }
1946
1947                 public override string StaticValueAsString {
1948                         get { return _expr.StaticValueAsString; }
1949                 }
1950
1951                 public override double StaticValueAsNumber {
1952                         get { return _expr.StaticValueAsNumber; }
1953                 }
1954
1955                 public override bool StaticValueAsBoolean {
1956                         get { return _expr.StaticValueAsBoolean; }
1957                 }
1958
1959                 public override String ToString () { return "(" + _expr.ToString () + ")"; }
1960                 public override XPathResultType ReturnType { get { return _expr.ReturnType; }}
1961                 public override object Evaluate (BaseIterator iter)
1962                 {
1963                         object o = (_expr.Evaluate (iter));
1964                         XPathNodeIterator xi = o as XPathNodeIterator;
1965                         BaseIterator predBase = xi as BaseIterator;
1966                         if (predBase == null && xi != null)
1967                                 predBase = new WrapperIterator (xi, iter.NamespaceManager);
1968                         if (predBase != null)
1969                                 return new ParensIterator (predBase);
1970                         else
1971                                 return o;
1972                 }
1973
1974                 internal override XPathNodeType EvaluatedNodeType {
1975                         get { return _expr.EvaluatedNodeType; }
1976                 }
1977
1978                 internal override bool IsPositional {
1979                         get { return _expr.IsPositional; }
1980                 }
1981
1982                 internal override bool Peer {
1983                         get { return _expr.Peer; }
1984                 }
1985         }
1986
1987         internal class FunctionArguments
1988         {
1989                 protected Expression _arg;
1990                 protected FunctionArguments _tail;
1991                 public FunctionArguments (Expression arg, FunctionArguments tail)
1992                 {
1993                         _arg = arg;
1994                         _tail = tail;
1995                 }
1996                 public Expression Arg
1997                 {
1998                         get { return _arg; }
1999                 }
2000                 public FunctionArguments Tail
2001                 {
2002                         get { return _tail; }
2003                 }
2004                 
2005                 public void ToArrayList (ArrayList a)
2006                 {
2007                         FunctionArguments cur = this;
2008                         
2009                         do {
2010                                 a.Add (cur._arg);
2011                                 cur = cur._tail;
2012                         } while (cur != null);
2013                         
2014                 }
2015         }
2016
2017         internal class ExprFunctionCall : Expression
2018         {
2019                 protected readonly XmlQualifiedName _name;
2020                 protected readonly bool resolvedName = false;
2021                 protected readonly ArrayList _args = new ArrayList ();
2022                 public ExprFunctionCall (XmlQualifiedName name, FunctionArguments args, IStaticXsltContext ctx)
2023                 {
2024                         if (ctx != null) {
2025                                 name = ctx.LookupQName (name.ToString ());
2026                                 resolvedName = true;
2027                         }
2028                         
2029                         _name = name;
2030                         if (args != null)
2031                                 args.ToArrayList (_args);
2032                 }
2033                 
2034                 public static Expression Factory (XmlQualifiedName name, FunctionArguments args, IStaticXsltContext ctx)
2035                 {
2036                         if (name.Namespace != null && name.Namespace != "")
2037                                 return new ExprFunctionCall (name, args, ctx);
2038                         
2039                         switch (name.Name) {
2040                         case "last": return new XPathFunctionLast (args);
2041                         case "position": return new XPathFunctionPosition (args);
2042                         case "count": return new XPathFunctionCount (args);
2043                         case "id": return new XPathFunctionId (args);
2044                         case "local-name": return new XPathFunctionLocalName (args);
2045                         case "namespace-uri": return new XPathFunctionNamespaceUri (args);
2046                         case "name": return new XPathFunctionName (args);
2047                         case "string": return new XPathFunctionString (args);
2048                         case "concat": return new XPathFunctionConcat (args);
2049                         case "starts-with": return new XPathFunctionStartsWith (args);
2050                         case "contains": return new XPathFunctionContains (args);
2051                         case "substring-before": return new XPathFunctionSubstringBefore (args);
2052                         case "substring-after": return new XPathFunctionSubstringAfter (args);
2053                         case "substring": return new XPathFunctionSubstring (args);
2054                         case "string-length": return new XPathFunctionStringLength (args);
2055                         case "normalize-space": return new XPathFunctionNormalizeSpace (args);
2056                         case "translate": return new XPathFunctionTranslate (args);
2057                         case "boolean": return new XPathFunctionBoolean (args);
2058                         case "not": return new XPathFunctionNot (args);
2059                         case "true": return new XPathFunctionTrue (args);
2060                         case "false": return new XPathFunctionFalse (args);
2061                         case "lang": return new XPathFunctionLang (args);
2062                         case "number": return new XPathFunctionNumber (args);
2063                         case "sum": return new XPathFunctionSum (args);
2064                         case "floor": return new XPathFunctionFloor (args);
2065                         case "ceiling": return new XPathFunctionCeil (args);
2066                         case "round": return new XPathFunctionRound (args);
2067                         }
2068                         return new ExprFunctionCall (name, args, ctx);
2069                 }
2070                 
2071                 public override String ToString ()
2072                 {
2073                         String strArgs = "";
2074                         for (int i = 0; i < _args.Count; i++) {
2075                                 Expression arg = (Expression) _args [i];
2076                                 if (strArgs != "")
2077                                         strArgs += ", ";
2078                                 strArgs += arg.ToString ();
2079                         }
2080                         return _name.ToString () + '(' + strArgs + ')';
2081                 }
2082                 public override XPathResultType ReturnType { get { return XPathResultType.Any; }}
2083                 public override XPathResultType GetReturnType (BaseIterator iter)
2084                 {
2085                         return XPathResultType.Any;
2086                 }
2087                 
2088                 private XPathResultType [] GetArgTypes (BaseIterator iter)
2089                 {
2090                         // TODO: can we cache these? what if the types depend on the nsm?
2091                         XPathResultType [] rgArgs = new XPathResultType [_args.Count];
2092                         for (int iArg = 0; iArg < _args.Count; iArg++)
2093                                 rgArgs [iArg] = ((Expression) _args [iArg]).GetReturnType (iter);
2094                         return rgArgs;
2095                 }
2096                 public override object Evaluate (BaseIterator iter)
2097                 {
2098                         XPathResultType [] rgTypes = GetArgTypes (iter);
2099                         IXsltContextFunction func = null;
2100                         XsltContext context = iter.NamespaceManager as XsltContext;
2101                         if (context != null) {
2102                                 if (resolvedName)
2103                                         func = context.ResolveFunction (_name, rgTypes);
2104                                 else
2105                                         func = context.ResolveFunction (_name.Namespace, _name.Name, rgTypes);
2106                         }
2107
2108                         if (func == null)
2109                                 throw new XPathException ("function "+_name.ToString ()+" not found");
2110
2111                         object [] rgArgs = new object [_args.Count];
2112                         if (func.Maxargs != 0)
2113                         {
2114                                 XPathResultType [] rgFuncTypes = func.ArgTypes;
2115                                 for (int iArg = 0; iArg < _args.Count; iArg ++)
2116                                 {
2117                                         XPathResultType typeArg;
2118                                         if (rgFuncTypes == null)
2119                                                 typeArg = XPathResultType.Any;
2120                                         else if (iArg < rgFuncTypes.Length)
2121                                                 typeArg = rgFuncTypes [iArg];
2122                                         else
2123                                                 typeArg = rgFuncTypes [rgFuncTypes.Length - 1];
2124
2125                                         Expression arg = (Expression) _args [iArg];
2126                                         object result = arg.EvaluateAs (iter, typeArg);
2127                                         rgArgs [iArg] = result;
2128                                 }
2129                         }
2130                         return func.Invoke (context, rgArgs, iter.Current);
2131                 }
2132
2133                 internal override bool Peer {
2134                         get { return false; }
2135                 }
2136         }
2137 }