Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / System.Core / System.Linq.jvm / Runner.cs
1 //
2 // Runner.cs
3 //
4 // (C) 2008 Mainsoft, Inc. (http://www.mainsoft.com)
5 // (C) 2008 db4objects, Inc. (http://www.db4o.com)
6 // (C) 2010 Novell, Inc. (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27
28 using System.Linq.Expressions;
29 using System.Reflection;
30
31 namespace System.Linq.jvm {
32
33         sealed class Runner {
34
35                 sealed class VoidTypeMarker {}
36
37                 static readonly Type VoidMarker = typeof (VoidTypeMarker);
38                 static readonly MethodInfo [] delegates = new MethodInfo [5];
39                 const BindingFlags method_flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
40
41                 readonly LambdaExpression lambda;
42                 readonly ExpressionInterpreter interpreter;
43
44                 static Runner ()
45                 {
46                         foreach (var method in typeof (Runner).GetMethods (method_flags).Where (m => m.Name == "GetDelegate"))
47                                 delegates [method.GetGenericArguments ().Length - 1] = method;
48                 }
49
50                 public Runner (LambdaExpression lambda)
51                 {
52                         this.lambda = lambda;
53                 }
54
55                 public Runner (LambdaExpression lambda, ExpressionInterpreter interpreter)
56                 {
57                         this.lambda = lambda;
58                         this.interpreter = interpreter;
59                 }
60
61                 public Delegate CreateDelegate ()
62                 {
63                         var types = GetGenericSignature ();
64                         var creator = delegates [types.Length - 1].MakeGenericMethod (types);
65
66                         return (Delegate) creator.Invoke (this, new object [0]);
67                 }
68
69                 Type [] GetGenericSignature ()
70                 {
71                         var count = lambda.Parameters.Count;
72                         var types = new Type [count + 1];
73
74                         var return_type = lambda.GetReturnType ();
75                         if (return_type == typeof (void))
76                                 return_type = VoidMarker;
77
78                         types [count] = return_type;
79                         for (int i = 0; i < count; i++) {
80                                 types [i] = lambda.Parameters [i].Type;
81                         }
82
83                         return types;
84                 }
85
86                 object Run (object [] arguments)
87                 {
88                         var interpreter = this.interpreter ?? new ExpressionInterpreter (lambda);
89
90                         return interpreter.Interpret (lambda, arguments);
91                 }
92
93                 MethodInfo GetActionRunner (params Type [] types)
94                 {
95                         return GetRunner ("ActionRunner", types);
96                 }
97
98                 MethodInfo GetFuncRunner (params Type [] types)
99                 {
100                         return GetRunner ("FuncRunner", types);
101                 }
102
103                 MethodInfo GetRunner (string name, Type [] type_arguments)
104                 {
105                         var method = GetMethod (name, type_arguments.Length);
106                         if (method == null)
107                                 throw new InvalidOperationException ();
108
109                         if (type_arguments.Length == 0)
110                                 return method;
111
112                         return method.MakeGenericMethod (type_arguments);
113                 }
114
115                 MethodInfo GetMethod (string name, int parameters)
116                 {
117                         foreach (var method in GetType ().GetMethods (method_flags)) {
118                                 if (method.Name != name)
119                                         continue;
120
121                                 if (method.GetGenericArguments ().Length != parameters)
122                                         continue;
123
124                                 return method;
125                         }
126
127                         return null;
128                 }
129
130                 Delegate CreateDelegate (MethodInfo runner)
131                 {
132                         return Delegate.CreateDelegate (lambda.Type, this, runner);
133                 }
134
135                 // all methods below are called through reflection
136
137                 Delegate GetDelegate<TResult> ()
138                 {
139                         if (typeof (TResult) == VoidMarker)
140                                 return CreateDelegate (GetActionRunner (Type.EmptyTypes));
141
142                         return CreateDelegate (GetFuncRunner (typeof (TResult)));
143                 }
144
145                 public TResult FuncRunner<TResult> ()
146                 {
147                         return (TResult) Run (new object [0]);
148                 }
149
150                 public void ActionRunner ()
151                 {
152                         Run (new object [0]);
153                 }
154
155                 Delegate GetDelegate<T, TResult> ()
156                 {
157                         if (typeof (TResult) == VoidMarker)
158                                 return CreateDelegate (GetActionRunner (typeof (T)));
159
160                         return CreateDelegate (GetFuncRunner (typeof (T), typeof (TResult)));
161                 }
162
163                 public TResult FuncRunner<T, TResult> (T arg)
164                 {
165                         return (TResult) Run (new object [] { arg });
166                 }
167
168                 public void ActionRunner<T> (T arg)
169                 {
170                         Run (new object [] { arg });
171                 }
172
173                 public Delegate GetDelegate<T1, T2, TResult> ()
174                 {
175                         if (typeof (TResult) == VoidMarker)
176                                 return CreateDelegate (GetActionRunner (typeof (T1), typeof (T2)));
177
178                         return CreateDelegate (GetFuncRunner (typeof (T1), typeof (T2), typeof (TResult)));
179                 }
180
181                 public TResult FuncRunner<T1, T2, TResult> (T1 arg1, T2 arg2)
182                 {
183                         return (TResult) Run (new object [] { arg1, arg2 });
184                 }
185
186                 public void ActionRunner<T1, T2> (T1 arg1, T2 arg2)
187                 {
188                         Run (new object [] { arg1, arg2 });
189                 }
190
191                 Delegate GetDelegate<T1, T2, T3, TResult> ()
192                 {
193                         if (typeof (TResult) == VoidMarker)
194                                 return CreateDelegate (GetActionRunner (typeof (T1), typeof (T2), typeof (T3)));
195
196                         return CreateDelegate (GetFuncRunner (typeof (T1), typeof (T2), typeof (T3), typeof (TResult)));
197                 }
198
199                 public TResult FuncRunner<T1, T2, T3, TResult> (T1 arg1, T2 arg2, T3 arg3)
200                 {
201                         return (TResult) Run (new object [] { arg1, arg2, arg3 });
202                 }
203
204                 public void ActionRunner<T1, T2, T3> (T1 arg1, T2 arg2, T3 arg3)
205                 {
206                         Run (new object [] { arg1, arg2, arg3 });
207                 }
208
209                 Delegate GetDelegate<T1, T2, T3, T4, TResult> ()
210                 {
211                         if (typeof (TResult) == VoidMarker)
212                                 return CreateDelegate (GetActionRunner (typeof (T1), typeof (T2), typeof (T3), typeof (T4)));
213
214                         return CreateDelegate (GetFuncRunner (typeof (T1), typeof (T2), typeof (T3), typeof (T4), typeof (TResult)));
215                 }
216
217                 public TResult FuncRunner<T1, T2, T3, T4, TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4)
218                 {
219                         return (TResult) Run (new object [] { arg1, arg2, arg3, arg4 });
220                 }
221
222                 public void ActionRunner<T1, T2, T3, T4> (T1 arg1, T2 arg2, T3 arg3, T4 arg4)
223                 {
224                         Run (new object [] { arg1, arg2, arg3, arg4 });
225                 }
226         }
227 }