Tuesday, July 14, 2009 5:07 AM bart

Bart’s Control Library – Not What You Think It Is – part 2

Introduction

In the latest episode in this series I talked about hypothetical compile-time rewriting facilities that would be used to turn our intermediate representation of control-flow driven code using our Control Library into efficient IL code. In a somewhat hand-waving way I communicated the fairly trivial nature of such a translation but as I don’t want to hold any information back, let’s have a look at it today.

But first, refresh your mind on what we’re doing here. Starting from C# code, we’re in the midst of proving we can compile away control flow concepts as a first class citizen in the language and replace them by library calls. Using method calls for such concepts allows for extensibility, e.g. overloading the meaning of “if” when applied to a certain operand (instead of requiring a more generally applicable implicit conversion to Boolean for example). After all, this is more of an academic exercise at this point, but definitely worth the brain cycles.

Once we end up with (control flow library) calls, we’re at a junction. Either we can leave the calls as-is, which means the runtime library will drive the execution. Since this involves calling through delegates, using exceptions for control transfers and gives rise to closure objects that are heap-allocated (hence increasing pressure on the garbage collector) we’re definitely causing a lot of overhead in the regular case. So the alternative is to envision a library implementing such control flow primitives to be able to opt in to “compile-time rewriting” where the compiler would hand over the code in terms of an object model and ask to rewrite it to whatever IL code the library wishes to result. For example:

Measure(“critical region 1”, () =>
{
    // Do whatever you want here.
});

could be compile-time rewritten into (just making up something here):

Measurement m = Measure.Create(“critical region 1”);
try
{
    m.Start();
    // Do whatever you want here.
}
fault
// Non-existing C# construct; exists at IL level.
{
    m.Failed();
}
finally
{
    m.Stop();
}

And if you fantasize about lightweight syntax for block-passing code, you’d end up with something that almost looks like a new keyword:

Measure(“critical region 1”)
{
    // Do whatever you want here.
}

Desirable or not, doesn’t matter. As long as we’re having fun on Crazy Sundays :-). This whole setting is depicted below:

image 

 

A domain-specific rewriter

With .NET 4.0’s introduction of statement trees, all of this is no longer plain fantasy. In fact, as shown in the previous post, we can represent our code fragment for a loop by using the enhanced System.Linq.Expressions API. Below is the fragment we’ve shown before for a simple (though meaningless) loop:

var ctrl = Expression.Parameter(typeof(LoopControl), "ctrl");
var cwi = (from mi in typeof(Console).GetMethods()
           where mi.Name == "WriteLine"
           let p = mi.GetParameters()
           where p.Length == 1 && p[0].ParameterType == typeof(int)
           select mi).Single();
var i = Expression.Variable(typeof(int), "i");
var m = Expression.Block(new [] { i },
    Expression.Assign(i, Expression.Constant(0)),
    Expression.Call(
        typeof(Control).GetMethod("While"),
        Expression.Lambda(Expression.LessThan(i, Expression.Constant(10))),
        Expression.Lambda(
            Expression.Block(
                Expression.Call(cwi, Expression.PostIncrementAssign(i)),
                Expression.Call(
                    typeof(Control).GetMethod("If"),
                    Expression.Lambda(Expression.GreaterThan(i, Expression.Constant(5))),
                    Expression.Lambda(
                        Expression.Call(ctrl, typeof(LoopControl).GetMethod("Break"))
                    )
                ),
                Expression.Call(
                    typeof(Control).GetMethod("If"),
                    Expression.Lambda(
                        Expression.Equal(
                            Expression.Divide(i, Expression.Constant(2)),
                            Expression.Constant(0)
                        )
                    ),
                    Expression.Lambda(
                        Expression.Call(ctrl, typeof(LoopControl).GetMethod("Continue"))
                    )
                ),
                Expression.Call(cwi, i)
            ),
            ctrl
        )
    )
);

Compiling this expression tree to a lambda expression would give us an Action delegate that will print the loop’s output to the screen just fine, if we’ve implemented the Control.While and Control.If methods correctly (as well as the Break and Continue methods used to translate break and continue statements). As we know, that triggers the disadvantageous runtime-driven execution path, so instead we’d like to cross-compile the tree above to the most efficient IL code possible, just as if we had written the loop in the old-style.

