7 people like it.

Translating quotations to LINQ

A sample that translates simple F# quotations (method calls, property getters) to stnadard C# LINQ expression trees.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations

/// Translates simple F# quotation to LINQ expression
/// (the function supports only variables, property getters,
/// method calls and static method calls)
let rec translateSimpleExpr expr =
  match expr with
  | Patterns.Var(var) ->
      // Variable access
      Expression.Variable(var.Type, var.Name) :> Expression
  | Patterns.PropertyGet(Some inst, pi, []) ->
      // Getter of an instance property
      let instExpr = translateSimpleExpr inst
      Expression.Property(instExpr, pi) :> Expression
  | Patterns.Call(Some inst, mi, args) ->
      // Method call - translate instance & arguments recursively
      let argsExpr = Seq.map translateSimpleExpr args
      let instExpr = translateSimpleExpr inst
      Expression.Call(instExpr, mi, argsExpr) :> Expression
  | Patterns.Call(None, mi, args) ->
      // Static method call - no instance
      let argsExpr = Seq.map translateSimpleExpr args
      Expression.Call(mi, argsExpr) :> Expression
  | _ -> failwith "not supported"

/// Translates a simple F# quotation to a lambda expression
let translateLambda (expr:Expr<'T -> 'R>) =
  match expr with
  | Patterns.Lambda(v, body) ->
      // Build LINQ style lambda expression
      let bodyExpr = translateSimpleExpr body
      let paramExpr = Expression.Parameter(v.Type, v.Name)
      Expression.Lambda<Func<'T, 'R>>(paramExpr)
  | _ -> failwith "not supported"
namespace System
namespace System.Linq
namespace System.Linq.Expressions
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Quotations
val translateSimpleExpr : expr:Expr -> Expression

Full name: Script.translateSimpleExpr


 Translates simple F# quotation to LINQ expression
 (the function supports only variables, property getters,
 method calls and static method calls)
val expr : Expr
module Patterns

from Microsoft.FSharp.Quotations
active recognizer Var: Expr -> Var option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Var|_| )
val var : Var
Multiple items
type Expression =
  member CanReduce : bool
  member NodeType : ExpressionType
  member Reduce : unit -> Expression
  member ReduceAndCheck : unit -> Expression
  member ReduceExtensions : unit -> Expression
  member ToString : unit -> string
  member Type : Type
  static member Add : left:Expression * right:Expression -> BinaryExpression + 1 overload
  static member AddAssign : left:Expression * right:Expression -> BinaryExpression + 2 overloads
  static member AddAssignChecked : left:Expression * right:Expression -> BinaryExpression + 2 overloads
  ...

Full name: System.Linq.Expressions.Expression

--------------------
type Expression<'TDelegate> =
  inherit LambdaExpression
  member Compile : unit -> 'TDelegate + 1 overload
  member Update : body:Expression * parameters:IEnumerable<ParameterExpression> -> Expression<'TDelegate>

Full name: System.Linq.Expressions.Expression<_>
Expression.Variable(type: Type) : ParameterExpression
Expression.Variable(type: Type, name: string) : ParameterExpression
property Var.Type: Type
property Var.Name: string
active recognizer PropertyGet: Expr -> (Expr option * Reflection.PropertyInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |PropertyGet|_| )
union case Option.Some: Value: 'T -> Option<'T>
val inst : Expr
val pi : Reflection.PropertyInfo
val instExpr : Expression
Expression.Property(expression: Expression, propertyAccessor: Reflection.MethodInfo) : MemberExpression
Expression.Property(expression: Expression, property: Reflection.PropertyInfo) : MemberExpression
Expression.Property(expression: Expression, propertyName: string) : MemberExpression
Expression.Property(expression: Expression, type: Type, propertyName: string) : MemberExpression
Expression.Property(instance: Expression, indexer: Reflection.PropertyInfo, arguments: Collections.Generic.IEnumerable<Expression>) : IndexExpression
Expression.Property(instance: Expression, indexer: Reflection.PropertyInfo, [<ParamArray>] arguments: Expression []) : IndexExpression
Expression.Property(instance: Expression, propertyName: string, [<ParamArray>] arguments: Expression []) : IndexExpression
active recognizer Call: Expr -> (Expr option * Reflection.MethodInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Call|_| )
val mi : Reflection.MethodInfo
val args : Expr list
val argsExpr : seq<Expression>
module Seq

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
Expression.Call(instance: Expression, method: Reflection.MethodInfo) : MethodCallExpression
   (+0 other overloads)
Expression.Call(method: Reflection.MethodInfo, arguments: Collections.Generic.IEnumerable<Expression>) : MethodCallExpression
   (+0 other overloads)
