2 using System.Collections.Generic;
4 using System.Linq.Expressions;
6 public struct InverseLogicalOperator
9 public InverseLogicalOperator (bool value)
14 public static bool operator true (InverseLogicalOperator u)
19 public static bool operator false (InverseLogicalOperator u)
25 /* TODO: Add tests for every numeric expression where a type has only 1 implicit
27 public struct MyType<T>
31 public MyType (T value)
36 public static implicit operator T (MyType<T> o)
47 public MyType (int value)
52 public static implicit operator int (MyType o)
57 public static bool operator true (MyType a)
62 public static bool operator false (MyType a)
67 public static MyType operator +(MyType a, MyType b)
69 return new MyType (a.value + b.value);
72 public static MyType operator / (MyType a, MyType b)
74 return new MyType (a.value / b.value);
77 public static MyType operator &(MyType a, MyType b)
79 return new MyType (a.value & b.value);
82 public static MyType operator | (MyType a, MyType b)
84 return new MyType (a.value | b.value);
87 public static MyType operator ^ (MyType a, MyType b)
89 return new MyType (a.value ^ b.value);
92 public static bool operator == (MyType a, MyType b)
94 return a.value == b.value;
97 public static bool operator != (MyType a, MyType b)
99 return a.value != b.value;
102 public static bool operator > (MyType a, MyType b)
104 return a.value > b.value;
107 public static bool operator >= (MyType a, MyType b)
109 return a.value >= b.value;
112 public override string ToString ()
114 return value.ToString ();
120 static void AssertNodeType (LambdaExpression e, ExpressionType et)
122 if (e.Body.NodeType != et)
123 throw new ApplicationException (e.Body.NodeType + " != " + et);
126 static void Assert<T> (T expected, T value)
128 if (!EqualityComparer<T>.Default.Equals (expected, value))
129 throw new ApplicationException (expected + " != " + value);
132 static void Assert<T> (T [] expected, T [] value)
134 if (expected.Length != value.Length)
135 throw new ApplicationException ("Array length does not match " + expected.Length + " != " + value.Length);
137 for (int i = 0; i < expected.Length; ++i) {
138 if (!EqualityComparer<T>.Default.Equals (expected [i], value [i]))
139 throw new ApplicationException ("Index " + i + ": " + expected [i] + " != " + value [i]);
145 Expression<Func<int, int, int>> e = (int a, int b) => a + b;
146 AssertNodeType (e, ExpressionType.Add);
147 Assert (50, e.Compile ().Invoke (20, 30));
149 Expression<Func<int?, int?, int?>> e2 = (a, b) => a + b;
150 AssertNodeType (e2, ExpressionType.Add);
151 Assert (null, e2.Compile ().Invoke (null, 3));
153 Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a + b;
154 AssertNodeType (e3, ExpressionType.Add);
155 Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
158 void AddCheckedTest ()
161 Expression<Func<int, int, int>> e = (int a, int b) => a + b;
162 AssertNodeType (e, ExpressionType.AddChecked);
163 Assert (50, e.Compile ().Invoke (20, 30));
165 Expression<Func<int?, int?, int?>> e2 = (a, b) => a + b;
166 AssertNodeType (e2, ExpressionType.AddChecked);
167 Assert (null, e2.Compile ().Invoke (null, 3));
169 Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a + b;
170 AssertNodeType (e3, ExpressionType.Add);
171 Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
177 Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a & b;
179 AssertNodeType (e, ExpressionType.And);
180 Func<bool, bool, bool> c = e.Compile ();
182 Assert (true, c (true, true));
183 Assert (false, c (true, false));
184 Assert (false, c (false, true));
185 Assert (false, c (false, false));
187 Expression<Func<MyType, MyType, MyType>> e2 = (MyType a, MyType b) => a & b;
189 AssertNodeType (e2, ExpressionType.And);
190 var c2 = e2.Compile ();
192 Assert (new MyType (0), c2 (new MyType (0), new MyType (1)));
193 Assert (new MyType (1), c2 (new MyType (0xFF), new MyType (0x01)));
196 void AndNullableTest ()
198 Expression<Func<bool?, bool?, bool?>> e = (bool? a, bool? b) => a & b;
200 AssertNodeType (e, ExpressionType.And);
201 Func<bool?, bool?, bool?> c = e.Compile ();
203 Assert (true, c (true, true));
204 Assert (false, c (true, false));
205 Assert (false, c (false, true));
206 Assert (false, c (false, false));
208 Assert (null, c (true, null));
209 Assert (false, c (false, null));
210 Assert (false, c (null, false));
211 Assert (null, c (true, null));
212 Assert (null, c (null, null));
214 Expression<Func<MyType?, MyType?, MyType?>> e2 = (MyType? a, MyType? b) => a & b;
216 AssertNodeType (e2, ExpressionType.And);
217 var c2 = e2.Compile ();
219 Assert (new MyType (0), c2 (new MyType (0), new MyType (1)));
220 Assert (new MyType (1), c2 (new MyType (0xFF), new MyType (0x01)));
221 Assert (null, c2 (new MyType (0xFF), null));
226 Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a && b;
228 AssertNodeType (e, ExpressionType.AndAlso);
229 Assert (false, e.Compile ().Invoke (true, false));
231 Expression<Func<MyType, MyType, MyType>> e2 = (MyType a, MyType b) => a && b;
233 AssertNodeType (e2, ExpressionType.AndAlso);
234 Assert (new MyType (64), e2.Compile ().Invoke (new MyType (64), new MyType (64)));
235 Assert (new MyType (0), e2.Compile ().Invoke (new MyType (32), new MyType (64)));
238 void ArrayIndexTest ()
240 Expression<Func<string [], long, string>> e = (string [] a, long i) => a [i];
241 AssertNodeType (e, ExpressionType.ArrayIndex);
242 Assert ("b", e.Compile ().Invoke (new string [] { "a", "b", "c" }, 1));
244 Expression<Func<string [], string>> e2 = (string [] a) => a [0];
245 AssertNodeType (e2, ExpressionType.ArrayIndex);
246 Assert ("a", e2.Compile ().Invoke (new string [] { "a", "b" }));
248 Expression<Func<object [,], int, int, object>> e3 = (object [,] a, int i, int j) => a [i, j];
249 AssertNodeType (e3, ExpressionType.Call);
251 Assert ("z", e3.Compile ().Invoke (
252 new object [,] { { 1, 2 }, { "x", "z" } }, 1, 1));
254 Expression<Func<decimal [] [], byte, decimal>> e4 = (decimal [] [] a, byte b) => a [b] [1];
255 AssertNodeType (e4, ExpressionType.ArrayIndex);
257 decimal [] [] array = { new decimal [] { 1, 9 }, new decimal [] { 10, 90 } };
258 Assert (90, e4.Compile ().Invoke (array, 1));
261 void ArrayLengthTest ()
263 int o = new int [0].Length;
265 Expression<Func<double [], int>> e = (double [] a) => a.Length;
266 AssertNodeType (e, ExpressionType.ArrayLength);
267 Assert (0, e.Compile ().Invoke (new double [0]));
268 Assert (9, e.Compile ().Invoke (new double [9]));
271 //Expression<Func<string [,], int>> e2 = (string [,] a) => a.Length;
272 //AssertNodeType (e2, ExpressionType.MemberAccess);
273 //Assert (0, e2.Compile ().Invoke (new string [0, 0]));
278 Expression<Func<int, int>> e = (int a) => Math.Max (a, 5);
279 AssertNodeType (e, ExpressionType.Call);
280 Assert (5, e.Compile ().Invoke (2));
281 Assert (9, e.Compile ().Invoke (9));
283 Expression<Func<string, string>> e2 = (string a) => InstanceMethod (a);
284 AssertNodeType (e2, ExpressionType.Call);
285 Assert ("abc", e2.Compile ().Invoke ("abc"));
287 Expression<Func<int, string, int, object>> e3 = (int index, string a, int b) => InstanceParamsMethod (index, a, b);
288 AssertNodeType (e3, ExpressionType.Call);
289 Assert<object> (4, e3.Compile ().Invoke (1, "a", 4));
291 Expression<Func<object>> e4 = () => InstanceParamsMethod (0);
292 AssertNodeType (e4, ExpressionType.Call);
293 Assert<object> ("<empty>", e4.Compile ().Invoke ());
295 Expression<Func<int, int>> e5 = (int a) => GenericMethod (a);
296 AssertNodeType (e5, ExpressionType.Call);
297 Assert (5, e5.Compile ().Invoke (5));
302 Expression<Func<uint?, uint>> e = (uint? a) => a ?? 99;
303 AssertNodeType (e, ExpressionType.Coalesce);
304 var r = e.Compile ();
305 Assert ((uint) 5, r.Invoke (5));
306 Assert ((uint) 99, r.Invoke (null));
308 Expression<Func<MyType?, int>> e2 = (MyType? a) => a ?? -3;
309 AssertNodeType (e2, ExpressionType.Coalesce);
310 var r2 = e2.Compile ();
311 Assert (2, r2.Invoke (new MyType (2)));
312 Assert (-3, r2.Invoke (null));
315 void ConditionTest ()
317 Expression<Func<bool, byte, int, int>> e = (bool a, byte b, int c) => (a ? b : c);
318 AssertNodeType (e, ExpressionType.Conditional);
319 var r = e.Compile ();
320 Assert (3, r.Invoke (true, 3, 999999));
321 Assert (999999, r.Invoke (false, 3, 999999));
323 Expression<Func<int, decimal, decimal?>> e2 = (int a, decimal d) => (a > 0 ? d : a < 0 ? -d : (decimal?) null);
324 AssertNodeType (e2, ExpressionType.Conditional);
325 var r2 = e2.Compile ();
326 Assert (null, r2.Invoke (0, 10));
327 Assert (50, r2.Invoke (1, 50));
328 Assert (30, r2.Invoke (-7, -30));
330 Expression<Func<bool?, int?>> e3 = (bool? a) => ((bool) a ? 3 : -2);
331 AssertNodeType (e3, ExpressionType.Convert);
332 var r3 = e3.Compile ();
333 Assert (3, r3.Invoke (true));
334 Assert (-2, r3.Invoke (false));
336 Expression<Func<InverseLogicalOperator, byte, byte, byte>> e4 = (InverseLogicalOperator a, byte b, byte c) => (a ? b : c);
337 AssertNodeType (e4, ExpressionType.Conditional);
338 var r4 = e4.Compile ();
339 Assert (3, r4.Invoke (new InverseLogicalOperator (true), 3, 4));
340 Assert (4, r4.Invoke (new InverseLogicalOperator (false), 3, 4));
343 public void ConvertTest ()
345 Expression<Func<int, byte>> e = (int a) => ((byte) a);
346 AssertNodeType (e, ExpressionType.Convert);
347 Assert (100, e.Compile ().Invoke (100));
349 Expression<Func<long, ushort>> e2 = (long a) => ((ushort) a);
350 AssertNodeType (e2, ExpressionType.Convert);
351 Assert (100, e2.Compile ().Invoke (100));
353 Expression<Func<float?, float>> e3 = (float? a) => ((float) a);
354 AssertNodeType (e3, ExpressionType.Convert);
355 Assert (-0.456f, e3.Compile ().Invoke (-0.456f));
357 Expression<Func<MyType, int>> e4 = (MyType a) => (a);
358 AssertNodeType (e4, ExpressionType.Convert);
359 Assert (-9, e4.Compile ().Invoke (new MyType (-9)));
361 Expression<Func<MyType, MyType, bool?>> e5 = (MyType a, MyType b) => a == b;
362 AssertNodeType (e5, ExpressionType.Convert);
365 public void ConvertCheckedTest ()
367 Expression<Func<int, byte>> e = (int a) => checked((byte) a);
368 AssertNodeType (e, ExpressionType.ConvertChecked);
369 Assert (100, e.Compile ().Invoke (100));
372 Expression<Func<long, ushort>> e2 = (long a) => unchecked((ushort) a);
373 AssertNodeType (e2, ExpressionType.Convert);
374 Assert (100, e2.Compile ().Invoke (100));
376 Expression<Func<float?, float>> e3 = (float? a) => ((float) a);
377 AssertNodeType (e3, ExpressionType.ConvertChecked);
378 Assert (-0.456f, e3.Compile ().Invoke (-0.456f));
380 Expression<Func<MyType, int>> e4 = (MyType a) => (a);
381 AssertNodeType (e4, ExpressionType.Convert);
382 Assert (-9, e4.Compile ().Invoke (new MyType (-9)));
386 public void DivideTest ()
388 Expression<Func<int, int, int>> e = (int a, int b) => a / b;
389 AssertNodeType (e, ExpressionType.Divide);
390 Assert (2, e.Compile ().Invoke (60, 30));
392 Expression<Func<double?, double?, double?>> e2 = (a, b) => a / b;
393 AssertNodeType (e2, ExpressionType.Divide);
394 Assert (null, e2.Compile ().Invoke (null, 3));
395 Assert (1.5, e2.Compile ().Invoke (3, 2));
397 Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a / b;
398 AssertNodeType (e3, ExpressionType.Divide);
399 Assert (1, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
401 Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a / b;
402 AssertNodeType (e4, ExpressionType.Divide);
403 Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
404 Assert (new MyType (-6), e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
407 public void EqualTest ()
409 Expression<Func<int, int, bool>> e = (int a, int b) => a == b;
410 AssertNodeType (e, ExpressionType.Equal);
411 Assert (false, e.Compile ().Invoke (60, 30));
412 Assert (true, e.Compile ().Invoke (-1, -1));
414 Expression<Func<double?, double?, bool>> e2 = (a, b) => a == b;
415 AssertNodeType (e2, ExpressionType.Equal);
416 Assert (true, e2.Compile ().Invoke (3, 3));
417 Assert (false, e2.Compile ().Invoke (3, 2));
419 Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a == b;
420 AssertNodeType (e3, ExpressionType.Equal);
421 Assert (true, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
423 Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a == b;
424 AssertNodeType (e4, ExpressionType.Equal);
425 Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
426 Assert (true, e4.Compile ().Invoke (null, null));
427 Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (120)));
430 public void ExclusiveOrTest ()
432 Expression<Func<int, int, int>> e = (int a, int b) => a ^ b;
433 AssertNodeType (e, ExpressionType.ExclusiveOr);
434 Assert (34, e.Compile ().Invoke (60, 30));
435 /* FIXME: missing conversion
436 Expression<Func<byte?, byte?, int?>> e2 = (a, b) => a ^ b;
437 AssertNodeType (e2, ExpressionType.ExclusiveOr);
438 Assert (null, e2.Compile ().Invoke (null, 3));
439 Assert (1, e2.Compile ().Invoke (3, 2));
441 Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a ^ b;
442 AssertNodeType (e3, ExpressionType.ExclusiveOr);
443 Assert (0, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
445 Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a ^ b;
446 AssertNodeType (e4, ExpressionType.ExclusiveOr);
447 Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
448 Assert (new MyType (-108), e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
451 public void GreaterThanTest ()
453 Expression<Func<int, int, bool>> e = (int a, int b) => a > b;
454 AssertNodeType (e, ExpressionType.GreaterThan);
455 Assert (true, e.Compile ().Invoke (60, 30));
457 Expression<Func<byte?, byte?, bool>> e2 = (a, b) => a > b;
458 AssertNodeType (e2, ExpressionType.GreaterThan);
459 Assert (false, e2.Compile ().Invoke (null, 3));
460 Assert (false, e2.Compile ().Invoke (2, 2));
462 Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a > b;
463 AssertNodeType (e3, ExpressionType.GreaterThan);
464 Assert (false, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
466 Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a > b;
467 AssertNodeType (e4, ExpressionType.GreaterThan);
468 Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
469 Assert (false, e4.Compile ().Invoke (null, null));
470 Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
473 public void GreaterThanOrEqualTest ()
475 Expression<Func<int, int, bool>> e = (int a, int b) => a >= b;
476 AssertNodeType (e, ExpressionType.GreaterThanOrEqual);
477 Assert (true, e.Compile ().Invoke (60, 30));
479 Expression<Func<byte?, byte?, bool>> e2 = (a, b) => a >= b;
480 AssertNodeType (e2, ExpressionType.GreaterThanOrEqual);
481 Assert (false, e2.Compile ().Invoke (null, 3));
482 Assert (true, e2.Compile ().Invoke (2, 2));
484 Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a >= b;
485 AssertNodeType (e3, ExpressionType.GreaterThanOrEqual);
486 Assert (true, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
488 Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a >= b;
489 AssertNodeType (e4, ExpressionType.GreaterThanOrEqual);
490 Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
491 Assert (false, e4.Compile ().Invoke (null, null));
492 Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
495 void NewArrayInitTest ()
497 Expression<Func<int []>> e = () => new int [0];
498 AssertNodeType (e, ExpressionType.NewArrayInit);
499 Assert (new int [0], e.Compile ().Invoke ());
501 e = () => new int [] { };
502 AssertNodeType (e, ExpressionType.NewArrayInit);
503 Assert (new int [0], e.Compile ().Invoke ());
505 Expression<Func<ushort, ulong? []>> e2 = (ushort a) => new ulong? [] { a };
506 AssertNodeType (e2, ExpressionType.NewArrayInit);
507 Assert (new ulong? [1] { ushort.MaxValue }, e2.Compile ().Invoke (ushort.MaxValue));
509 Expression<Func<char [] []>> e3 = () => new char [] [] { new char [] { 'a' } };
510 AssertNodeType (e3, ExpressionType.NewArrayInit);
511 Assert (new char [] { 'a' }, e3.Compile ().Invoke () [0]);
516 Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a | b;
518 AssertNodeType (e, ExpressionType.Or);
519 Func<bool, bool, bool> c = e.Compile ();
521 Assert (true, c (true, true));
522 Assert (true, c (true, false));
523 Assert (true, c (false, true));
524 Assert (false, c (false, false));
526 Expression<Func<MyType, MyType, MyType>> e2 = (MyType a, MyType b) => a | b;
527 AssertNodeType (e2, ExpressionType.Or);
528 var c2 = e2.Compile ();
529 Assert (new MyType (3), c2 (new MyType (1), new MyType (2)));
532 void OrNullableTest ()
534 Expression<Func<bool?, bool?, bool?>> e = (bool? a, bool? b) => a | b;
536 AssertNodeType (e, ExpressionType.Or);
537 Func<bool?, bool?, bool?> c = e.Compile ();
539 Assert (true, c (true, true));
540 Assert (true, c (true, false));
541 Assert (true, c (false, true));
542 Assert (false, c (false, false));
544 Assert (true, c (true, null));
545 Assert (null, c (false, null));
546 Assert (null, c (null, false));
547 Assert (true, c (true, null));
548 Assert (null, c (null, null));
550 Expression<Func<MyType?, MyType?, MyType?>> e2 = (MyType? a, MyType? b) => a | b;
551 AssertNodeType (e2, ExpressionType.Or);
552 var c2 = e2.Compile ();
553 Assert (new MyType (3), c2 (new MyType (1), new MyType (2)));
554 Assert (null, c2 (new MyType (1), null));
560 string InstanceMethod (string arg)
565 object InstanceParamsMethod (int index, params object [] args)
569 if (args.Length == 0)
574 T GenericMethod<T> (T t)
580 public static int Main ()
582 Tester e = new Tester ();
584 e.AndNullableTest ();
589 e.ArrayLengthTest ();
594 e.ConvertCheckedTest ();
597 e.ExclusiveOrTest ();
598 e.GreaterThanTest ();
599 e.GreaterThanOrEqualTest ();
600 e.NewArrayInitTest ();