For now, we’ll just look at this problem in isolation. In other words, we’re going to write a translator that turns the tree above into another (more efficient, control runtime library independent) tree, but making that translator tied to the Control methods. The way to deal with expression trees is by means of a visitor, which basically walks the tree recursively and allows us to produce a new tree out of it. The visitor pattern is a well-known recipe to do this kind of stuff and in fact .NET 4.0 comes with an ExpressionVisitor base class to write such a visitor:

image

Being an abstract class, the way to use this guy is to derive from it and override any virtual method corresponding to an expression tree node you’re interested in to inspect and/or rewrite during the visitation. On an instance of the resulting visitor you simply call Visit, passing it an expression tree, and out comes a new expression tree that contains the resulting tree:

image

It’s clear our rewriter will have to recognize static methods on the Control type: While and If to keep things simple. When visiting such a node, child nodes will exist for the parameters passed to the method. For If there’s the condition parameter and the body (we’ll ignore a call to Else for sake of simplicity); for While there’s a condition and a body as well. While is a bit different though: when visiting that one’s body, we need to look for other types of method calls, namely the ones that invoke Break or Continue.

Let’s start with the simple part: creating our visitor type, deriving from ExpressionVisitor and overriding the VisitMethodCall method that will be called (recursively) for each method call encountered in the tree:

sealed class MyVisitor : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        return base.VisitMethodCall(node);
    }
}

Can’t get any simpler. In fact this is a no-op visitor; it simply clones the existing tree. The base method call turns the base functionality of the visitor in action. For a MethodCallExpression it visits the expression for the object on which the method is called (if any, a static method won’t have such an object) and the expressions representing the arguments:

image

Of course we want to do something more meaningful. We’ll assume we have the two well-known control flow methods available on the Control type, and want to look for those when called on VisitMethodCall to take appropriate action:

public static void While(this Func<bool> condition, Action<LoopControl> body) { … }
public static IfBlock If(this Func<bool> condition, Action @if) { … }

This switch on method is easy to do as all the information is obviously available in the MethodCallExpression instance that’s passed in:

protected override Expression VisitMethodCall(MethodCallExpression node)
{
    var type = node.Method.DeclaringType;

    if (type == typeof(Control))
    {
        switch (node.Method.Name)
        {
            case "If":
                return VisitIf(node);
            case "While":
                return VisitWhile(node);
            default:
                throw new NotSupportedException("Unknown control flow method encountered: " + node.Method);
        }
    }
    /* more to follow */

    return base.VisitMethodCall(node);
}

This code should be pretty straightforward to grasp. The Method property returns the MethodInfo reflection object representing the method that’s intended to be called by the code represented by the MethodCallExpression node. With DeclaringType and Name properties on this MethodInfo we’re in reflection land, which should be clear to all readers. Next, we simply switch on the method name and dispatch to another helper method. If the declaring type wasn’t (our) Control, we keep our hands off and let the base type visitor implementation do its work. It will simply copy the tree. Such a situation arises for Console.WriteLine calls in our code, or whatever methods calls the user wrote in the code fragment fed in to the visitor.

What’s VisitIf and VisitWhile about? That’s were the magic happens. Here we want to translate the node to a more efficient form that eliminates delegate invocations, use of exceptions and whatnot, substituting it for a plain statement tree node like ConditionalExpression or LoopExpression. Let’s start by VisitIf to set the scene:

private Expression VisitIf(MethodCallExpression node)
{
    var ctrlCondition = (LambdaExpression)node.Arguments[0];
    var ctrlBody = (LambdaExpression)node.Arguments[1];

    var condition = Visit(ctrlCondition.Body);
    var body = Visit(ctrlBody.Body);

    return // What about IfThenElse case? Left as a simple exercise for the reader.
        Expression.IfThen(
            condition,
            body
        );
}

Okay, what about explaining this code based on a sample? Let’s write the following:

var sample =
    Expression.Call(
        typeof(Control).GetMethod("If"),                // Control.If(
        Expression.Lambda(Expression.Constant(true)),   //    () => true,
        Expression.Lambda(Expression.Empty())           //    () => { }
    );                                                  // );

var res = new MyVisitor().Visit(sample);

I can’t get it any simpler. It doesn’t do anything meaningful but will trigger our code:

image

Notice the debug view. The default(Void) represents the empty statement. Let’s have a closer look using the new DebugView property which shows a textual representation of the expression tree:

image

Told you it was a small thing, no? Have a look:

image

