Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / QIL / QilPatternFactory.cs
blob28cdbe3359d36d2e897c2dbf6c2be5a3731a6806
1 //------------------------------------------------------------------------------
2 // <copyright file="QilPatternFactory.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Collections.Generic;
9 using System.Diagnostics;
10 using System.Reflection;
11 using System.Xml.Schema;
13 namespace System.Xml.Xsl.Qil {
15 /// <summary>
16 /// Additional factory methods for constructing common QIL patterns.
17 /// </summary>
18 /// <remarks>
19 /// Some of the methods here are exactly like the ones in QilFactory except
20 /// that they perform constant-folding and other normalization. Others are
21 /// "macro patterns" that simplify the task of constructing otherwise complex patterns.
22 /// </remarks>
23 internal class QilPatternFactory {
24 private bool debug;
25 private QilFactory f;
27 public QilPatternFactory(QilFactory f, bool debug) {
28 Debug.Assert(f != null);
29 this.f = f;
30 this.debug = debug;
33 public QilFactory BaseFactory { get { return f; } }
34 public bool IsDebug { get { return this.debug; } }
36 #region Convenience methods
38 public QilLiteral String(string val) {
39 return f.LiteralString(val);
42 public QilLiteral Int32(int val) {
43 return f.LiteralInt32(val);
46 public QilLiteral Double(double val) {
47 return f.LiteralDouble(val);
50 public QilName QName(string local, string uri, string prefix) {
51 return f.LiteralQName(local, uri, prefix);
54 public QilName QName(string local, string uri) {
55 return f.LiteralQName(local, uri, System.String.Empty);
58 public QilName QName(string local) {
59 return f.LiteralQName(local, System.String.Empty, System.String.Empty);
62 public QilNode Unknown(XmlQueryType t) {
63 return f.Unknown(t);
65 #endregion
67 #region meta
68 //-----------------------------------------------
69 // meta
70 //-----------------------------------------------
71 public QilExpression QilExpression(QilNode root, QilFactory factory) {
72 return f.QilExpression(root, factory);
75 public QilList FunctionList() {
76 return f.FunctionList();
79 public QilList GlobalVariableList() {
80 return f.GlobalVariableList();
83 public QilList GlobalParameterList() {
84 return f.GlobalParameterList();
87 public QilList ActualParameterList() {
88 return f.ActualParameterList();
91 public QilList ActualParameterList(QilNode arg1) {
92 QilList result = f.ActualParameterList();
93 result.Add(arg1);
94 return result;
97 public QilList ActualParameterList(QilNode arg1, QilNode arg2) {
98 QilList result = f.ActualParameterList();
99 result.Add(arg1);
100 result.Add(arg2);
101 return result;
104 public QilList ActualParameterList(params QilNode[] args) {
105 return f.ActualParameterList(args);
108 public QilList FormalParameterList() {
109 return f.FormalParameterList();
112 public QilList FormalParameterList(QilNode arg1) {
113 QilList result = f.FormalParameterList();
114 result.Add(arg1);
115 return result;
118 public QilList FormalParameterList(QilNode arg1, QilNode arg2) {
119 QilList result = f.FormalParameterList();
120 result.Add(arg1);
121 result.Add(arg2);
122 return result;
125 public QilList FormalParameterList(params QilNode[] args) {
126 return f.FormalParameterList(args);
129 public QilList SortKeyList() {
130 return f.SortKeyList();
133 public QilList SortKeyList(QilSortKey key) {
134 QilList list = f.SortKeyList();
135 list.Add(key);
136 return list;
139 public QilList BranchList(params QilNode[] args) {
140 return f.BranchList(args);
143 public QilNode OptimizeBarrier(QilNode child) {
144 return f.OptimizeBarrier(child);
147 #endregion // meta
149 #region specials
150 //-----------------------------------------------
151 // specials
152 //-----------------------------------------------
153 public QilNode DataSource(QilNode name, QilNode baseUri) {
154 return f.DataSource(name, baseUri);
157 public QilNode Nop(QilNode child) {
158 return f.Nop(child);
161 public QilNode Error(QilNode text) {
162 return f.Error(text);
165 public QilNode Warning(QilNode text) {
166 return f.Warning(text);
169 #endregion // specials
171 #region variables
172 //-----------------------------------------------
173 // variables
174 //-----------------------------------------------
175 public QilIterator For(QilNode binding) {
176 return f.For(binding);
179 public QilIterator Let(QilNode binding) {
180 return f.Let(binding);
183 public QilParameter Parameter(XmlQueryType t) {
184 return f.Parameter(t);
187 public QilParameter Parameter(QilNode defaultValue, QilName name, XmlQueryType t) {
188 return f.Parameter(defaultValue, name, t);
191 public QilNode PositionOf(QilIterator expr) {
192 return f.PositionOf(expr);
195 #endregion // variables
197 #region literals
198 //-----------------------------------------------
199 // literals
200 //-----------------------------------------------
201 public QilNode True() {
202 return f.True();
205 public QilNode False() {
206 return f.False();
209 public QilNode Boolean(bool b) {
210 return b ? this.True() : this.False();
213 #endregion // literals
215 #region boolean operators
216 //-----------------------------------------------
217 // boolean operators
218 //-----------------------------------------------
220 // ToDo: Why we have nulls here at all?
221 private static void CheckLogicArg(QilNode arg) {
222 Debug.Assert(arg != null, "Argulent shouldn't be null");
223 Debug.Assert(arg.XmlType.TypeCode == XmlTypeCode.Boolean && arg.XmlType.IsSingleton,
224 "The operand must be boolean-typed"
228 public QilNode And(QilNode left, QilNode right) {
229 CheckLogicArg(left);
230 CheckLogicArg(right);
232 if (! debug) {
233 // True, True => True (right) other, True => other (left)
234 // True, False => False (right) other, False => False (right)
235 // True, other => other (right) other, other => And
236 if (left.NodeType == QilNodeType.True || right.NodeType == QilNodeType.False) {
237 return right;
239 if (left.NodeType == QilNodeType.False || right.NodeType == QilNodeType.True) {
240 return left;
243 return f.And(left, right);
246 public QilNode Or(QilNode left, QilNode right) {
247 CheckLogicArg(left);
248 CheckLogicArg(right);
250 if (! debug) {
251 // True, True => True (left) other, True => True (right)
252 // True, False => True (left) other, False => other (left)
253 // True, other => True (left) other, other => Or
254 if (left.NodeType == QilNodeType.True || right.NodeType == QilNodeType.False) {
255 return left;
257 if (left.NodeType == QilNodeType.False || right.NodeType == QilNodeType.True) {
258 return right;
261 return f.Or(left, right);
264 public QilNode Not(QilNode child) {
265 if (! debug) {
266 switch (child.NodeType) {
267 case QilNodeType.True:
268 return f.False();
269 case QilNodeType.False:
270 return f.True();
271 case QilNodeType.Not:
272 return ((QilUnary) child).Child;
275 return f.Not(child);
278 #endregion // boolean operators
280 #region choice
281 //-----------------------------------------------
282 // choice
283 //-----------------------------------------------
285 public QilNode Conditional(QilNode condition, QilNode trueBranch, QilNode falseBranch) {
286 if (! debug) {
287 switch (condition.NodeType) {
288 case QilNodeType.True:
289 return trueBranch;
290 case QilNodeType.False:
291 return falseBranch;
292 case QilNodeType.Not:
293 return this.Conditional(((QilUnary)condition).Child, falseBranch, trueBranch);
296 return f.Conditional(condition, trueBranch, falseBranch);
299 public QilNode Choice(QilNode expr, QilList branches) {
300 if (! debug) {
301 switch (branches.Count) {
302 case 1:
303 // If expr has no side effects, it will be eliminated by optimizer
304 return f.Loop(f.Let(expr), branches[0]);
305 case 2:
306 return f.Conditional(f.Eq(expr, f.LiteralInt32(0)), branches[0], branches[1]);
309 return f.Choice(expr, branches);
312 #endregion // choice
314 #region collection operators
315 //-----------------------------------------------
316 // collection operators
317 //-----------------------------------------------
318 public QilNode Length(QilNode child) {
319 return f.Length(child);
322 public QilNode Sequence() {
323 return f.Sequence();
326 public QilNode Sequence(QilNode child) {
327 if (! debug) {
328 return child;
330 QilList res = f.Sequence();
331 res.Add(child);
332 return res;
335 public QilNode Sequence(QilNode child1, QilNode child2) {
336 QilList res = f.Sequence();
337 res.Add(child1);
338 res.Add(child2);
339 return res;
342 public QilNode Sequence(params QilNode[] args) {
343 if (! debug) {
344 switch(args.Length) {
345 case 0 : return f.Sequence();
346 case 1 : return args[0];
349 QilList res = f.Sequence();
350 foreach (QilNode n in args)
351 res.Add(n);
352 return res;
355 public QilNode Union(QilNode left, QilNode right) {
356 return f.Union(left, right);
359 public QilNode Sum(QilNode collection) {
360 return f.Sum(collection);
362 #endregion // collection operators
364 #region arithmetic operators
365 //-----------------------------------------------
366 // arithmetic operators
367 //-----------------------------------------------
368 public QilNode Negate(QilNode child) {
369 return f.Negate(child);
372 public QilNode Add(QilNode left, QilNode right) {
373 return f.Add(left, right);
376 public QilNode Subtract(QilNode left, QilNode right) {
377 return f.Subtract(left, right);
380 public QilNode Multiply(QilNode left, QilNode right) {
381 return f.Multiply(left, right);
384 public QilNode Divide(QilNode left, QilNode right) {
385 return f.Divide(left, right);
388 public QilNode Modulo(QilNode left, QilNode right) {
389 return f.Modulo(left, right);
392 #endregion // arithmetic operators
394 #region string operators
395 //-----------------------------------------------
396 // string operators
397 //-----------------------------------------------
398 public QilNode StrLength(QilNode str) {
399 return f.StrLength(str);
402 public QilNode StrConcat(QilNode values) {
403 if (! debug) {
404 if (values.XmlType.IsSingleton)
405 return values;
407 return f.StrConcat(values);
410 public QilNode StrConcat(params QilNode[] args) {
411 return StrConcat((IList<QilNode>)args);
414 public QilNode StrConcat(IList<QilNode> args) {
415 if (! debug) {
416 switch(args.Count) {
417 case 0 :
418 return f.LiteralString(string.Empty);
419 case 1 :
420 return StrConcat(args[0]);
423 return StrConcat(f.Sequence(args));
426 public QilNode StrParseQName(QilNode str, QilNode ns) {
427 return f.StrParseQName(str, ns);
429 #endregion // string operators
431 #region value comparison operators
432 //-----------------------------------------------
433 // value comparison operators
434 //-----------------------------------------------
435 public QilNode Ne(QilNode left, QilNode right) {
436 return f.Ne(left, right);
439 public QilNode Eq(QilNode left, QilNode right) {
440 return f.Eq(left, right);
443 public QilNode Gt(QilNode left, QilNode right) {
444 return f.Gt(left, right);
447 public QilNode Ge(QilNode left, QilNode right) {
448 return f.Ge(left, right);
451 public QilNode Lt(QilNode left, QilNode right) {
452 return f.Lt(left, right);
455 public QilNode Le(QilNode left, QilNode right) {
456 return f.Le(left, right);
459 #endregion // value comparison operators
461 #region node comparison operators
462 //-----------------------------------------------
463 // node comparison operators
464 //-----------------------------------------------
465 public QilNode Is(QilNode left, QilNode right) {
466 return f.Is(left, right);
469 public QilNode After(QilNode left, QilNode right) {
470 return f.After(left, right);
473 public QilNode Before(QilNode left, QilNode right) {
474 return f.Before(left, right);
477 #endregion // node comparison operators
479 #region loops
480 //-----------------------------------------------
481 // loops
482 //-----------------------------------------------
483 public QilNode Loop(QilIterator variable, QilNode body) {
484 if (! debug) {
485 //((Loop (For $Binding) ($Binding) ) => ($binding))
486 if (body == variable.Binding) {
487 return body;
490 return f.Loop(variable, body);
493 public QilNode Filter(QilIterator variable, QilNode expr) {
494 if (! debug) {
495 //((Filter (For $Binding) (True ) ) => ($binding))
496 if (expr.NodeType == QilNodeType.True) {
497 return variable.Binding;
499 // The following optimization is not safe if the iterator has side effects
500 //((Filter (For $Binding) (False) ) => (Sequence))
502 return f.Filter(variable, expr);
505 #endregion // loops
507 #region sorting
508 //-----------------------------------------------
509 // sorting
510 //-----------------------------------------------
511 public QilNode Sort(QilIterator iter, QilNode keys) {
512 return f.Sort(iter, keys);
515 public QilSortKey SortKey(QilNode key, QilNode collation) {
516 return f.SortKey(key, collation);
519 public QilNode DocOrderDistinct(QilNode collection) {
520 if (collection.NodeType == QilNodeType.DocOrderDistinct) {
521 return collection;
523 return f.DocOrderDistinct(collection);
526 #endregion // sorting
528 #region function definition and invocation
529 //-----------------------------------------------
530 // function definition and invocation
531 //-----------------------------------------------
532 public QilFunction Function(QilList args, QilNode sideEffects, XmlQueryType resultType) {
533 Debug.Assert(args.NodeType == QilNodeType.FormalParameterList);
534 return f.Function(args, sideEffects, resultType);
536 public QilFunction Function(QilList args, QilNode defn, QilNode sideEffects) {
537 Debug.Assert(args.NodeType == QilNodeType.FormalParameterList);
538 return f.Function(args, defn, sideEffects, defn.XmlType);
541 public QilNode Invoke(QilFunction func, QilList args) {
542 Debug.Assert(args.NodeType == QilNodeType.ActualParameterList);
543 Debug.Assert(func.Arguments.Count == args.Count);
544 return f.Invoke(func, args);
546 #endregion // function definition and invocation
548 #region XML navigation
549 //-----------------------------------------------
550 // XML navigation
551 //-----------------------------------------------
552 public QilNode Content(QilNode context) {
553 return f.Content(context);
556 public QilNode Parent(QilNode context) {
557 return f.Parent(context);
560 public QilNode Root(QilNode context) {
561 return f.Root(context);
564 public QilNode XmlContext() {
565 return f.XmlContext();
568 public QilNode Descendant(QilNode expr) {
569 return f.Descendant(expr);
572 public QilNode DescendantOrSelf(QilNode context) {
573 return f.DescendantOrSelf(context);
576 public QilNode Ancestor(QilNode expr) {
577 return f.Ancestor(expr);
580 public QilNode AncestorOrSelf(QilNode expr) {
581 return f.AncestorOrSelf(expr);
584 public QilNode Preceding(QilNode expr) {
585 return f.Preceding(expr);
588 public QilNode FollowingSibling(QilNode expr) {
589 return f.FollowingSibling(expr);
592 public QilNode PrecedingSibling(QilNode expr) {
593 return f.PrecedingSibling(expr);
596 public QilNode NodeRange(QilNode left, QilNode right) {
597 return f.NodeRange(left, right);
600 public QilBinary Deref(QilNode context, QilNode id) {
601 return f.Deref(context, id);
603 #endregion // XML navigation
605 #region XML construction
606 //-----------------------------------------------
607 // XML construction
608 //-----------------------------------------------
609 public QilNode ElementCtor(QilNode name, QilNode content) {
610 return f.ElementCtor(name, content);
613 public QilNode AttributeCtor(QilNode name, QilNode val) {
614 return f.AttributeCtor(name, val);
617 public QilNode CommentCtor(QilNode content) {
618 return f.CommentCtor(content);
621 public QilNode PICtor(QilNode name, QilNode content) {
622 return f.PICtor(name, content);
625 public QilNode TextCtor(QilNode content) {
626 return f.TextCtor(content);
629 public QilNode RawTextCtor(QilNode content) {
630 return f.RawTextCtor(content);
633 public QilNode DocumentCtor(QilNode child) {
634 return f.DocumentCtor(child);
637 public QilNode NamespaceDecl(QilNode prefix, QilNode uri) {
638 return f.NamespaceDecl(prefix, uri);
641 public QilNode RtfCtor(QilNode content, QilNode baseUri) {
642 return f.RtfCtor(content, baseUri);
645 #endregion // XML construction
647 #region Node properties
648 //-----------------------------------------------
649 // Node properties
650 //-----------------------------------------------
651 public QilNode NameOf(QilNode expr) {
652 return f.NameOf(expr);
655 public QilNode LocalNameOf(QilNode expr) {
656 return f.LocalNameOf(expr);
659 public QilNode NamespaceUriOf(QilNode expr) {
660 return f.NamespaceUriOf(expr);
663 public QilNode PrefixOf(QilNode expr) {
664 return f.PrefixOf(expr);
667 #endregion // Node properties
669 #region Type operators
670 //-----------------------------------------------
671 // Type operators
672 //-----------------------------------------------
673 public QilNode TypeAssert(QilNode expr, XmlQueryType t) {
674 return f.TypeAssert(expr, t);
677 public QilNode IsType(QilNode expr, XmlQueryType t) {
678 Debug.Assert(t != null, "Type can't be null");
679 return f.IsType(expr, t);
682 public QilNode IsEmpty(QilNode set) {
683 return f.IsEmpty(set);
686 #endregion // Type operators
688 #region XPath operators
689 //-----------------------------------------------
690 // XPath operators
691 //-----------------------------------------------
692 public QilNode XPathNodeValue(QilNode expr) {
693 return f.XPathNodeValue(expr);
696 public QilNode XPathFollowing(QilNode expr) {
697 return f.XPathFollowing(expr);
700 public QilNode XPathNamespace(QilNode expr) {
701 return f.XPathNamespace(expr);
704 public QilNode XPathPreceding(QilNode expr) {
705 return f.XPathPreceding(expr);
708 #endregion // XPath operators
710 #region XSLT
711 //-----------------------------------------------
712 // XSLT
713 //-----------------------------------------------
714 public QilNode XsltGenerateId(QilNode expr) {
715 return f.XsltGenerateId(expr);
718 public QilNode XsltInvokeEarlyBound(QilNode name, MethodInfo d, XmlQueryType t, IList<QilNode> args) {
719 QilList list = f.ActualParameterList();
720 list.Add(args);
721 return f.XsltInvokeEarlyBound(name, f.LiteralObject(d), list, t);
724 public QilNode XsltInvokeLateBound(QilNode name, IList<QilNode> args) {
725 QilList list = f.ActualParameterList();
726 list.Add(args);
727 return f.XsltInvokeLateBound(name, list);
730 public QilNode XsltCopy(QilNode expr, QilNode content) {
731 return f.XsltCopy(expr, content);
734 public QilNode XsltCopyOf(QilNode expr) {
735 return f.XsltCopyOf(expr);
738 public QilNode XsltConvert(QilNode expr, XmlQueryType t) {
739 return f.XsltConvert(expr, t);
742 #endregion // XSLT