|
1 | 1 | # RoslynPad Utility |
2 | 2 |
|
3 | | -TODO |
4 | | - |
5 | | -Code editor for expressions |
6 | | -Use of Roslyn workspace services |
7 | | -Optional reference to Microsoft.CSharp.Expressions |
8 | | -Reduce, optimize, and evaluate support |
9 | | -Tree visualization |
10 | | -C# and IL decompilers |
11 | | -Save/load snippets |
| 3 | +RoslynPad is a utility that enables compiling C# snippets that construct expression trees. For example: |
| 4 | + |
| 5 | +```csharp |
| 6 | +(Expression<Func<int>>)(() => 42) |
| 7 | +``` |
| 8 | + |
| 9 | +This tools enables inspection of the expression tree code generated by the Roslyn fork in this repo, including support for C# language constructs that are currently not supported in expression trees (i.e. C# 4.0, 5.0, and 6.0 features). An example is shown below: |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +In here, we use the C# 6.0 null-propagating `?.` operator, which is not supported in expression trees. By selecting `Include Microsoft.CSharp.Expressions`, support for this language construct is enabled. |
| 14 | + |
| 15 | +Looking at the `Tree` tab, we can see the new `CSharpExpression` nodes being used to represent the `?.` expression: |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +Clicking on the `Reduce` button will trigger lowering of the new nodes to the original `System.Linq.Expressions` node types, thus proving that all new nodes can be built on top of the existing facilities in the .NET standard libraries: |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +Therefore, all new expressions can be compiled and evaluated as well, including very complex expressions using statement nodes and `async` lambdas. Consider the following example: |
| 24 | + |
| 25 | +```csharp |
| 26 | +(Expression<Func<int, int, Task<List<int>>>>)(async (int min, int max) => |
| 27 | +{ |
| 28 | + var primes = new List<int>(); |
| 29 | + |
| 30 | + for (int i = min; i <= max; i++) |
| 31 | + { |
| 32 | + await Task.Delay(i); |
| 33 | + |
| 34 | + bool found = false; |
| 35 | + |
| 36 | + for (int d = 2; d <= Math.Sqrt(i); d++) |
| 37 | + { |
| 38 | + if (i % d == 0) |
| 39 | + { |
| 40 | + found = true; |
| 41 | + break; |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + if (!found) |
| 46 | + { |
| 47 | + primes.Add(i); |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + return primes; |
| 52 | +}) |
| 53 | +``` |
| 54 | + |
| 55 | +which contains a ton of constructs not supported in expression trees today, including statements (`if`, `for`, `return`, `break`), `async` lambdas, `await` expressions, etc. Compiling this "just works" (yes, also for any awaitable type, and for task-like return types): |
| 56 | + |
| 57 | + |
| 58 | + |
| 59 | +and reduction generates the familiar async state machine that turns the async lambda into a regular lambda: |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +If you look carefully at the image above, you'll see familiar things such as `__state` variables, `AsyncTaskMethodBuilder` construction, etc. It goes without saying the evaluation "just works": |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +Finally, RoslynPad has a decompiler: |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +and IL visualizer: |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +which can be used to evaluate the efficiency of the generated code. The `Optimize` button illustrates another expression tree optimizer library (orthogonal to the Roslyn language bindings and even the `Microsoft.CSharp.Expressions` library; i.e. it works for any existing expression tree and operates on lowered forms) which could be considered for inclusion in .NET metaprogramming facilities. |
| 76 | + |
| 77 | +TODO - further detailed descriptions of: |
| 78 | + |
| 79 | +* Code editor for expressions |
| 80 | +* Use of Roslyn workspace services |
| 81 | +* Optional reference to Microsoft.CSharp.Expressions |
| 82 | +* Reduce, optimize, and evaluate support |
| 83 | +* Tree visualization |
| 84 | +* C# and IL decompilers |
| 85 | +* Save/load snippets |
0 commit comments