.Call, fine enough. To our Control.If method, also fine. Passing in two lambda expressions with some symbolic name. One of type Func<bool> taking in no arguments and producing true, another one of type Action with no arguments and a “void” return value (= nada). Looks good. But what do we want to end up with? Really the code should behave as if the user had written:

if (true)
    ;

instead. This is simply to do: get the body of both lambda expressions and feed them into the Expression.IfThen factory method. One caveat: both bodies could be arbitrarily complex. The “true” condition could in reality be any expression, maybe by itself calling a Control.* method (which seems nonsense here, but let’s go with the flow here). More realistic is the body of the if statement containing another control flow call, like one or more other calls to Control.If or Control.While with arbitrary levels of nesting. In other words, we need to visit the tree recursively:

    var ctrlCondition = (LambdaExpression)node.Arguments[0];
    var ctrlBody = (LambdaExpression)node.Arguments[1];

    var condition = Visit(ctrlCondition.Body);
    var body = Visit(ctrlBody.Body);

But ultimately the promise of Visit is to give us back the translated (sub)tree, so once we’ve done that faithfully, we can starting gluing things together again, this time in a more efficient ConditionalExpression node created by the IfThen factory:

    return // What about IfThenElse case? Left as a simple exercise for the reader.
        Expression.IfThen(
            condition,
            body
        );

And that’s it. Told you it was easy, didn’t I?

A little problem?

In fact we have a little problem. Our Control.If method returns an IfBlock instance, used to (optionally) call Else on. Some fool could write things like:

Control.If(() => Control.If(…, …) != null, () => { … });

Here the Control.If call is used in the context of an expression to be compared against null (or it could even be compared to another If call’s return value, or assigned to a variable, or … oh my). Such uses should be rejected by the visitor to be really precise. However, we assume for now the only way calls to Control.If can occur in the tree is because of some hypothetical front-end language compiler emitting calls to it. Along those lines we assume that front-end doesn’t emit invalid uses. This is naive, but acceptable for the sake of the demo.

Let’s have a peek at the result. Feel free to step through the code line by line, but ultimately inspect the res variable in the Main method where we return from the Visit call:

image

Looks right, doesn’t it? The debug view always shows the .Else case but it’s also supplied with the empty statement, so that’s fine. We’ve compiled away the Control.If call. Wiiii!

Next is the While call. This is a bit more complicated. Not on the level of the call itself, but in the recursive part. Why? Let’s again set the scene by writing total nonsense, but just the bare minimum piece of code illustrating the point:

var @break = typeof(LoopControl).GetMethod("Break");          // LoopControl.Break
var @continue = typeof(LoopControl).GetMethod("Continue");    // LoopControl.Continue

var ctrl = Expression.Parameter(typeof(LoopControl), "ctrl"); // ctrl (lambda parameter for loop body)

var sample =
    Expression.Call(
        typeof(Control).GetMethod("While"),            
//    Control.While(
        Expression.Lambda(Expression.Constant(true)),  
//       ()   => true,
        Expression.Lambda(                              //       ctrl =>
            Expression.Block(                          
// /*     ^   */ {
                Expression.Call(ctrl, @break),         
// /*     |   */      break;
                Expression.Call(ctrl, @continue)       
// /*     |   */      continue;
            ),                                         
// /*     |   */ }
            ctrl                                       
// /* ----+   */
        )                                               //    );
    );

var res = new MyVisitor().Visit(sample);

Okay, it’s a bit bigger but not too bad. Look at the comments to correlate to familiar C# notation. Don’t you love constructor algebraic APIs? Inside the debugger view it may look more manageable:

image

3.14-nuts. A call to Control.While, two arguments. Two lambda expressions again, but now the second one takes an argument of type LoopControl, which as we recall from previous time around is our “handle to the currently executing loop” ready for us to receive Break or Continue calls. And that’s exactly what we’re doing inside the body code block. We just wrote a loop that’s total nonsense in C# and only worth it for its side-effects that originate from evaluating the condition:

while (someExpressionHere)
{
    break;
    continue; // Unreachable code detected.
}

Of course, the real C# compiler would baffle at us:

image

Exercise for the reader

Write a “reachability analysis” visitor to detect control flow library calls that violate unreachable code rules. Or, make it a post-rewriting phase in which you can “simply” look out for GotoExpressions. This is not a trivial exercise at all, so no worries if you don’t get it in a matter of minutes :-). Tip: basic blocks.

