Ugly Linq
One of the things that always bothered me with Linq was that it is actually not an interesting idea from the compiler perspective. I just had to implement a very simple expression to expression tree converter, which only served to strengthen my opinion. Here is the (ugly, proof of concept, horrible) implementation, using the Boo AST:
private static Block Linqify(Expression expr) { var block = new Block(expr.LexicalInfo); ReferenceExpression condition = AddCondition(block); Parse(block, condition, expr); block.Add(new ReturnStatement(condition)); return block; } private static ReferenceExpression AddCondition(Block block) { var condition = new MethodInvocationExpression(new ReferenceExpression("Condition")); var expression = new ReferenceExpression("condition_" + CompilerContext.Current.AllocIndex()); block.Add( new BinaryExpression( BinaryOperatorType.Assign, expression, condition) ); return expression; } private static void Parse(Block block, Expression condition, Expression expr) { var be = expr as BinaryExpression; if (be != null && (be.Operator == BinaryOperatorType.Or || be.Operator == BinaryOperatorType.And)) { block.Add(new BinaryExpression( BinaryOperatorType.Assign, new MemberReferenceExpression(condition, "Operator"), new StringLiteralExpression(be.Operator.ToString().ToLowerInvariant())) ); ReferenceExpression left = AddCondition(block); block.Add( new MethodInvocationExpression( new MemberReferenceExpression(new MemberReferenceExpression(condition, "Expressions"), "Add"), left)); ReferenceExpression right = AddCondition(block); block.Add( new MethodInvocationExpression( new MemberReferenceExpression(new MemberReferenceExpression(condition, "Expressions"), "Add"), right)); Parse(block, left, be.Left); Parse(block, right, be.Right); return; } var fragment = new MethodInvocationExpression(new ReferenceExpression("Fragment")); if (expr is UnaryExpression) { fragment.NamedArguments.Add( new ExpressionPair(new ReferenceExpression("Modifier"), new StringLiteralExpression("not")) ); be = (BinaryExpression)((UnaryExpression)expr).Operand; } var func1 = (MethodInvocationExpression)be.Left; fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Func1"), new StringLiteralExpression(func1.Target.ToString()))); fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Prop1"), GetStringArgument(func1.Arguments[0]))); var func2 = be.Right as MethodInvocationExpression; if (func2 != null) { fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Func2"), new StringLiteralExpression(func2.Target.ToString()))); fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Prop2"), GetStringArgument(func2.Arguments[0]))); } else { fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Func2"), new StringLiteralExpression("literal"))); fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Prop2"), GetStringArgument(be.Right))); } fragment.NamedArguments.Add(new ExpressionPair(new ReferenceExpression("Operator"), new StringLiteralExpression(GetOperator(be)))); block.Add( new MethodInvocationExpression( new MemberReferenceExpression(new MemberReferenceExpression(condition, "Expressions"), "Add"), fragment)); } private static Expression GetStringArgument(Expression expr) { if (expr is StringLiteralExpression) return expr; return new StringLiteralExpression(expr.ToString()); } private static string GetOperator(BinaryExpression be) { switch (be.Operator) { case BinaryOperatorType.Equality: return "=="; case BinaryOperatorType.Inequality: return "!="; case BinaryOperatorType.Member: return "in"; case BinaryOperatorType.LessThan: return "<"; case BinaryOperatorType.LessThanOrEqual: return "<="; case BinaryOperatorType.GreaterThan: return ">"; case BinaryOperatorType.GreaterThanOrEqual: return ">="; default: throw new NotSupportedException(be.Operator.ToString()); } }
This takes a Boo expression and transform that into the code that creates an object model that represents this expression. Linq is simply an extension to this implementation.

Comments
Comment preview