Expression.Call(method: Reflection.MethodInfo, [<ParamArray>] arguments: Expression []) : MethodCallExpression
   (+0 other overloads)
Expression.Call(method: Reflection.MethodInfo, arg0: Expression) : MethodCallExpression
   (+0 other overloads)
Expression.Call(instance: Expression, method: Reflection.MethodInfo, arguments: Collections.Generic.IEnumerable<Expression>) : MethodCallExpression
   (+0 other overloads)
Expression.Call(instance: Expression, method: Reflection.MethodInfo, [<ParamArray>] arguments: Expression []) : MethodCallExpression
   (+0 other overloads)
Expression.Call(method: Reflection.MethodInfo, arg0: Expression, arg1: Expression) : MethodCallExpression
   (+0 other overloads)
Expression.Call(type: Type, methodName: string, typeArguments: Type [], [<ParamArray>] arguments: Expression []) : MethodCallExpression
   (+0 other overloads)
Expression.Call(instance: Expression, methodName: string, typeArguments: Type [], [<ParamArray>] arguments: Expression []) : MethodCallExpression
   (+0 other overloads)
Expression.Call(instance: Expression, method: Reflection.MethodInfo, arg0: Expression, arg1: Expression) : MethodCallExpression
   (+0 other overloads)
union case Option.None: Option<'T>
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val translateLambda : expr:Expr<('T -> 'R)> -> Expression<Func<'T,'R>>

Full name: Script.translateLambda


 Translates a simple F# quotation to a lambda expression
val expr : Expr<('T -> 'R)>
Multiple items
type Expr =
  override Equals : obj:obj -> bool
  member GetFreeVars : unit -> seq<Var>
  member Substitute : substitution:(Var -> Expr option) -> Expr
  member ToString : full:bool -> string
  member CustomAttributes : Expr list
  member Type : Type
  static member AddressOf : target:Expr -> Expr
  static member AddressSet : target:Expr * value:Expr -> Expr
  static member Application : functionExpr:Expr * argument:Expr -> Expr
  static member Applications : functionExpr:Expr * arguments:Expr list list -> Expr
  ...

Full name: Microsoft.FSharp.Quotations.Expr

--------------------
type Expr<'T> =
  inherit Expr
  member Raw : Expr

Full name: Microsoft.FSharp.Quotations.Expr<_>
active recognizer Lambda: Expr -> (Var * Expr) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Lambda|_| )
val v : Var
val body : Expr
val bodyExpr : Expression
val paramExpr : ParameterExpression
Expression.Parameter(type: Type) : ParameterExpression
Expression.Parameter(type: Type, name: string) : ParameterExpression
Expression.Lambda(body: Expression, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : LambdaExpression
   (+0 other overloads)
Expression.Lambda(body: Expression, [<ParamArray>] parameters: ParameterExpression []) : LambdaExpression
   (+0 other overloads)
Expression.Lambda<'TDelegate>(body: Expression, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : Expression<'TDelegate>
   (+0 other overloads)
Expression.Lambda<'TDelegate>(body: Expression, [<ParamArray>] parameters: ParameterExpression []) : Expression<'TDelegate>
   (+0 other overloads)
Expression.Lambda(body: Expression, name: string, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : LambdaExpression
   (+0 other overloads)
Expression.Lambda(delegateType: Type, body: Expression, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : LambdaExpression
   (+0 other overloads)
Expression.Lambda(delegateType: Type, body: Expression, [<ParamArray>] parameters: ParameterExpression []) : LambdaExpression
   (+0 other overloads)
Expression.Lambda(body: Expression, tailCall: bool, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : LambdaExpression
   (+0 other overloads)
Expression.Lambda(body: Expression, tailCall: bool, [<ParamArray>] parameters: ParameterExpression []) : LambdaExpression
   (+0 other overloads)
Expression.Lambda<'TDelegate>(body: Expression, name: string, parameters: Collections.Generic.IEnumerable<ParameterExpression>) : Expression<'TDelegate>
   (+0 other overloads)
Multiple items
type Func<'TResult> =
  delegate of unit -> 'TResult

Full name: System.Func<_>

--------------------
type Func<'T,'TResult> =
  delegate of 'T -> 'TResult

Full name: System.Func<_,_>

--------------------
type Func<'T1,'T2,'TResult> =
  delegate of 'T1 * 'T2 -> 'TResult

Full name: System.Func<_,_,_>

--------------------
type Func<'T1,'T2,'T3,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 -> 'TResult

Full name: System.Func<_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 -> 'TResult

Full name: System.Func<_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> 'TResult

Full name: System.Func<_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>
Raw view Test code New version

More information

Link:http://fssnip.net/c6
Posted:12 years ago
Author:Tomas Petricek
Tags: meta-programming , quotations , linq , expression