Anyway, the point we’re making is this: when recursively visiting the expression for the body of the loop, we need to look out for calls to the Break and Continue methods as well. Not just “calls”, very specific calls. If two loops are nested, with our library one can jump out of a loop other than the immediately enclosing one. So we need to correlate back the call to Break or Continue with the jump target. But first, let’s see how to write a loop in the expression tree API. This will set the direction:

image

Three things are expected from us: a body, a break target label and a continue target label. Here’s the code that creates the minimal loop that loops forever:

var @break = Expression.Label();
var @continue = Expression.Label();

var loop =
    Expression.Loop(
        Expression.Call(
            typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
            Expression.Constant("Forever")
        ),
        @break,
        @continue
    );

Expression.Lambda<Action>(loop).Compile()();

The labels we’re using a simply of type void (that’s what the parameterless overload to Label stands for). You may wonder, why do labels have a type? The deep answer lies in the stack-driven nature of the CLR. If you leave something on the top of the stack at the time you branch somewhere, you better make sure that every path leading to the jump destination has something with a compatible type on top of the stack. Let’s not go there as it would lead us far away from the straight path.

Screams for a debug view one more time? Here it is:

image

Notice where the two labels, #Label1 for continue and #Label2 for break, are put by the Expression.Loop constructor. This is nothing but an infinite loop. So, how to write something real based on this? Like this:

.Loop .LabelTarget #Continue: {
    // Check condition; if not met, jump to #Break
    // Do loop body. Translate break; to jump to #Break and continue; to jump to #Continue.
}
.LabelTarget #Break:

That’s exactly what we’re going to do. The while-loop condition gets negated and put in an if-statement that jumps to the break label if the condition isn’t met (anymore). Then comes the body, which we visit recursively and replace all occurrences of LoopControl.[Break|Continue] calls in by the appropriate jumps. And that’s it.

One more thing we need to do is bookkeeping. Every time we encounter a Control.While(…, ctrl => { /* body */ }) call, we need to correlate the body “ctrl” lambda parameter with the pair of jump labels we’ve associated with the loop. When we encounter a call to either Continue or Break inside the loop body, we map back the loop through the object the method is called on. Doesn’t make sense? Have a look at the following diagram:

image

This happens during the initial translation of a new loop: we add an entry to a table where we keep track of loop control variables and the associated labels we should jump to upon encountering a call to Break or Continue. When we recursively visit the loop body, we need to consult the table to find the right jumping label.

image

This is precisely what our code for VisitWhile does:

  1. It news up labels for the jump targets of the loop. The expression tree API will take care of naming those in a unique way.
  2. The jump labels are stored and associated with the ParameterExpression that was used in the lambda for the body of the loop (second argument to the While call). We use a Tuple<LabelTarget, LabelTarget> to create an ad-hoc type for this duo of labels. Obviously such a mapping is represented by a Dictionary from ParameterExpression on the tuple type.
  3. We visit the condition and loop body recursively while the table contains the entry for the loop. When during this visitation method calls on LoopControl are found, the mapping table is consulted to emit the right jump instruction.
  4. After we’ve done the recursive part, we can clean up the table as nothing outside the loop will be able to jump to any of its labels. This is guaranteed by the fact the lambda parameter for the second parameter is, well, scope to that lambda expression for the body.
  5. Finally we construct the loop expression based on the secret sauce we revealed before: if not condition met, jump to break; otherwise, do loop body.

And here’s the corresponding code for VisitWhile:

private Expression VisitWhile(MethodCallExpression node)
{
    var ctrlCondition = (LambdaExpression)node.Arguments[0];
    var ctrlBody = (LambdaExpression)node.Arguments[1];
    var ctrlParam = ctrlBody.Parameters[0];

    var @break = Expression.Label();
    var @continue = Expression.Label();

    _jumpLabels.Add(ctrlParam, new Tuple<LabelTarget, LabelTarget>(@break, @continue));

    var condition = Visit(ctrlCondition.Body);
    var body = Visit(ctrlBody.Body);

    _jumpLabels.Remove(ctrlParam);

    return
        Expression.Loop(
            Expression.Block(
                Expression.IfThen(
                    Expression.Not(condition),
                    Expression.Goto(@break)
                ),
                body
            ),
            @break, @continue
        );
}

Should look fairly straightforward now, no? What’s _jumpLabels? Simply a field, defined like this:

private Dictionary<ParameterExpression, Tuple<LabelTarget, LabelTarget>> _jumpLabels = new Dictionary<ParameterExpression, Tuple<LabelTarget, LabelTarget>>();

No, no type inference for you there :-). Read this with the table shape in the figure in mind: the key is the lambda parameter, the value is a pair (a two-tuple) of two label target objects. We’re still missing one part: the one that takes care of detecting calls to Break or Continue and takes appropriate action based on the table. Where does that piece of the puzzle go? In our top-level VisitMethodCall method of course:

protected override Expression VisitMethodCall(MethodCallExpression node)
{
    var type = node.Method.DeclaringType;

    if (type == typeof(Control))
    {
        switch (node.Method.Name)
        {
            case "If":
                return VisitIf(node);
            case "While":
                return VisitWhile(node);
            default:
                throw new NotSupportedException("Unknown control flow method encountered: " + node.Method);
        }
    }

    else (type == typeof(LoopControl))
    {
        switch (node.Method.Name)
        {
            case "Break":
                return VisitBreak(node);
            case "Continue":
                return VisitContinue(node);
            default:
                throw new NotSupportedException("Unknown control flow control method encountered: " + node.Method);
        }
    }

    return base.VisitMethodCall(node);
}

Again, we delegate to two helper methods and I dared to refactor it a bit to make it as concise as possible:

private Expression VisitBreak(MethodCallExpression node)
{
    return VisitBreakOrContinue(node, t => t.Item1 /* break */, tgt => Expression.Break(tgt));
}

private Expression VisitContinue(MethodCallExpression node)
{
    return VisitBreakOrContinue(node, t => t.Item2 /* continue */, tgt => Expression.Break(tgt));

}

private Expression VisitBreakOrContinue(MethodCallExpression node, Func<Tuple<LabelTarget, LabelTarget>, LabelTarget> targetLabel, Func<LabelTarget, Expression> ctor)
{
    Tuple<LabelTarget, LabelTarget> targets;
    if (!_jumpLabels.TryGetValue(node.Object as ParameterExpression, out targets))
        throw new InvalidOperationException("Invalid control flow control variable: " + node.Object);

    return ctor(targetLabel(targets));
}

Also excuse me for being a bit lame with the error handling here (the “as” part is not quite ideal, we should throw a more proper exception if this returned null). So, what’s the result of all this fooling around between geeks and expression trees? A screenshot for the lame loop translation will tell:

var @break = typeof(LoopControl).GetMethod("Break");          // LoopControl.Break
var @continue = typeof(LoopControl).GetMethod("Continue");    // LoopControl.Continue

var ctrl = Expression.Parameter(typeof(LoopControl), "ctrl"); // ctrl (lambda parameter for loop body)

var sample =
    Expression.Call(
        typeof(Control).GetMethod("While"),            
//    Control.While(
        Expression.Lambda(Expression.Constant(true)),  
//       ()   => true,
        Expression.Lambda(                              //       ctrl =>
            Expression.Block(                          
// /*     ^   */ {
                Expression.Call(ctrl, @break),         
// /*     |   */      break;
                Expression.Call(ctrl, @continue)       
// /*     |   */      continue;
            ),                                         
// /*     |   */ }
            ctrl                                       
// /* ----+   */
        )                                               //    );
    );

var res = new MyVisitor().Visit(sample);

No, not fake at all:

image

It worked! So, what about our original contrived loop?

Console.WriteLine("Old school: ");
{
    int i = 0;
    while (i < 10)
    {
        Console.WriteLine(i++);
        if (i > 5)
            break;
        if (i % 2 == 0)
            continue;
        Console.WriteLine(i);
    }
}
Console.WriteLine();

Console.WriteLine("New school: ");
{
    int i = 0;
    Console.While(() => i < 10, ctrl =>
    {
        Console.WriteLine(i++);
        Control.If(() => i > 5, () =>
        {
            ctrl.Break();
        });
        Control.If(() => i % 2 == 0, () =>
        {
            ctrl.Continue();
        });
        Console.WriteLine(i);
    });
}
Console.WriteLine();

Console.WriteLine("After rewrite: ");
{
    var m = GetCode();
    var res = new MyVisitor().Visit(m);
    Expression.Lambda<Action>(res).Compile()();
}
Console.WriteLine();

The GetCode method simply returns the “m” expression tree shown near the start of the post, which is the equivalent to the preceding “New school” code. The “res” variable reads the following in the debugger:

image

Looks the same as the plain old loop, doesn’t it?

Exercise for the reader

Does the body of the loop need to have two nested Block expression nodes? Where do those come from? How can you eliminate one of those? Why? Why not?

 

Conclusion

My claim for compile-time rewrite capabilities wasn’t fake. In fact, next time we’ll see how to generalize this notion (with a CompileTimeRewrite attribute tagged onto certain methods) and then we’ll move on to generalizing other control flow constructs. First we’ll look at Do and For, later at Switch (go nuts) and ForEach (“ducks quack”), and even aim for Try, Catch, When, Finally, Fault and Using. What follows after that, I’ll keep secret for now :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# re: Bart’s Control Library – Not What You Think It Is – part 2

Tuesday, July 14, 2009 4:09 PM by Aaron Powell

Don't you require the two block nodes so that the different control operations can be executed (break and continue)?

I *think* you could bring it down to 1 if the continue statement supports fall-through, detecting the ultimate end of the while (yet skipping the logic it's not meant to execute) and going there rather than having a jump point up to the start of the control block.

Does the While visitor handle more than two control statements, say multiple break conditions or multiple continue conditions?

Unrelated question - is the LINQ for SharePoint in SP2010 from your codeplex project? When I heard them talk it up yesterday and say there was a commandline tool "spmetal" I thought "now THAT sounds familiar :P"

# Dew Drop &#8211; July 15, 2009 | Alvin Ashcraft's Morning Dew

Wednesday, July 15, 2009 5:31 AM by Dew Drop – July 15, 2009 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop &#8211; July 15, 2009 | Alvin Ashcraft's Morning Dew

# Bart’s Control Library – Not What You Think It Is – part 2 - Bart De Smet

Wednesday, July 15, 2009 8:38 AM by DotNetShoutout

Thank you for submitting this cool story - Trackback from DotNetShoutout

# re: Bart’s Control Library – Not What You Think It Is – part 2

Thursday, July 16, 2009 5:27 PM by bart

Hi Aaron,

The cosmetic issue with the multiple block nodes comes from the way the rewriter actually inserted the loop's terminating if-statement, continuing with a blind rewrite of the subsequent loop body, which typically is a block node already. In fact, in certain cases (which ones?) excessive use of blocks can be eliminated. Question is why you would want or not want to do such a thing.

Yes, the visitor handles multiple break and continue statements. It's as recursive as it can get, so there shouldn't be a problem with that either.

LINQ to SharePoint is a long story. Maybe I'll blog about that story another time, but yes there have been talks between me and the team that ultimately implemented this feature in SharePoint 2010. Suffice to say they've been doing an outstanding job and I'm glad to see LINQ getting picked up by more teams, really allowing us to redefine the way people think about data access moving forward.

Thanks,

-Bart

# re: Bart’s Control Library – Not What You Think It Is – part 2

Friday, July 17, 2009 1:09 AM by Aaron Powell

If you had mutually exclusive conditional if blocks (if ( i < 5 ) { ... } if (i > 5) { ... }) you could compress them back into a single If{}.Else{} block, but that'd require a lot of evaluation of the different control blocks before parsing which may result in things going pear-shaped long before you get there! :P

I'd be interested in the story of how LINQ to SharePoint become a feature of SP 2010. Ironically a similar thing happened with me and the Umbraco CMS. I was going to write a LINQ provider and now it's part of the core (and I think we'll ship it before SP 2010, first .NET CMS with a OOB LINQ provider as far as I know :P).

Hanging out for part 3 + source code ;)

# re: Bart’s Control Library – Not What You Think It Is – part 2

Saturday, July 18, 2009 5:47 AM by bart

Hi Aaron,

Mutually exclusive blocks, sure that would work, but on the other hand it's not semantics preserving in the general case. The condition could well be side-effecting and moving it into an else block would remove that side-effect from the original code flow path. On the other hand, you'd likely only perform such optimizations for known types where no such side-effects exist :-). It's definitely doable to create such a thing as part of the optimizer.

To clarify the LINQ to SharePoint story a tiny little bit: by the time I arrived at Microsoft in October 2007, a team was already working on such a provider. So I shared my experiences with them and ultimately it ended up in the product. The code base is totally fresh compared to the CodePlex one (a good thing as the Codeplex one needed lots of refinement and cleanup and was more of a POC).

Part 3 coming up some time soon.

Thanks,

-Bart