Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / QIL / QilPatternFactory.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="QilPatternFactory.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>
6 //------------------------------------------------------------------------------
7
8 using System.Collections.Generic;
9 using System.Diagnostics;
10 using System.Reflection;
11 using System.Xml.Schema;
12
13 namespace System.Xml.Xsl.Qil {
14
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;
26
27         public QilPatternFactory(QilFactory f, bool debug) {
28             Debug.Assert(f != null);
29             this.f = f;
30             this.debug = debug;
31         }
32
33         public QilFactory          BaseFactory { get { return f; } }
34         public bool                IsDebug     { get { return this.debug; } }
35
36         #region Convenience methods
37
38         public QilLiteral String(string val) {
39             return f.LiteralString(val);
40         }
41
42         public QilLiteral Int32(int val) {
43             return f.LiteralInt32(val);
44         }
45
46         public QilLiteral Double(double val) {
47             return f.LiteralDouble(val);
48         }
49
50         public QilName QName(string local, string uri, string prefix) {
51             return f.LiteralQName(local, uri, prefix);
52         }
53
54         public QilName QName(string local, string uri) {
55             return f.LiteralQName(local, uri, System.String.Empty);
56         }
57
58         public QilName QName(string local) {
59             return f.LiteralQName(local, System.String.Empty, System.String.Empty);
60         }
61
62         public QilNode Unknown(XmlQueryType t) {
63             return f.Unknown(t);
64         }
65         #endregion
66
67         #region meta
68         //-----------------------------------------------
69         // meta
70         //-----------------------------------------------
71         public QilExpression QilExpression(QilNode root, QilFactory factory) {
72             return f.QilExpression(root, factory);
73         }
74
75         public QilList FunctionList() {
76             return f.FunctionList();
77         }
78
79         public QilList GlobalVariableList() {
80             return f.GlobalVariableList();
81         }
82
83         public QilList GlobalParameterList() {
84             return f.GlobalParameterList();
85         }
86
87         public QilList ActualParameterList() {
88             return f.ActualParameterList();
89         }
90
91         public QilList ActualParameterList(QilNode arg1) {
92             QilList result = f.ActualParameterList();
93             result.Add(arg1);
94             return result;
95         }
96
97         public QilList ActualParameterList(QilNode arg1, QilNode arg2) {
98             QilList result = f.ActualParameterList();
99             result.Add(arg1);
100             result.Add(arg2);
101             return result;
102         }
103
104         public QilList ActualParameterList(params QilNode[] args) {
105             return f.ActualParameterList(args);
106         }
107
108         public QilList FormalParameterList() {
109             return f.FormalParameterList();
110         }
111
112         public QilList FormalParameterList(QilNode arg1) {
113             QilList result = f.FormalParameterList();
114             result.Add(arg1);
115             return result;
116         }
117
118         public QilList FormalParameterList(QilNode arg1, QilNode arg2) {
119             QilList result = f.FormalParameterList();
120             result.Add(arg1);
121             result.Add(arg2);
122             return result;
123         }
124
125         public QilList FormalParameterList(params QilNode[] args) {
126             return f.FormalParameterList(args);
127         }
128
129         public QilList SortKeyList() {
130             return f.SortKeyList();
131         }
132
133         public QilList SortKeyList(QilSortKey key) {
134             QilList list = f.SortKeyList();
135             list.Add(key);
136             return list;
137         }
138
139         public QilList BranchList(params QilNode[] args) {
140             return f.BranchList(args);
141         }
142
143         public QilNode OptimizeBarrier(QilNode child) {
144             return f.OptimizeBarrier(child);
145         }
146
147         #endregion // meta
148
149         #region specials
150         //-----------------------------------------------
151         // specials
152         //-----------------------------------------------
153         public QilNode DataSource(QilNode name, QilNode baseUri) {
154             return f.DataSource(name, baseUri);
155         }
156
157         public QilNode Nop(QilNode child) {
158             return f.Nop(child);
159         }
160
161         public QilNode Error(QilNode text) {
162             return f.Error(text);
163         }
164
165         public QilNode Warning(QilNode text) {
166             return f.Warning(text);
167         }
168
169         #endregion // specials
170
171         #region variables
172         //-----------------------------------------------
173         // variables
174         //-----------------------------------------------
175         public QilIterator For(QilNode binding) {
176             return f.For(binding);
177         }
178
179         public QilIterator Let(QilNode binding) {
180             return f.Let(binding);
181         }
182
183         public QilParameter Parameter(XmlQueryType t) {
184             return f.Parameter(t);
185         }
186
187         public QilParameter Parameter(QilNode defaultValue, QilName name, XmlQueryType t) {
188             return f.Parameter(defaultValue, name, t);
189         }
190
191         public QilNode PositionOf(QilIterator expr) {
192             return f.PositionOf(expr);
193         }
194
195         #endregion // variables
196
197         #region literals
198         //-----------------------------------------------
199         // literals
200         //-----------------------------------------------
201         public QilNode True() {
202             return f.True();
203         }
204
205         public QilNode False() {
206             return f.False();
207         }
208
209         public QilNode Boolean(bool b) {
210             return b ? this.True() : this.False();
211         }
212
213         #endregion // literals
214
215         #region boolean operators
216         //-----------------------------------------------
217         // boolean operators
218         //-----------------------------------------------
219
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"
225             );
226         }
227
228         public QilNode And(QilNode left, QilNode right) {
229             CheckLogicArg(left);
230             CheckLogicArg(right);
231
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;
238                 }
239                 if (left.NodeType == QilNodeType.False || right.NodeType == QilNodeType.True) {
240                     return left;
241                 }
242             }
243             return f.And(left, right);
244         }
245
246         public QilNode Or(QilNode left, QilNode right) {
247             CheckLogicArg(left);
248             CheckLogicArg(right);
249
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;
256                 }
257                 if (left.NodeType == QilNodeType.False || right.NodeType == QilNodeType.True) {
258                     return right;
259                 }
260             }
261             return f.Or(left, right);
262         }
263
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;
273                 }
274             }
275             return f.Not(child);
276         }
277
278         #endregion // boolean operators
279
280         #region choice
281         //-----------------------------------------------
282         // choice
283         //-----------------------------------------------
284
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);
294                 }
295             }
296             return f.Conditional(condition, trueBranch, falseBranch);
297         }
298
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]);
307                 }
308             }
309             return f.Choice(expr, branches);
310         }
311
312         #endregion // choice
313
314         #region collection operators
315         //-----------------------------------------------
316         // collection operators
317         //-----------------------------------------------
318         public QilNode Length(QilNode child) {
319             return f.Length(child);
320         }
321
322         public QilNode Sequence() {
323             return f.Sequence();
324         }
325
326         public QilNode Sequence(QilNode child) {
327             if (! debug) {
328                 return child;
329             }
330             QilList res = f.Sequence();
331             res.Add(child);
332             return res;
333         }
334
335         public QilNode Sequence(QilNode child1, QilNode child2) {
336             QilList res = f.Sequence();
337             res.Add(child1);
338             res.Add(child2);
339             return res;
340         }
341
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];
347                 }
348             }
349             QilList res = f.Sequence();
350             foreach (QilNode n in args)
351                 res.Add(n);
352             return res;
353         }
354
355         public QilNode Union(QilNode left, QilNode right) {
356             return f.Union(left, right);
357         }
358
359         public QilNode Sum(QilNode collection) {
360             return f.Sum(collection);
361         }
362         #endregion // collection operators
363
364         #region arithmetic operators
365         //-----------------------------------------------
366         // arithmetic operators
367         //-----------------------------------------------
368         public QilNode Negate(QilNode child) {
369             return f.Negate(child);
370         }
371
372         public QilNode Add(QilNode left, QilNode right) {
373             return f.Add(left, right);
374         }
375
376         public QilNode Subtract(QilNode left, QilNode right) {
377             return f.Subtract(left, right);
378         }
379
380         public QilNode Multiply(QilNode left, QilNode right) {
381             return f.Multiply(left, right);
382         }
383
384         public QilNode Divide(QilNode left, QilNode right) {
385             return f.Divide(left, right);
386         }
387
388         public QilNode Modulo(QilNode left, QilNode right) {
389             return f.Modulo(left, right);
390         }
391
392         #endregion // arithmetic operators
393
394         #region string operators
395         //-----------------------------------------------
396         // string operators
397         //-----------------------------------------------
398         public QilNode StrLength(QilNode str) {
399             return f.StrLength(str);
400         }
401
402         public QilNode StrConcat(QilNode values) {
403             if (! debug) {
404                 if (values.XmlType.IsSingleton)
405                     return values;
406             }
407             return f.StrConcat(values);
408         }
409
410         public QilNode StrConcat(params QilNode[] args) {
411             return StrConcat((IList<QilNode>)args);
412         }
413
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]);
421                 }
422             }
423             return StrConcat(f.Sequence(args));
424         }
425
426         public QilNode StrParseQName(QilNode str, QilNode ns) {
427             return f.StrParseQName(str, ns);
428         }
429         #endregion // string operators
430
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);
437         }
438
439         public QilNode Eq(QilNode left, QilNode right) {
440             return f.Eq(left, right);
441         }
442
443         public QilNode Gt(QilNode left, QilNode right) {
444             return f.Gt(left, right);
445         }
446
447         public QilNode Ge(QilNode left, QilNode right) {
448             return f.Ge(left, right);
449         }
450
451         public QilNode Lt(QilNode left, QilNode right) {
452             return f.Lt(left, right);
453         }
454
455         public QilNode Le(QilNode left, QilNode right) {
456             return f.Le(left, right);
457         }
458
459         #endregion // value comparison operators
460
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);
467         }
468
469         public QilNode After(QilNode left, QilNode right) {
470             return f.After(left, right);
471         }
472
473         public QilNode Before(QilNode left, QilNode right) {
474             return f.Before(left, right);
475         }
476
477         #endregion // node comparison operators
478
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;
488                 }
489             }
490             return f.Loop(variable, body);
491         }
492
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;
498                 }
499                 // The following optimization is not safe if the iterator has side effects
500                 //((Filter (For $Binding) (False) ) => (Sequence))
501             }
502             return f.Filter(variable, expr);
503         }
504
505         #endregion // loops
506
507         #region sorting
508         //-----------------------------------------------
509         // sorting
510         //-----------------------------------------------
511         public QilNode Sort(QilIterator iter, QilNode keys) {
512             return f.Sort(iter, keys);
513         }
514
515         public QilSortKey SortKey(QilNode key, QilNode collation) {
516             return f.SortKey(key, collation);
517         }
518
519         public QilNode DocOrderDistinct(QilNode collection) {
520             if (collection.NodeType == QilNodeType.DocOrderDistinct) {
521                 return collection;
522             }
523             return f.DocOrderDistinct(collection);
524         }
525
526         #endregion // sorting
527
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);
535         }
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);
539         }
540
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);
545         }
546         #endregion // function definition and invocation
547
548         #region XML navigation
549         //-----------------------------------------------
550         // XML navigation
551         //-----------------------------------------------
552         public QilNode Content(QilNode context) {
553             return f.Content(context);
554         }
555
556         public QilNode Parent(QilNode context) {
557             return f.Parent(context);
558         }
559
560         public QilNode Root(QilNode context) {
561             return f.Root(context);
562         }
563
564         public QilNode XmlContext() {
565             return f.XmlContext();
566         }
567
568         public QilNode Descendant(QilNode expr) {
569             return f.Descendant(expr);
570         }
571
572         public QilNode DescendantOrSelf(QilNode context) {
573             return f.DescendantOrSelf(context);
574         }
575
576         public QilNode Ancestor(QilNode expr) {
577             return f.Ancestor(expr);
578         }
579
580         public QilNode AncestorOrSelf(QilNode expr) {
581             return f.AncestorOrSelf(expr);
582         }
583
584         public QilNode Preceding(QilNode expr) {
585             return f.Preceding(expr);
586         }
587
588         public QilNode FollowingSibling(QilNode expr) {
589             return f.FollowingSibling(expr);
590         }
591
592         public QilNode PrecedingSibling(QilNode expr) {
593             return f.PrecedingSibling(expr);
594         }
595
596         public QilNode NodeRange(QilNode left, QilNode right) {
597             return f.NodeRange(left, right);
598         }
599
600         public QilBinary Deref(QilNode context, QilNode id) {
601             return f.Deref(context, id);
602         }
603         #endregion // XML navigation
604
605         #region XML construction
606         //-----------------------------------------------
607         // XML construction
608         //-----------------------------------------------
609         public QilNode ElementCtor(QilNode name, QilNode content) {
610             return f.ElementCtor(name, content);
611         }
612
613         public QilNode AttributeCtor(QilNode name, QilNode val) {
614             return f.AttributeCtor(name, val);
615         }
616
617         public QilNode CommentCtor(QilNode content) {
618             return f.CommentCtor(content);
619         }
620
621         public QilNode PICtor(QilNode name, QilNode content) {
622             return f.PICtor(name, content);
623         }
624
625         public QilNode TextCtor(QilNode content) {
626             return f.TextCtor(content);
627         }
628
629         public QilNode RawTextCtor(QilNode content) {
630             return f.RawTextCtor(content);
631         }
632
633         public QilNode DocumentCtor(QilNode child) {
634             return f.DocumentCtor(child);
635         }
636
637         public QilNode NamespaceDecl(QilNode prefix, QilNode uri) {
638             return f.NamespaceDecl(prefix, uri);
639         }
640
641         public QilNode RtfCtor(QilNode content, QilNode baseUri) {
642             return f.RtfCtor(content, baseUri);
643         }
644
645         #endregion // XML construction
646
647         #region Node properties
648         //-----------------------------------------------
649         // Node properties
650         //-----------------------------------------------
651         public QilNode NameOf(QilNode expr) {
652             return f.NameOf(expr);
653         }
654
655         public QilNode LocalNameOf(QilNode expr) {
656             return f.LocalNameOf(expr);
657         }
658
659         public QilNode NamespaceUriOf(QilNode expr) {
660             return f.NamespaceUriOf(expr);
661         }
662
663         public QilNode PrefixOf(QilNode expr) {
664             return f.PrefixOf(expr);
665         }
666
667         #endregion // Node properties
668
669         #region Type operators
670         //-----------------------------------------------
671         // Type operators
672         //-----------------------------------------------
673         public QilNode TypeAssert(QilNode expr, XmlQueryType t) {
674             return f.TypeAssert(expr, t);
675         }
676
677         public QilNode IsType(QilNode expr, XmlQueryType t) {
678             Debug.Assert(t != null, "Type can't be null");
679             return f.IsType(expr, t);
680         }
681
682         public QilNode IsEmpty(QilNode set) {
683             return f.IsEmpty(set);
684         }
685
686         #endregion // Type operators
687
688         #region XPath operators
689         //-----------------------------------------------
690         // XPath operators
691         //-----------------------------------------------
692         public QilNode XPathNodeValue(QilNode expr) {
693             return f.XPathNodeValue(expr);
694         }
695
696         public QilNode XPathFollowing(QilNode expr) {
697             return f.XPathFollowing(expr);
698         }
699
700         public QilNode XPathNamespace(QilNode expr) {
701             return f.XPathNamespace(expr);
702         }
703
704         public QilNode XPathPreceding(QilNode expr) {
705             return f.XPathPreceding(expr);
706         }
707
708         #endregion // XPath operators
709
710         #region XSLT
711         //-----------------------------------------------
712         // XSLT
713         //-----------------------------------------------
714         public QilNode XsltGenerateId(QilNode expr) {
715             return f.XsltGenerateId(expr);
716         }
717
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);
722         }
723
724         public QilNode XsltInvokeLateBound(QilNode name, IList<QilNode> args) {
725             QilList list = f.ActualParameterList();
726             list.Add(args);
727             return f.XsltInvokeLateBound(name, list);
728         }
729
730         public QilNode XsltCopy(QilNode expr, QilNode content) {
731             return f.XsltCopy(expr, content);
732         }
733
734         public QilNode XsltCopyOf(QilNode expr) {
735             return f.XsltCopyOf(expr);
736         }
737
738         public QilNode XsltConvert(QilNode expr, XmlQueryType t) {
739             return f.XsltConvert(expr, t);
740         }
741
742         #endregion // XSLT
743     }
744 }