2 // XPath2Expression.cs - abstract syntax tree for XPath 2.0
5 // Atsushi Enomoto <atsushi@ximian.com>
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Globalization;
34 using System.Xml.Query;
35 using System.Xml.Schema;
36 using System.Xml.XPath;
37 using Mono.Xml.XQuery;
39 namespace Mono.Xml.XPath2
41 public class ExprSequence : CollectionBase
43 public ExprSequence ()
47 public void Add (ExprSingle expr)
52 public void AddRange (ICollection items)
55 foreach (ExprSingle e in items)
59 public void Insert (int pos, ExprSingle expr)
61 List.Insert (pos, expr);
64 public ExprSingle this [int i] {
65 get { return List [i] as ExprSingle; }
66 set { List [i] = value; }
69 internal void CheckReference (XQueryASTCompiler compiler)
71 foreach (ExprSingle expr in List)
72 expr.CheckReference (compiler);
76 public abstract partial class ExprSingle
78 internal abstract void CheckReference (XQueryASTCompiler compiler);
80 #region CompileAndEvaluate
81 internal static readonly XPathAtomicValue AtomicTrue = new XPathAtomicValue (true, XmlSchemaSimpleType.XsBoolean);
82 internal static readonly XPathAtomicValue AtomicFalse = new XPathAtomicValue (false, XmlSchemaSimpleType.XsBoolean);
84 XQueryStaticContext ctx;
86 internal ExprSingle Compile (XQueryASTCompiler compiler)
89 return CompileCore (compiler);
92 // If internal&&protected is available in C#, it is the best signature.
93 internal abstract ExprSingle CompileCore (XQueryASTCompiler compiler);
95 internal XQueryStaticContext Context {
99 public abstract SequenceType StaticType { get; }
102 This is the core part of ExprSingle. It is
103 generally used to evaluate expression and returns
104 XPathItem sequence (iterator). The result is unordered
106 public abstract XPathSequence Evaluate (XPathSequence iter);
108 public virtual XPathSequence EvaluateOrdered (XPathSequence iter)
110 if (RequireSorting) {
111 ArrayList al = new ArrayList ();
112 foreach (XPathItem item in Evaluate (iter))
114 return new ListIterator (iter.Context, al);
117 return Evaluate (iter);
120 public virtual void Serialize (XPathSequence iter)
122 XmlWriter w = iter.Context.Writer;
123 XPathSequence result = Evaluate (iter);
125 foreach (XPathItem item in result) {
129 w.WriteWhitespace (" ");
130 WriteXPathItem (item, w);
134 private void WriteXPathItem (XPathItem item, XmlWriter w)
137 XPathNavigator nav = item as XPathNavigator;
138 if (w.WriteState != WriteState.Start && nav.NodeType == XPathNodeType.Root)
139 throw new XmlQueryException ("Current output can not accept root node.");
140 if (w.WriteState == WriteState.Attribute)
141 w.WriteString (nav.Value);
143 w.WriteNode (nav, false);
145 w.WriteString (item.Value);
148 // get EBV (fn:boolean())
149 public virtual bool EvaluateAsBoolean (XPathSequence iter)
151 XPathSequence result = Evaluate (iter);
152 if (!result.MoveNext ())
154 XPathItem v = result.Current;
155 if (v is XPathNavigator)
157 if (result.MoveNext ())
159 switch (v.XmlType.TypeCode) {
160 case XmlTypeCode.Boolean:
161 return v.ValueAsBoolean;
162 case XmlTypeCode.String:
163 case XmlTypeCode.UntypedAtomic:
164 return v.Value != String.Empty;
165 case XmlTypeCode.Float:
166 return v.ValueAsSingle != Single.NaN && v.ValueAsSingle != 0.0;
167 case XmlTypeCode.Double:
168 return v.ValueAsDouble != Double.NaN && v.ValueAsSingle != 0.0;
169 case XmlTypeCode.Decimal:
170 return v.ValueAsDecimal != 0;
171 case XmlTypeCode.Integer:
172 case XmlTypeCode.NonPositiveInteger:
173 case XmlTypeCode.NegativeInteger:
174 case XmlTypeCode.Long:
175 case XmlTypeCode.Int:
176 case XmlTypeCode.Short:
177 case XmlTypeCode.Byte:
178 case XmlTypeCode.UnsignedInt:
179 case XmlTypeCode.UnsignedShort:
180 case XmlTypeCode.UnsignedByte:
181 return v.ValueAsInt64 != 0;
182 case XmlTypeCode.NonNegativeInteger:
183 case XmlTypeCode.UnsignedLong:
184 case XmlTypeCode.PositiveInteger:
185 return (ulong) (v.ValueAs (typeof (ulong))) != 0;
187 // otherwise, return true
191 public virtual int EvaluateAsInt (XPathSequence iter)
193 XPathAtomicValue v = Atomize (Evaluate (iter));
194 return v != null ? v.ValueAsInt32 : 0;
197 public virtual string EvaluateAsString (XPathSequence iter)
199 XPathAtomicValue v = Atomize (Evaluate (iter));
200 return v != null ? v.Value : String.Empty;
203 public static XPathAtomicValue Atomize (XPathItem item)
205 XPathNavigator nav = item as XPathNavigator;
207 if (nav.SchemaInfo != null)
208 return new XPathAtomicValue (nav.TypedValue, nav.SchemaInfo.SchemaType);
210 return new XPathAtomicValue (nav.Value, XmlSchemaSimpleType.XdtUntypedAtomic);
213 return (XPathAtomicValue) item;
216 // FIXME: What if iter contains list value?
217 public static XPathAtomicValue Atomize (XPathSequence iter)
219 if (!iter.MoveNext ())
221 XPathNavigator nav = iter.Current as XPathNavigator;
223 // FIXME: is it really always untypedAtomic?
224 // It might be complex content.
225 XmlSchemaType type = nav.SchemaInfo == null ? XmlSchemaSimpleType.XdtUntypedAtomic : nav.SchemaInfo.SchemaType;
226 return new XPathAtomicValue (nav.TypedValue, type);
229 return (XPathAtomicValue) iter.Current;
232 public virtual XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
234 return Atomize (Evaluate (iter));
237 public virtual bool RequireSorting {
238 get { return false; }
245 internal partial class FLWORExpr : ExprSingle
247 public FLWORExpr (ForLetClauseCollection forlet, ExprSequence whereClause, OrderSpecList orderBy, ExprSingle ret)
250 if (whereClause != null)
251 this.whereClause = new ParenthesizedExpr (whereClause);
252 this.orderBy = orderBy;
256 ForLetClauseCollection fl;
257 ExprSingle whereClause;
258 OrderSpecList orderBy;
261 public ForLetClauseCollection ForLetClauses {
265 public ExprSingle WhereClause {
266 get { return whereClause; }
269 public OrderSpecList OrderBy {
270 get { return orderBy; }
273 public ExprSingle ReturnExpr {
278 // ExprSingle Overrides
280 internal override void CheckReference (XQueryASTCompiler compiler)
282 foreach (ForLetClause flc in fl)
283 foreach (ForLetSingleBody single in flc)
284 single.CheckReference (compiler);
285 if (whereClause != null)
286 whereClause.CheckReference (compiler);
288 foreach (OrderSpec os in orderBy)
289 os.Expression.CheckReference (compiler);
290 ret.CheckReference (compiler);
293 #region CompileAndEvaluate
294 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
296 foreach (ForLetClause flc in ForLetClauses) {
297 foreach (ForLetSingleBody flsb in flc) {
298 flsb.Expression = flsb.Expression.Compile (compiler);
299 if (flsb.ReturnType != null)
300 compiler.CheckType (flsb.Expression, flsb.ReturnType);
303 if (WhereClause != null)
304 whereClause = whereClause.Compile (compiler);
306 foreach (OrderSpec os in OrderBy)
307 os.Expression = os.Expression.Compile (compiler);
308 ReturnExpr = ReturnExpr.Compile (compiler);
313 public override SequenceType StaticType {
314 get { return ReturnExpr.StaticType; }
317 public override XPathSequence Evaluate (XPathSequence iter)
319 return new FLWORIterator (iter, this);
324 internal class ForLetClauseCollection : CollectionBase
326 public void Add (ForLetClause clause)
331 public void Insert (int pos, ForLetClause clause)
333 List.Insert (pos, clause);
336 public ForLetClause this [int i] {
337 get { return (ForLetClause) List [i]; }
341 internal class OrderSpecList : CollectionBase
345 public OrderSpecList ()
349 public bool IsStable {
350 get { return isStable; }
351 set { isStable = value; }
354 public void Insert (int pos, OrderSpec os)
356 List.Insert (pos, os);
359 public void Add (OrderSpec spec)
364 public OrderSpec this [int i] {
365 get { return (OrderSpec) List [i]; }
369 internal class OrderSpec
371 public OrderSpec (ExprSingle expr, OrderModifier modifier)
380 public ExprSingle Expression {
382 set { expr = value; }
385 public OrderModifier Modifier {
391 internal class OrderModifier
393 public OrderModifier (XmlSortOrder order, XmlSortOrder emptyOrder, string collation)
395 this.sortOrder = sortOrder;
396 this.emptyOrder = emptyOrder;
397 if (collation != null)
398 this.coll = new CultureInfo (collation);
401 XmlSortOrder sortOrder;
402 XmlSortOrder emptyOrder;
405 public XmlSortOrder SortOrder {
406 get { return sortOrder; }
409 public XmlSortOrder EmptyOrder {
410 get { return emptyOrder; }
413 public CultureInfo Collation {
418 internal class ForLetClause : CollectionBase
420 public ForLetSingleBody this [int i] {
421 get { return (ForLetSingleBody) List [i]; }
425 internal class ForClause : ForLetClause
431 public void Insert (int pos, ForSingleBody body)
433 List.Insert (pos, body);
436 public void Add (ForSingleBody body)
442 internal class LetClause : ForLetClause
448 public void Insert (int pos, LetSingleBody body)
450 List.Insert (pos, body);
453 public void Add (LetSingleBody body)
459 internal abstract class ForLetSingleBody
461 XmlQualifiedName varName;
465 public ForLetSingleBody (XmlQualifiedName varName, SequenceType type, ExprSingle expr)
467 this.varName = varName;
472 public XmlQualifiedName VarName {
473 get { return varName; }
476 public SequenceType ReturnType {
480 public ExprSingle Expression {
482 set { expr = value; }
485 internal void CheckReference (XQueryASTCompiler compiler)
488 compiler.CheckSchemaType (type);
489 expr.CheckReference (compiler);
493 internal class ForSingleBody : ForLetSingleBody
495 public ForSingleBody (XmlQualifiedName varName, SequenceType type, XmlQualifiedName positionalVar, ExprSingle expr)
496 : base (varName, type, expr)
498 this.positionalVar = positionalVar;
501 XmlQualifiedName positionalVar;
503 public XmlQualifiedName PositionalVar {
504 get { return positionalVar; }
508 internal class LetSingleBody : ForLetSingleBody
510 public LetSingleBody (XmlQualifiedName varName, SequenceType type, ExprSingle expr)
511 : base (varName, type, expr)
518 internal class QuantifiedExpr : ExprSingle
520 QuantifiedExprBodyList body;
521 ExprSingle satisfies;
524 public QuantifiedExpr (bool every, QuantifiedExprBodyList body, ExprSingle satisfies)
528 this.satisfies = satisfies;
532 get { return every; }
535 public QuantifiedExprBodyList BodyList {
539 public ExprSingle Satisfies {
540 get { return satisfies; }
541 set { satisfies = value; }
544 internal override void CheckReference (XQueryASTCompiler compiler)
546 foreach (QuantifiedExprBody one in body) {
547 if (one.Type != null)
548 compiler.CheckSchemaType (one.Type);
549 one.Expression.CheckReference (compiler);
551 Satisfies.CheckReference (compiler);
554 #region CompileAndEvaluate
555 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
557 Satisfies = Satisfies.Compile (compiler);
558 for (int i = 0; i < BodyList.Count; i++) {
559 BodyList [i].Expression = BodyList [i].Expression.Compile (compiler);
560 if (BodyList [i].Type != null)
561 compiler.CheckType (BodyList [i].Expression, BodyList [i].Type);
566 public override SequenceType StaticType {
567 get { return SequenceType.Boolean; }
570 public override XPathSequence Evaluate (XPathSequence iter)
572 return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
575 public override bool EvaluateAsBoolean (XPathSequence iter)
577 return EvaluateQuantification (iter, BodyList.GetEnumerator ());
580 private bool EvaluateQuantification (XPathSequence iter, IEnumerator bodies)
582 if (bodies.MoveNext ()) {
583 QuantifiedExprBody qb = bodies.Current as QuantifiedExprBody;
584 XPathSequence seq = qb.Expression.Evaluate (iter);
586 foreach (XPathItem item in seq) {
588 // FIXME: consider qb.Type
590 iter.Context.PushVariable (qb.VarName, item);
591 if (EvaluateQuantification (iter, bodies)) {
598 iter.Context.PopVariable ();
603 return Satisfies.EvaluateAsBoolean (iter);
608 internal class QuantifiedExprBodyList : CollectionBase
610 public QuantifiedExprBodyList ()
614 public void Add (QuantifiedExprBody body)
619 public void Insert (int pos, QuantifiedExprBody body)
621 List.Insert (pos, body);
624 public QuantifiedExprBody this [int i] {
625 get { return (QuantifiedExprBody) List [i]; }
629 internal class QuantifiedExprBody
631 private XmlQualifiedName varName;
632 private SequenceType type;
633 private ExprSingle expr;
635 public QuantifiedExprBody (XmlQualifiedName varName,
636 SequenceType type, ExprSingle expr)
638 this.varName = varName;
643 public XmlQualifiedName VarName {
644 get { return varName; }
647 public SequenceType Type {
651 public ExprSingle Expression {
653 set { expr = value; }
659 internal class TypeswitchExpr : ExprSingle
661 ExprSequence switchExpr;
662 CaseClauseList caseList;
663 XmlQualifiedName defaultVarName;
664 ExprSingle defaultReturn;
666 public TypeswitchExpr (ExprSequence switchExpr, CaseClauseList caseList, XmlQualifiedName defaultVarName, ExprSingle defaultReturn)
668 this.switchExpr = switchExpr;
669 this.caseList = caseList;
670 this.defaultVarName = defaultVarName;
671 this.defaultReturn = defaultReturn;
674 public ExprSequence SwitchExpr {
675 get { return switchExpr; }
678 public CaseClauseList Cases {
679 get { return caseList; }
682 public XmlQualifiedName DefaultVarName {
683 get { return defaultVarName; }
686 public ExprSingle DefaultReturn {
687 get { return defaultReturn; }
688 set { defaultReturn = value; }
691 internal override void CheckReference (XQueryASTCompiler compiler)
693 switchExpr.CheckReference (compiler);
694 foreach (CaseClause cc in caseList) {
695 compiler.CheckSchemaType (cc.Type);
696 cc.Expr.CheckReference (compiler);
698 defaultReturn.CheckReference (compiler);
701 #region CompileAndEvaluate
702 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
704 for (int i = 0; i < SwitchExpr.Count; i++)
705 SwitchExpr [i] = SwitchExpr [i].Compile (compiler);
706 foreach (CaseClause cc in Cases)
707 cc.Expr = cc.Expr.Compile (compiler);
708 DefaultReturn = DefaultReturn.Compile (compiler);
712 // FIXME: it can be optimized by checking all case clauses.
713 public override SequenceType StaticType {
714 get { return SequenceType.AnyType; }
717 public override XPathSequence Evaluate (XPathSequence iter)
719 // FIXME: should move to iterator?
720 XPathSequence cond = new ExprSequenceIterator (iter, SwitchExpr);
721 XPathSequence ret = null;
723 foreach (CaseClause ccc in Cases) {
724 if (ccc.Type.Matches (cond)) {
725 if (ccc.VarName != XmlQualifiedName.Empty)
726 iter.Context.PushVariable (ccc.VarName, cond);
727 ret = ccc.Expr.Evaluate (iter);
728 // FIXME: The design should make sure that in-scope variables are held on actual iteration.
729 if (ccc.VarName != XmlQualifiedName.Empty)
730 iter.Context.PopVariable ();
735 if (DefaultVarName != XmlQualifiedName.Empty)
736 iter.Context.PushVariable (DefaultVarName, cond);
737 ret = DefaultReturn.Evaluate (iter);
738 if (DefaultVarName != XmlQualifiedName.Empty)
739 iter.Context.PopVariable ();
745 internal class CaseClauseList : CollectionBase
747 public void Insert (int pos, CaseClause cc)
749 List.Insert (pos, cc);
752 public void Add (CaseClause cc)
757 public CaseClause this [int i] {
758 get { return (CaseClause) List [i]; }
762 internal class CaseClause
764 public CaseClause (SequenceType type, ExprSingle expr, XmlQualifiedName varName)
768 this.varName = varName;
773 XmlQualifiedName varName;
775 public SequenceType Type {
779 public ExprSingle Expr {
781 set { expr = value; }
784 public XmlQualifiedName VarName {
785 get { return varName; }
786 set { varName = value; }
792 internal class IfExpr : ExprSingle
794 public IfExpr (ExprSequence condition, ExprSingle trueExpr, ExprSingle falseExpr)
796 this.condition = new ParenthesizedExpr (condition);
797 this.trueExpr = trueExpr;
798 this.falseExpr = falseExpr;
801 ExprSingle condition;
803 ExprSingle falseExpr;
805 public ExprSingle Condition {
806 get { return condition; }
807 set { condition = value; }
810 public ExprSingle TrueExpr {
811 get { return trueExpr; }
812 set { trueExpr = value; }
815 public ExprSingle FalseExpr {
816 get { return falseExpr; }
817 set { falseExpr = value; }
820 internal override void CheckReference (XQueryASTCompiler compiler)
822 condition.CheckReference (compiler);
823 trueExpr.CheckReference (compiler);
824 falseExpr.CheckReference (compiler);
827 #region CompileAndEvaluate
828 SequenceType computedReturnType;
830 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
832 condition = condition.Compile (compiler);
833 // FIXME: check if condition is constant, and returns trueExpr or falseExpr
834 TrueExpr = TrueExpr.Compile (compiler);
835 FalseExpr = FalseExpr.Compile (compiler);
839 public override SequenceType StaticType {
842 return SequenceType.AnyType;
843 if (computedReturnType == null)
844 computedReturnType = SequenceType.ComputeCommonBase (TrueExpr.StaticType, FalseExpr.StaticType);
845 return computedReturnType;
849 public override XPathSequence Evaluate (XPathSequence iter)
851 if (condition.EvaluateAsBoolean (iter))
852 return TrueExpr.Evaluate (iter);
853 return FalseExpr.Evaluate (iter);
861 internal abstract class BinaryOperationExpr : ExprSingle
863 protected BinaryOperationExpr (ExprSingle left, ExprSingle right)
869 ExprSingle left, right;
871 public ExprSingle Left {
873 set { left = value; }
876 public ExprSingle Right{
877 get { return right; }
878 set { right = value; }
881 internal override void CheckReference (XQueryASTCompiler compiler)
883 left.CheckReference (compiler);
884 right.CheckReference (compiler);
887 #region CompileAndEvaluate
888 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
890 Left = Left.Compile (compiler);
891 Right = Right.Compile (compiler);
898 internal class OrExpr : BinaryOperationExpr
900 public OrExpr (ExprSingle left, ExprSingle right)
905 #region CompileAndEvaluate
906 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
908 base.CompileCore (compiler);
909 // FIXME: check constant value and return true or false
913 public override SequenceType StaticType {
914 get { return SequenceType.Boolean; }
917 public override bool EvaluateAsBoolean (XPathSequence iter)
919 return Left.EvaluateAsBoolean (iter) || Right.EvaluateAsBoolean (iter);
922 public override XPathSequence Evaluate (XPathSequence iter)
924 return new SingleItemIterator (EvaluateAsBoolean (iter) ?AtomicTrue : AtomicFalse, iter.Context);
929 return leftExprBool (context) || rightExprBool (context);
934 internal class AndExpr : BinaryOperationExpr
936 public AndExpr (ExprSingle left, ExprSingle right)
941 #region CompileAndEvaluate
942 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
944 base.CompileCore (compiler);
945 // FIXME: check constant value and return true or false
949 public override SequenceType StaticType {
950 get { return SequenceType.Boolean; }
953 public override bool EvaluateAsBoolean (XPathSequence iter)
955 return Left.EvaluateAsBoolean (iter) && Right.EvaluateAsBoolean (iter);
958 public override XPathSequence Evaluate (XPathSequence iter)
960 return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
965 return leftExprBool (context) && rightExprBool (context);
970 // TypeOperation expr
972 internal abstract class TypeOperationExpr : ExprSingle
974 protected TypeOperationExpr (ExprSingle expr, SequenceType type)
983 public ExprSingle Expr {
985 set { expr = value; }
988 public SequenceType TargetType {
992 internal override void CheckReference (XQueryASTCompiler compiler)
994 expr.CheckReference (compiler);
995 compiler.CheckSchemaType (type);
999 internal abstract class AtomicTypeOperationExpr : ExprSingle
1001 protected AtomicTypeOperationExpr (ExprSingle expr, XmlTypeCode type, bool optional)
1004 this.targetType = SequenceType.Create (type, optional ? Occurence.Optional : Occurence.One);
1008 SequenceType targetType;
1010 internal ExprSingle Expr {
1011 get { return expr; }
1012 set { expr = value; }
1016 public XmlTypeCode TypeCode {
1017 get { return typeCode; }
1020 public bool Optional {
1021 get { return optional; }
1024 internal SequenceType TargetType {
1025 get { return targetType; }
1028 internal override void CheckReference (XQueryASTCompiler compiler)
1030 expr.CheckReference (compiler);
1034 internal class InstanceOfExpr : TypeOperationExpr
1036 public InstanceOfExpr (ExprSingle expr, SequenceType type)
1041 #region CompileAndEvaluate
1042 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1044 Expr = Expr.Compile (compiler);
1045 // FIXME: check return type and if it never matches then return false
1049 public override SequenceType StaticType {
1050 get { return SequenceType.Boolean; }
1053 public override bool EvaluateAsBoolean (XPathSequence iter)
1055 bool occured = false;
1056 bool onlyOnce = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.Optional);
1057 bool required = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.OneOrMore);
1058 foreach (XPathItem item in iter) {
1059 if (occured && onlyOnce)
1061 if (!TargetType.IsInstance (item))
1064 return occured || !required;
1067 public override XPathSequence Evaluate (XPathSequence iter)
1069 return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
1074 internal class TreatExpr : TypeOperationExpr
1076 public TreatExpr (ExprSingle expr, SequenceType type)
1081 #region CompileAndEvaluate
1082 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1084 Expr = Expr.Compile (compiler);
1085 // FIXME: check return type and if it never matches then return false
1089 public override SequenceType StaticType {
1090 get { return SequenceType.AnyType; }
1093 public override XPathSequence Evaluate (XPathSequence iter)
1095 if (TargetType.CanConvert (iter))
1098 throw new XmlQueryException (String.Format ("Cannot treat as {1}", TargetType));
1103 internal class CastableExpr : AtomicTypeOperationExpr
1105 public CastableExpr (ExprSingle expr, XmlTypeCode atomicType, bool optional)
1106 : base (expr, atomicType, optional)
1110 #region CompileAndEvaluate
1111 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1113 Expr = Expr.Compile (compiler);
1114 // FIXME: check return type and if it never matches then return boolean
1118 public override SequenceType StaticType {
1119 get { return SequenceType.Boolean; }
1122 public override XPathSequence Evaluate (XPathSequence iter)
1124 return new SingleItemIterator (new XPathAtomicValue (EvaluateAsBoolean (iter), XmlSchemaSimpleType.XsBoolean), iter.Context);
1127 public override bool EvaluateAsBoolean (XPathSequence iter)
1129 bool occured = false;
1130 bool onlyOnce = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.Optional);
1131 bool required = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.OneOrMore);
1132 foreach (XPathItem item in iter) {
1133 if (occured && onlyOnce)
1135 if (!TargetType.CanConvert (item))
1138 return occured || !required;
1143 internal class CastExpr : AtomicTypeOperationExpr
1145 public CastExpr (ExprSingle expr, XmlTypeCode atomicType, bool optional)
1146 : base (expr, atomicType, optional)
1150 #region CompileAndEvaluate
1151 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1153 Expr = Expr.Compile (compiler);
1154 // FIXME: check return type and if it never matches then return boolean
1158 public override SequenceType StaticType {
1159 get { return TargetType; }
1162 public override XPathSequence Evaluate (XPathSequence iter)
1164 if (TargetType.CanConvert (iter))
1165 return new ConvertingIterator (iter, TargetType);
1167 throw new XmlQueryException (String.Format ("Cannot cast as {1}", TargetType));
1174 internal class ComparisonExpr : BinaryOperationExpr
1176 public ComparisonExpr (ExprSingle left, ExprSingle right, ComparisonOperator oper)
1177 : base (left, right)
1182 ComparisonOperator oper;
1184 public ComparisonOperator Operation {
1185 get { return oper; }
1188 #region CompileAndEvaluate
1189 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1191 Left = Left.Compile (compiler);
1192 Right = Right.Compile (compiler);
1193 // FIXME: check return type and if it never matches then return boolean
1197 public override SequenceType StaticType {
1198 get { return SequenceType.Boolean; }
1201 public override XPathSequence Evaluate (XPathSequence iter)
1204 bool result = EvaluateAsBoolean (iter, out isEmpty);
1206 return new XPathEmptySequence (iter.Context);
1207 return new SingleItemIterator (result ? AtomicTrue : AtomicFalse, iter.Context);
1210 public override bool EvaluateAsBoolean (XPathSequence iter)
1213 return EvaluateAsBoolean (iter, out isEmpty);
1216 private bool EvaluateAsBoolean (XPathSequence iter, out bool isEmpty)
1218 XPathSequence lseq, rseq;
1221 switch (Operation) {
1222 // FIXME: it is curious but currently gmcs requires full typename.
1223 case Mono.Xml.XPath2.ComparisonOperator.ValueEQ:
1224 case Mono.Xml.XPath2.ComparisonOperator.ValueNE:
1225 case Mono.Xml.XPath2.ComparisonOperator.ValueLT:
1226 case Mono.Xml.XPath2.ComparisonOperator.ValueLE:
1227 case Mono.Xml.XPath2.ComparisonOperator.ValueGT:
1228 case Mono.Xml.XPath2.ComparisonOperator.ValueGE:
1229 XPathItem itemVL = ExamineOneItem (Left.Evaluate (iter));
1230 XPathItem itemVR = ExamineOneItem (Right.Evaluate (iter));
1231 if (itemVL == null || itemVR == null) {
1235 return CompareAtomic (itemVL, itemVR);
1237 case Mono.Xml.XPath2.ComparisonOperator.GeneralEQ:
1238 case Mono.Xml.XPath2.ComparisonOperator.GeneralNE:
1239 case Mono.Xml.XPath2.ComparisonOperator.GeneralLT:
1240 case Mono.Xml.XPath2.ComparisonOperator.GeneralLE:
1241 case Mono.Xml.XPath2.ComparisonOperator.GeneralGT:
1242 case Mono.Xml.XPath2.ComparisonOperator.GeneralGE:
1243 lseq = Left.Evaluate (iter);
1244 rseq = Right.Evaluate (iter);
1245 foreach (XPathItem itemGL in lseq) {
1246 foreach (XPathItem itemGR in rseq.Clone ()) {
1247 if (CompareAtomic (itemGL, itemGR))
1253 case Mono.Xml.XPath2.ComparisonOperator.NodeIs:
1254 case Mono.Xml.XPath2.ComparisonOperator.NodeFWD:
1255 case Mono.Xml.XPath2.ComparisonOperator.NodeBWD:
1256 XPathNavigator lnav = ExamineOneNode (Left.Evaluate (iter));
1257 XPathNavigator rnav = ExamineOneNode (Right.Evaluate (iter));
1258 if (lnav == null || rnav == null) {
1262 switch (Operation) {
1263 case Mono.Xml.XPath2.ComparisonOperator.NodeIs:
1264 return lnav.IsSamePosition (rnav);
1265 case Mono.Xml.XPath2.ComparisonOperator.NodeFWD:
1266 return lnav.ComparePosition (rnav) == XmlNodeOrder.Before;
1267 case Mono.Xml.XPath2.ComparisonOperator.NodeBWD:
1268 return lnav.ComparePosition (rnav) == XmlNodeOrder.After;
1272 throw new SystemException ("XQuery internal error: should not happen.");
1275 // returns null if sequence was empty
1276 private XPathItem ExamineOneItem (XPathSequence seq)
1278 if (!seq.MoveNext ())
1280 XPathItem item = seq.Current;
1281 if (seq.MoveNext ())
1282 throw new XmlQueryException ("Operand of value comparison expression must be evaluated as a sequence that contains exactly one item.");
1286 // returns null if sequence was empty
1287 private XPathNavigator ExamineOneNode (XPathSequence seq)
1289 if (!seq.MoveNext ())
1291 XPathNavigator nav = seq.Current as XPathNavigator;
1292 if (nav == null || seq.MoveNext ())
1293 throw new XmlQueryException ("Operand of node comparison expression must be evaluated as a sequence that contains exactly one node.");
1297 private bool CompareAtomic (XPathItem itemL, XPathItem itemR)
1299 XmlSchemaSimpleType ua = XmlSchemaSimpleType.XdtUntypedAtomic;
1300 XmlSchemaSimpleType str = XmlSchemaSimpleType.XsString;
1301 // FIXME: XPathNavigator might be complex content.
1302 bool uaL = itemL.XmlType == null || itemL.XmlType == ua;
1303 bool uaR = itemR.XmlType == null || itemR.XmlType == ua;
1304 bool bothUA = uaL && uaR;
1305 XPathAtomicValue avL =
1307 bothUA ? new XPathAtomicValue (itemL.Value, str) :
1308 new XPathAtomicValue (itemL.Value, itemR.XmlType) :
1310 XPathAtomicValue avR =
1312 bothUA ? new XPathAtomicValue (itemR.Value, str) :
1313 new XPathAtomicValue (itemR.Value, itemL.XmlType) :
1316 switch (Operation) {
1317 // FIXME: it is curious but currently gmcs requires full typename.
1318 case Mono.Xml.XPath2.ComparisonOperator.ValueEQ:
1319 case Mono.Xml.XPath2.ComparisonOperator.GeneralEQ:
1320 return XQueryComparisonOperator.ValueEQ (avL, avR);
1321 case Mono.Xml.XPath2.ComparisonOperator.ValueNE:
1322 case Mono.Xml.XPath2.ComparisonOperator.GeneralNE:
1323 return XQueryComparisonOperator.ValueNE (avL, avR);
1324 case Mono.Xml.XPath2.ComparisonOperator.ValueLT:
1325 case Mono.Xml.XPath2.ComparisonOperator.GeneralLT:
1326 return XQueryComparisonOperator.ValueLT (avL, avR);
1327 case Mono.Xml.XPath2.ComparisonOperator.ValueLE:
1328 case Mono.Xml.XPath2.ComparisonOperator.GeneralLE:
1329 return XQueryComparisonOperator.ValueLE (avL, avR);
1330 case Mono.Xml.XPath2.ComparisonOperator.ValueGT:
1331 case Mono.Xml.XPath2.ComparisonOperator.GeneralGT:
1332 return XQueryComparisonOperator.ValueGT (avL, avR);
1333 case Mono.Xml.XPath2.ComparisonOperator.ValueGE:
1334 case Mono.Xml.XPath2.ComparisonOperator.GeneralGE:
1335 return XQueryComparisonOperator.ValueGE (avL, avR);
1337 return false; // should not happen
1342 public enum ComparisonOperator {
1362 internal class RangeExpr : BinaryOperationExpr
1364 public RangeExpr (ExprSingle left, ExprSingle right)
1365 : base (left, right)
1369 #region CompileAndEvaluate
1370 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1372 Left = Left.Compile (compiler);
1373 Right = Right.Compile (compiler);
1377 public override SequenceType StaticType {
1378 get { return SequenceType.IntegerList; }
1381 public override XPathSequence Evaluate (XPathSequence iter)
1383 int start = Left.EvaluateAsInt (iter);
1384 int end = Right.EvaluateAsInt (iter);
1385 return new IntegerRangeIterator (iter.Context, start, end);
1388 public override void Serialize (XPathSequence iter)
1390 int start = Left.EvaluateAsInt (iter);
1391 int end = Right.EvaluateAsInt (iter);
1392 for (int i = start; i <= end; i++) {
1393 iter.Context.Writer.WriteValue (i);
1395 iter.Context.Writer.WriteWhitespace (" ");
1401 // arithmetic operation expr
1403 public enum ArithmeticOperator {
1412 internal class ArithmeticOperationExpr : BinaryOperationExpr
1414 public ArithmeticOperationExpr (ExprSingle left, ExprSingle right, ArithmeticOperator oper)
1415 : base (left, right)
1420 ArithmeticOperator oper;
1422 public ArithmeticOperator Operation {
1423 get { return oper; }
1426 #region CompileAndEvaluate
1427 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1429 Left = Left.Compile (compiler);
1430 Right = Right.Compile (compiler);
1434 // FIXME: It can be optimized by comparing l/r value types.
1435 public override SequenceType StaticType {
1436 get { return SequenceType.AnyType; }
1439 public override XPathSequence Evaluate (XPathSequence iter)
1441 XPathSequence lseq = Left.Evaluate (iter);
1442 if (!lseq.MoveNext ())
1443 return new XPathEmptySequence (iter.Context);
1444 XPathSequence rseq = Right.Evaluate (iter);
1445 if (!rseq.MoveNext ())
1446 return new XPathEmptySequence (iter.Context);
1447 XPathAtomicValue lvalue = Atomize (lseq.Current);
1448 XPathAtomicValue rvalue = Atomize (rseq.Current);
1449 if (lseq.MoveNext ())
1450 throw new XmlQueryException ("XP0006: Left operand resulted in an sequence that contains more than one item.");
1451 if (rseq.MoveNext ())
1452 throw new XmlQueryException ("XP0006: Left operand resulted in an sequence that contains more than one item.");
1454 // FIXME: handle "untypedAtomic to xs:double" casting
1456 return new SingleItemIterator (Compute (lvalue, rvalue), iter.Context);
1459 private XPathAtomicValue Compute (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
1461 switch (Operation) {
1462 case ArithmeticOperator.Add:
1463 return XQueryArithmeticOperator.Add (lvalue, rvalue);
1464 case ArithmeticOperator.Sub:
1465 return XQueryArithmeticOperator.Subtract (lvalue, rvalue);
1466 case ArithmeticOperator.Mul:
1467 return XQueryArithmeticOperator.Multiply (lvalue, rvalue);
1468 case ArithmeticOperator.Div:
1469 return XQueryArithmeticOperator.Divide (lvalue, rvalue);
1470 case ArithmeticOperator.IDiv:
1471 return XQueryArithmeticOperator.IntDivide (lvalue, rvalue);
1472 case ArithmeticOperator.IMod:
1473 return XQueryArithmeticOperator.Remainder (lvalue, rvalue);
1475 throw new SystemException ("XQuery internal error: should not happen.");
1481 internal class MinusExpr : ExprSingle
1483 public MinusExpr (ExprSingle expr)
1490 public ExprSingle Expr {
1491 get { return expr; }
1492 set { expr = value; }
1495 internal override void CheckReference (XQueryASTCompiler compiler)
1497 expr.CheckReference (compiler);
1500 #region CompileAndEvaluate
1501 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1503 return new ArithmeticOperationExpr (new DecimalLiteralExpr (-1), Expr, ArithmeticOperator.Mul).Compile (compiler);
1506 public override SequenceType StaticType {
1507 get { return Expr.StaticType; }
1510 public override XPathSequence Evaluate (XPathSequence iter)
1512 throw new SystemException ("XQuery internal error: should not happen.");
1519 public enum AggregationType {
1525 internal class GroupExpr : BinaryOperationExpr
1527 public GroupExpr (ExprSingle left, ExprSingle right, AggregationType aggrType)
1528 : base (left, right)
1530 this.aggrType = aggrType;
1533 AggregationType aggrType;
1535 public AggregationType AggregationType {
1536 get { return aggrType; }
1539 #region CompileAndEvaluate
1540 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1542 Left = Left.Compile (compiler);
1543 Right = Right.Compile (compiler);
1547 // FIXME: It can be optimized by comparing l/r value types.
1548 public override SequenceType StaticType {
1549 get { return SequenceType.AnyType; }
1552 // only applicable against node-sets
1553 public override XPathSequence Evaluate (XPathSequence iter)
1555 return new GroupIterator (iter, this);
1562 internal class ValidateExpr : ExprSingle
1564 XmlSchemaContentProcessing schemaMode;
1567 public ValidateExpr (XmlSchemaContentProcessing schemaMode, ExprSequence expr)
1569 this.schemaMode = schemaMode;
1573 public ExprSequence Expr {
1574 get { return expr; }
1577 public XmlSchemaContentProcessing SchemaMode {
1578 get { return schemaMode; }
1581 internal override void CheckReference (XQueryASTCompiler compiler)
1583 expr.CheckReference (compiler);
1586 #region CompileAndEvaluate
1587 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1589 for (int i = 0; i < expr.Count; i++)
1590 expr [i] = expr [i].Compile (compiler);
1594 public override SequenceType StaticType {
1595 get { return SequenceType.AnyType; }
1598 public override XPathSequence Evaluate (XPathSequence iter)
1601 throw new NotImplementedException ();
1608 internal abstract class PathExpr : ExprSingle
1613 internal class PathRootExpr : PathExpr
1615 public PathRootExpr ()
1619 internal override void CheckReference (XQueryASTCompiler compiler)
1623 #region CompileAndEvaluate
1624 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1629 public override SequenceType StaticType {
1630 get { return SequenceType.Document; }
1633 public override XPathSequence Evaluate (XPathSequence iter)
1635 XPathNavigator nav = iter.Context.CurrentItem as XPathNavigator;
1637 throw new XmlQueryException ("Context item is not a node when evaluating expression '/'.");
1640 return new SingleItemIterator (nav, iter.Context);
1645 internal abstract class PathStepExpr : PathExpr
1650 public PathStepExpr (ExprSingle first, ExprSingle next)
1656 public ExprSingle First {
1657 get { return first; }
1658 set { first = value; }
1661 public ExprSingle Next {
1662 get { return next; }
1663 set { next = value; }
1666 internal override void CheckReference (XQueryASTCompiler compiler)
1668 first.CheckReference (compiler);
1669 next.CheckReference (compiler);
1672 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1674 first = first.Compile (compiler);
1675 next = next.Compile (compiler);
1682 internal class PathSlashExpr : PathStepExpr
1684 public PathSlashExpr (ExprSingle first, ExprSingle next)
1685 : base (first, next)
1689 #region CompileAndEvaluate
1690 // FIXME: It can be optimized by comparing l/r value types.
1691 public override SequenceType StaticType {
1692 get { return SequenceType.Node; }
1695 public override XPathSequence Evaluate (XPathSequence iter)
1697 return new PathStepIterator (First.Evaluate (iter), this);
1703 internal class PathSlash2Expr : PathStepExpr
1705 public PathSlash2Expr (ExprSingle first, ExprSingle next)
1706 : base (first, next)
1710 #region CompileAndEvaluate
1711 // FIXME: It can be optimized by comparing l/r value types.
1712 public override SequenceType StaticType {
1713 get { return SequenceType.Node; }
1716 public override XPathSequence Evaluate (XPathSequence iter)
1718 XPathSequence seq = First.Evaluate (iter);
1719 if (!seq.MoveNext ())
1720 return new XPathEmptySequence (iter.Context);
1721 return new PathStepIterator (
1722 new DescendantOrSelfIterator (seq.Current as XPathNavigator, seq.Context), this);
1727 internal class AxisStepExpr : PathExpr
1729 public AxisStepExpr (XPathAxis axis, XPath2NodeTest test)
1733 nameTest = XmlQualifiedName.Empty;
1735 if (test.NameTest != null)
1736 this.nameTest = test.NameTest;
1738 this.kindTest = test.KindTest;
1743 XmlQualifiedName nameTest;
1746 public XPathAxis Axis {
1747 get { return axis; }
1750 public XmlQualifiedName NameTest {
1751 get { return nameTest; }
1752 set { nameTest = value; }
1755 public KindTest KindTest {
1756 get { return kindTest; }
1757 set { kindTest = value; }
1760 internal override void CheckReference (XQueryASTCompiler compiler)
1762 if (KindTest != null)
1763 KindTest.CheckReference (compiler);
1766 #region CompileAndEvaluate
1767 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1769 if (KindTest != null)
1770 KindTest.Compile (compiler);
1774 public override SequenceType StaticType {
1776 switch (Axis.AxisType) {
1777 case XPathAxisType.Attribute:
1778 return SequenceType.Attribute;
1779 case XPathAxisType.Namespace:
1780 return SequenceType.Namespace;
1782 // FIXME: we can more filtering by KindTest
1783 return SequenceType.Node;
1787 public override XPathSequence Evaluate (XPathSequence iter)
1789 XQueryContext ctx = iter.Context;
1791 if (iter.Position == 0) {
1792 iter = iter.Clone ();
1793 if (!iter.MoveNext ())
1794 return new XPathEmptySequence (iter.Context);
1797 XPathNavigator nav = iter.Current as XPathNavigator;
1799 throw new XmlQueryException ("Node set is expected.");
1801 NodeIterator argIter = null;
1803 switch (Axis.AxisType) {
1804 case XPathAxisType.Child:
1805 argIter = new ChildIterator (nav, ctx); break;
1806 case XPathAxisType.Descendant:
1807 argIter = new DescendantIterator (nav, ctx); break;
1808 case XPathAxisType.Attribute:
1809 argIter = new AttributeIterator (nav, ctx); break;
1810 case XPathAxisType.Self:
1811 argIter = new SelfIterator (nav, ctx); break;
1812 case XPathAxisType.DescendantOrSelf:
1813 argIter = new DescendantOrSelfIterator (nav, ctx); break;
1814 case XPathAxisType.FollowingSibling:
1815 argIter = new FollowingSiblingIterator (nav, ctx); break;
1816 case XPathAxisType.Following:
1817 argIter = new FollowingIterator (nav, ctx); break;
1818 case XPathAxisType.Parent:
1819 argIter = new ParentIterator (nav, ctx); break;
1820 case XPathAxisType.Ancestor:
1821 argIter = new AncestorIterator (nav, ctx); break;
1822 case XPathAxisType.PrecedingSibling:
1823 argIter = new PrecedingSiblingIterator (nav, ctx); break;
1824 case XPathAxisType.Preceding:
1825 argIter = new PrecedingIterator (nav, ctx); break;
1826 case XPathAxisType.AncestorOrSelf:
1827 argIter = new AncestorOrSelfIterator (nav, ctx); break;
1828 case XPathAxisType.Namespace: // only applicable under XPath 2.0: not XQuery 1.0
1829 argIter = new NamespaceIterator (nav, ctx); break;
1831 return new AxisIterator (argIter, this);
1834 internal bool Matches (XPathNavigator nav)
1836 if (nameTest != null)
1837 return nameTest == XmlQualifiedName.Empty ||
1838 ((nameTest.Name == nav.LocalName || nameTest.Name == "*") &&
1839 (nameTest.Namespace == nav.NamespaceURI || nameTest.Namespace == "*"));
1841 return kindTest.Matches (nav);
1846 internal class FilterStepExpr : PathExpr
1848 public FilterStepExpr (ExprSingle expr, ExprSequence predicate)
1851 this.predicate = predicate;
1855 ExprSequence predicate;
1857 public ExprSingle Expr {
1858 get { return expr; }
1859 set { expr = value; }
1862 public ExprSequence Predicate {
1863 get { return predicate; }
1866 internal override void CheckReference (XQueryASTCompiler compiler)
1868 expr.CheckReference (compiler);
1869 predicate.CheckReference (compiler);
1872 #region CompileAndEvaluate
1873 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1875 Expr = Expr.Compile (compiler);
1876 for (int i = 0; i < predicate.Count; i++)
1877 predicate [i] = predicate [i].Compile (compiler);
1881 public override SequenceType StaticType {
1882 get { return Expr.StaticType; }
1885 public override XPathSequence Evaluate (XPathSequence iter)
1887 return new FilteredIterator (iter, this);
1893 // predicates == exprsequence list == list of list of exprsingle
1894 internal class PredicateList : CollectionBase
1896 public void Add (ExprSequence expr)
1901 public void Insert (int pos, ExprSequence expr)
1903 List.Insert (pos, expr);
1906 public ExprSequence this [int i] {
1907 get { return (ExprSequence) List [i]; }
1912 internal class XPath2NodeTest
1914 public XPath2NodeTest (XmlQualifiedName nameTest)
1916 this.NameTest = nameTest;
1919 public XPath2NodeTest (KindTest kindTest)
1921 this.KindTest = kindTest;
1924 public XmlQualifiedName NameTest;
1926 public KindTest KindTest;
1929 internal class EnclosedExpr : ExprSingle
1933 public EnclosedExpr (ExprSequence expr)
1938 public ExprSequence Expr {
1939 get { return expr; }
1942 internal override void CheckReference (XQueryASTCompiler compiler)
1944 expr.CheckReference (compiler);
1947 #region CompileAndEvaluate
1948 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1950 if (Expr.Count == 1)
1951 return Expr [0].Compile (compiler);
1952 for (int i = 0; i < Expr.Count; i++)
1953 Expr [i] = Expr [i].Compile (compiler);
1957 // FIXME: can be optimized by checking all items in Expr
1958 public override SequenceType StaticType {
1959 get { return SequenceType.AnyType; }
1962 public override XPathSequence Evaluate (XPathSequence iter)
1964 return new ExprSequenceIterator (iter, Expr);
1971 internal abstract class PrimaryExpr : ExprSingle
1973 internal override void CheckReference (XQueryASTCompiler compiler)
1977 #region CompileAndEvaluate
1978 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
1983 public override XPathSequence Evaluate (XPathSequence iter)
1985 return new SingleItemIterator (EvaluateAsAtomic (iter), iter.Context);
1990 internal class StringLiteralExpr : PrimaryExpr
1994 public StringLiteralExpr (string literal)
1996 this.literal = literal;
1999 public string Literal {
2000 get { return literal; }
2003 #region CompileAndEvaluate
2004 XmlSchemaSimpleType stringType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("string", XmlSchema.Namespace));
2006 public override SequenceType StaticType {
2007 get { return SequenceType.AtomicString; }
2010 public override string EvaluateAsString (XPathSequence iter)
2015 public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
2017 return new XPathAtomicValue (Literal, stringType);
2022 internal class DecimalLiteralExpr : PrimaryExpr
2026 public DecimalLiteralExpr (decimal value)
2031 public decimal Value {
2032 get { return value; }
2035 #region CompileAndEvaluate
2036 XmlSchemaSimpleType decimalType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("decimal", XmlSchema.Namespace));
2038 public override SequenceType StaticType {
2039 get { return SequenceType.Decimal; }
2042 public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
2044 return new XPathAtomicValue (Value, decimalType);
2049 internal class DoubleLiteralExpr : PrimaryExpr
2053 public DoubleLiteralExpr (double value)
2058 public double Value {
2059 get { return value; }
2062 #region CompileAndEvaluate
2063 XmlSchemaSimpleType doubleType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("double", XmlSchema.Namespace));
2065 public override SequenceType StaticType {
2066 get { return SequenceType.Double; }
2069 public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
2071 return new XPathAtomicValue (Value, doubleType);
2076 internal class VariableReferenceExpr : PrimaryExpr
2078 XmlQualifiedName varName;
2080 public VariableReferenceExpr (XmlQualifiedName varName)
2082 this.varName = varName;
2085 public XmlQualifiedName VariableName {
2086 get { return varName; }
2089 // FIXME: variable name must be stacked in any area
2090 // whereever variables are defined.
2091 internal override void CheckReference (XQueryASTCompiler compiler)
2093 compiler.CheckVariableName (varName);
2096 #region CompileAndEvaluate
2097 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2099 // FIXME: try to resolve static context variable and return the actual value expression
2103 public override SequenceType StaticType {
2104 get { return SequenceType.AnyType; }
2107 public override XPathSequence Evaluate (XPathSequence iter)
2109 XPathSequence variable = iter.Context.ResolveVariable (VariableName);
2110 // FIXME: if Evaluate() accepts XPathSequence, then XPathSequence must be public class (to make IXPath2Variable public).
2116 internal class ParenthesizedExpr : PrimaryExpr
2120 public ParenthesizedExpr (ExprSequence expr)
2123 expr = new ExprSequence ();
2128 get { return expr; }
2131 #region CompileAndEvaluate
2132 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2134 if (Expr.Count == 1)
2135 return Expr [0].Compile (compiler);
2136 for (int i = 0; i < Expr.Count; i++)
2137 Expr [i] = Expr [i].Compile (compiler);
2141 // FIXME: can be optimized by checking all items in Expr
2142 public override SequenceType StaticType {
2143 get { return SequenceType.AnyType; }
2146 public override XPathSequence Evaluate (XPathSequence iter)
2148 switch (Expr.Count) {
2150 return new XPathEmptySequence (iter.Context);
2152 return Expr [0].Evaluate (iter);
2154 return new ExprSequenceIterator (iter, Expr);
2161 internal class ContextItemExpr : PrimaryExpr
2163 public ContextItemExpr ()
2167 #region CompileAndEvaluate
2168 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2173 public override SequenceType StaticType {
2174 get { return SequenceType.AnyType; }
2177 public override XPathSequence Evaluate (XPathSequence iter)
2179 return new SingleItemIterator (iter.Context.CurrentItem, iter.Context);
2184 internal abstract class FunctionCallExprBase : PrimaryExpr
2186 XmlQualifiedName name;
2189 public FunctionCallExprBase (XmlQualifiedName name, ExprSequence args)
2192 throw new ArgumentNullException (String.Format ("Function argument expressions for {0} is null.", name));
2197 public XmlQualifiedName Name {
2198 get { return name; }
2201 public ExprSequence Args {
2202 get { return args; }
2205 internal override void CheckReference (XQueryASTCompiler compiler)
2207 compiler.CheckFunctionName (name);
2210 #region CompileAndEvaluate
2212 internal static DefaultFunctionCall Create (
2213 XmlQualifiedName name,
2215 XQueryStaticContext ctx)
2217 switch (name.Namespace) {
2218 case XQueryFunction.Namespace:
2219 switch (name.Name) {
2221 return new FnNodeNameCall (ctx, args);
2223 return new FnNilledCall (ctx, args);
2225 return new FnStringCall (ctx, args);
2227 return new FnDataCall (ctx, args);
2229 return new FnBaseUriCall (ctx, args);
2230 case "document-uri":
2231 return new FnDocumentUriCall (ctx, args);
2233 return new FnErrorCall (ctx, args);
2235 return new FnTraceCall (ctx, args);
2237 return new FnAbsCall (ctx, args);
2239 return new FnCeilingCall (ctx, args);
2241 return new FnFloorCall (ctx, args);
2243 return new FnRoundCall (ctx, args);
2244 case "round-half-to-even":
2245 return new FnRoundHalfToEvenCall (ctx, args);
2246 case "codepoints-to-string":
2247 return new FnCodepointsToStringCall (ctx, args);
2248 case "string-to-codepoints":
2249 return new FnStringCallToCodepointsCall (ctx, args);
2252 case XmlSchema.XdtNamespace:
2253 case XmlSchema.Namespace:
2254 XmlSchemaType type = XmlSchemaType.GetBuiltInSimpleType (name);
2256 return new AtomicConstructorCall (ctx, SequenceType.Create (type, Occurence.One), args);
2257 type = XmlSchemaType.GetBuiltInComplexType (name);
2262 XQueryFunction func = ctx.CompileContext.InEffectFunctions [name];
2264 return new CustomFunctionCallExpression (ctx, args, func);
2270 internal void CheckArguments (XQueryASTCompiler compiler)
2272 if (args.Count < MinArgs || args.Count > MaxArgs)
2273 // FIXME: add more info
2274 throw new XmlQueryCompileException (String.Format ("{0} is invalid for the number of {1} function argument. MinArgs = {2}, MaxArgs = {3}.", args.Count, name, MinArgs, MaxArgs));
2277 public abstract int MinArgs { get; }
2278 public abstract int MaxArgs { get; }
2282 internal class FunctionCallExpr : FunctionCallExprBase
2284 public FunctionCallExpr (XmlQualifiedName name, ExprSequence args)
2289 XQueryFunction function;
2291 public XQueryFunction Function {
2292 get { return function; }
2295 #region CompileAndEvaluate
2296 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2299 function = compiler.ResolveFunction (Name);
2300 CheckArguments (compiler);
2301 for (int i = 0; i < Args.Count; i++)
2302 Args [i] = Args [i].Compile (compiler);
2306 public override int MinArgs {
2307 get { return function.MinArgs; }
2310 public override int MaxArgs {
2311 get { return function.MaxArgs; }
2314 public override SequenceType StaticType {
2315 get { return function.ReturnType; }
2318 public override XPathSequence Evaluate (XPathSequence iter)
2320 return Function.Evaluate (iter, Args);
2323 // FIXME: add all overrides that delegates to XQueryFunction
2328 #region CompileAndEvaluate
2330 // It is instantiated per function call expression.
2331 // (e.g. the example below contains 4 FunctionCallExpression instances:
2332 // "replace(node-name (node-before(/*)), 'foo', node-name($var))"
2333 internal class CustomFunctionCallExpr : FunctionCallExprBase
2335 public CustomFunctionCallExpr (ExprSequence args, XQueryFunction function)
2336 : base (function.Name, args)
2338 this.function = function;
2341 XQueryFunction function;
2343 public XQueryFunction Function {
2344 get { return function; }
2347 public override int MinArgs {
2348 get { return function.MinArgs; }
2351 public override int MaxArgs {
2352 get { return function.MaxArgs; }
2355 public override SequenceType StaticType {
2356 get { return function.ReturnType; }
2359 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2361 CheckArguments (compiler);
2362 for (int i = 0; i < Args.Count; i++)
2363 Args [i] = Args [i].Compile (compiler);
2367 public override XPathSequence Evaluate (XPathSequence iter)
2369 return Function.Evaluate (iter, Args);
2372 // FIXME: add all overrides that delegates to XQueryFunction
2377 // Ordered / Unordered
2378 internal class OrderSpecifiedExpr : ExprSingle
2383 public OrderSpecifiedExpr (ExprSequence expr, bool ordered)
2385 this.ordered = ordered;
2389 public ExprSequence Expr {
2390 get { return expr; }
2393 public bool Ordered {
2394 get { return ordered; }
2397 internal override void CheckReference (XQueryASTCompiler compiler)
2399 expr.CheckReference (compiler);
2402 #region CompileAndEvaluate
2403 public override SequenceType StaticType {
2404 // FIXME: could be optimized by checking all the expressions
2405 get { return SequenceType.AnyType; }
2408 public override bool RequireSorting {
2409 get { return Ordered; }
2412 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
2414 for (int i = 0; i < Expr.Count; i++)
2415 Expr [i] = Expr [i].Compile (compiler);
2419 public override XPathSequence Evaluate (XPathSequence iter)
2421 throw new NotImplementedException ();