15 people like it.

Eval Quotations

Evaluates a useful subset of F# quotations at run-time (without the F# PowerPack API).

Evaluate expression

 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: 
open System
open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

/// Evaluates expression untyped
let rec eval = function
    | Value(v,t) -> v
    | Coerce(e,t) -> eval e
    | NewObject(ci,args) -> ci.Invoke(evalAll args)
    | NewArray(t,args) -> 
        let array = Array.CreateInstance(t, args.Length) 
        args |> List.iteri (fun i arg -> array.SetValue(eval arg, i))
        box array
    | NewUnionCase(case,args) -> FSharpValue.MakeUnion(case, evalAll args)
    | NewRecord(t,args) -> FSharpValue.MakeRecord(t, evalAll args)
    | NewTuple(args) ->
        let t = FSharpType.MakeTupleType [|for arg in args -> arg.Type|]
        FSharpValue.MakeTuple(evalAll args, t)
    | FieldGet(Some(Value(v,_)),fi) -> fi.GetValue(v)
    | PropertyGet(None, pi, args) -> pi.GetValue(null, evalAll args)
    | PropertyGet(Some(x),pi,args) -> pi.GetValue(eval x, evalAll args)
    | Call(None,mi,args) -> mi.Invoke(null, evalAll args)
    | Call(Some(x),mi,args) -> mi.Invoke(eval x, evalAll args)
    | arg -> raise <| NotSupportedException(arg.ToString())
and evalAll args = [|for arg in args -> eval arg|]

Unit tests

 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: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
open NUnit.Framework

type Tests () =
    static member Expressions = 
        let (==) quote value = TestCaseData([|quote|]).Returns(value)
        [
        <@ 1 @> == 1
        <@ 1 + 1 @> == 2
        <@ 2 * 2 @> == 4
        <@ 9.9M @> == 9.9M
        <@ "Hello World" @> == "Hello World"
        <@ [1;2;3] @> == [1;2;3]
        <@ [|1;2;3|] @> == [|1;2;3|]
        <@ (1,2,3) @> == (1,2,3)
        <@ Some(1) @> == Some(1)
        <@ {Name="Phil"; Age=27} @> == {Name = "Phil"; Age=27}
        <@ PersonClass("Phil", 27) @> == PersonClass("Phil", 27)
        ]        
    
    [<Test;TestCaseSource("Expressions")>]
    static member ``evaluates`` (expr:Expr) = eval expr

    member test.LocalProperty = 1

    [<Test>]
    member test.``local property getter`` () =
        Assert.AreEqual(test.LocalProperty, eval <@ test.LocalProperty @>)

    member test.LocalMethod() = 1

    [<Test>]
    member test.``local property method`` () =
        Assert.AreEqual(test.LocalMethod(), eval <@ test.LocalMethod() @>)

    static member GlobalProperty = 1

    [<Test>]
    member test.``global property getter`` () =
        Assert.AreEqual(Tests.GlobalProperty, eval <@ Tests.GlobalProperty @>)

    static member GlobalMethod() = 1

    [<Test>]
    member test.``global property method`` () =
        Assert.AreEqual(Tests.GlobalMethod(), eval <@ Tests.GlobalMethod() @>)
namespace System
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
namespace Microsoft.FSharp.Quotations
module Patterns

from Microsoft.FSharp.Quotations
val eval : _arg1:Expr -> obj

Full name: Script.eval


 Evaluates expression untyped
active recognizer Value: Expr -> (obj * Type) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Value|_| )
val v : obj
val t : Type
active recognizer Coerce: Expr -> (Expr * Type) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Coerce|_| )
val e : Expr
active recognizer NewObject: Expr -> (Reflection.ConstructorInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |NewObject|_| )
val ci : Reflection.ConstructorInfo
val args : Expr list
Reflection.ConstructorInfo.Invoke(parameters: obj []) : obj
Reflection.MethodBase.Invoke(obj: obj, parameters: obj []) : obj
Reflection.ConstructorInfo.Invoke(invokeAttr: Reflection.BindingFlags, binder: Reflection.Binder, parameters: obj [], culture: Globalization.CultureInfo) : obj
Reflection.MethodBase.Invoke(obj: obj, invokeAttr: Reflection.BindingFlags, binder: Reflection.Binder, parameters: obj [], culture: Globalization.CultureInfo) : obj
val evalAll : args:Expr list -> obj []

Full name: Script.evalAll
active recognizer NewArray: Expr -> (Type * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |NewArray|_| )
Multiple items
val array : Array

--------------------
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
Array.CreateInstance(elementType: Type, [<ParamArray>] lengths: int64 []) : Array
Array.CreateInstance(elementType: Type, [<ParamArray>] lengths: int []) : Array
Array.CreateInstance(elementType: Type, length: int) : Array
Array.CreateInstance(elementType: Type, lengths: int [], lowerBounds: int []) : Array
Array.CreateInstance(elementType: Type, length1: int, length2: int) : Array
Array.CreateInstance(elementType: Type, length1: int, length2: int, length3: int) : Array
property List.Length: int
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val iteri : action:(int -> 'T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iteri
val i : int
val arg : Expr
Array.SetValue(value: obj, [<ParamArray>] indices: int64 []) : unit
Array.SetValue(value: obj, index: int64) : unit
Array.SetValue(value: obj, [<ParamArray>] indices: int []) : unit
Array.SetValue(value: obj, index: int) : unit
Array.SetValue(value: obj, index1: int64, index2: int64) : unit
Array.SetValue(value: obj, index1: int, index2: int) : unit
Array.SetValue(value: obj, index1: int64, index2: int64, index3: int64) : unit
Array.SetValue(value: obj, index1: int, index2: int, index3: int) : unit
val box : value:'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
active recognizer NewUnionCase: Expr -> (UnionCaseInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |NewUnionCase|_| )
val case : UnionCaseInfo
type FSharpValue =
  static member GetExceptionFields : exn:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetRecordField : record:obj * info:PropertyInfo -> obj
  static member GetRecordFields : record:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetTupleField : tuple:obj * index:int -> obj
  static member GetTupleFields : tuple:obj -> obj []
  static member GetUnionFields : value:obj * unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo * obj []
  static member MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
  static member MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:BindingFlags -> obj
  static member MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
  static member MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:BindingFlags -> obj
  ...

Full name: Microsoft.FSharp.Reflection.FSharpValue
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?allowAccessToPrivateRepresentation:bool -> obj
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:Reflection.BindingFlags -> obj
active recognizer NewRecord: Expr -> (Type * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |NewRecord|_| )
static member FSharpValue.MakeRecord : recordType:Type * values:obj [] * ?allowAccessToPrivateRepresentation:bool -> obj
static member FSharpValue.MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:Reflection.BindingFlags -> obj
active recognizer NewTuple: Expr -> Expr list option

Full name: Microsoft.FSharp.Quotations.Patterns.( |NewTuple|_| )
type FSharpType =
  static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetFunctionElements : functionType:Type -> Type * Type
  static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetTupleElements : tupleType:Type -> Type []
  static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
  static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
  static member IsFunction : typ:Type -> bool
  static member IsModule : typ:Type -> bool
  static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
  static member IsTuple : typ:Type -> bool
  ...

Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.MakeTupleType : types:Type [] -> Type
property Expr.Type: Type
static member FSharpValue.MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
active recognizer FieldGet: Expr -> (Expr option * Reflection.FieldInfo) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |FieldGet|_| )
union case Option.Some: Value: 'T -> Option<'T>
val fi : Reflection.FieldInfo
Reflection.FieldInfo.GetValue(obj: obj) : obj
active recognizer PropertyGet: Expr -> (Expr option * Reflection.PropertyInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |PropertyGet|_| )
union case Option.None: Option<'T>
val pi : Reflection.PropertyInfo
Reflection.PropertyInfo.GetValue(obj: obj, index: obj []) : obj
Reflection.PropertyInfo.GetValue(obj: obj, invokeAttr: Reflection.BindingFlags, binder: Reflection.Binder, index: obj [], culture: Globalization.CultureInfo) : obj
val x : Expr
active recognizer Call: Expr -> (Expr option * Reflection.MethodInfo * Expr list) option

Full name: Microsoft.FSharp.Quotations.Patterns.( |Call|_| )
val mi : Reflection.MethodInfo
Reflection.MethodBase.Invoke(obj: obj, parameters: obj []) : obj
Reflection.MethodBase.Invoke(obj: obj, invokeAttr: Reflection.BindingFlags, binder: Reflection.Binder, parameters: obj [], culture: Globalization.CultureInfo) : obj
val raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type NotSupportedException =
  inherit SystemException
  new : unit -> NotSupportedException + 2 overloads

Full name: System.NotSupportedException

--------------------
NotSupportedException() : unit
NotSupportedException(message: string) : unit
NotSupportedException(message: string, innerException: exn) : unit
Object.ToString() : string
member Expr.ToString : full:bool -> string
namespace NUnit
namespace NUnit.Framework
Multiple items
type Tests =
  new : unit -> Tests
  member LocalMethod : unit -> int
  member LocalProperty : int
  member ( global property getter ) : unit -> unit
  member ( global property method ) : unit -> unit
  member ( local property getter ) : unit -> unit
  member ( local property method ) : unit -> unit
  static member GlobalMethod : unit -> int
  static member evaluates : expr:Expr -> obj
  static member Expressions : TestCaseData list
  ...

Full name: Script.Tests

--------------------
new : unit -> Tests
static member Tests.Expressions : TestCaseData list

Full name: Script.Tests.Expressions
val quote : obj
val value : 'a
Multiple items
type TestCaseData =
  new : [<ParamArray>] args:obj[] -> TestCaseData + 3 overloads
  member Arguments : obj[]
  member Categories : IList
  member Description : string
  member ExpectedException : Type
  member ExpectedExceptionName : string
  member Explicit : bool
  member HasExpectedResult : bool
  member Ignore : unit -> TestCaseData + 1 overload
  member IgnoreReason : string
  ...

Full name: NUnit.Framework.TestCaseData

--------------------
TestCaseData([<ParamArray>] args: obj []) : unit
TestCaseData(arg: obj) : unit
TestCaseData(arg1: obj, arg2: obj) : unit
TestCaseData(arg1: obj, arg2: obj, arg3: obj) : unit
Multiple items
type PersonClass =
  new : name:string * age:int -> PersonClass
  override Equals : b:obj -> bool
  override GetHashCode : unit -> int
  member Age : int
  member Name : string

Full name: Script.PersonClass

--------------------
new : name:string * age:int -> PersonClass
Multiple items
type TestAttribute =
  inherit Attribute
  new : unit -> TestAttribute
  member Description : string with get, set

Full name: NUnit.Framework.TestAttribute

--------------------
TestAttribute() : unit
Multiple items
type TestCaseSourceAttribute =
  inherit Attribute
  new : sourceName:string -> TestCaseSourceAttribute + 2 overloads
  member Category : string with get, set
  member SourceName : string
  member SourceType : Type

Full name: NUnit.Framework.TestCaseSourceAttribute

--------------------
TestCaseSourceAttribute(sourceName: string) : unit
TestCaseSourceAttribute(sourceType: Type) : unit
TestCaseSourceAttribute(sourceType: Type, sourceName: string) : unit
val expr : Expr
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<_>
val test : Tests
member Tests.LocalProperty : int

Full name: Script.Tests.LocalProperty
member Tests.( local property getter ) : unit -> unit

Full name: Script.Tests.( local property getter )
type Assert =
  static member AreEqual : expected:int * actual:int -> unit + 23 overloads
  static member AreNotEqual : expected:int * actual:int -> unit + 23 overloads
  static member AreNotSame : expected:obj * actual:obj -> unit + 2 overloads
  static member AreSame : expected:obj * actual:obj -> unit + 2 overloads
  static member ByVal : actual:obj * expression:IResolveConstraint -> unit + 2 overloads
  static member Catch : code:TestDelegate -> Exception + 8 overloads
  static member Contains : expected:obj * actual:ICollection -> unit + 2 overloads
  static member Counter : int
  static member DoesNotThrow : code:TestDelegate -> unit + 2 overloads
  static member Equals : a:obj * b:obj -> bool
  ...

Full name: NUnit.Framework.Assert
Assert.AreEqual(expected: obj, actual: obj) : unit
   (+0 other overloads)
Assert.AreEqual(expected: decimal, actual: decimal) : unit
   (+0 other overloads)
Assert.AreEqual(expected: uint64, actual: uint64) : unit
   (+0 other overloads)
Assert.AreEqual(expected: uint32, actual: uint32) : unit
   (+0 other overloads)
Assert.AreEqual(expected: int64, actual: int64) : unit
   (+0 other overloads)
Assert.AreEqual(expected: int, actual: int) : unit
   (+0 other overloads)
Assert.AreEqual(expected: obj, actual: obj, message: string) : unit
   (+0 other overloads)
Assert.AreEqual(expected: float, actual: Nullable<float>, delta: float) : unit
   (+0 other overloads)
Assert.AreEqual(expected: float, actual: float, delta: float) : unit
   (+0 other overloads)
Assert.AreEqual(expected: decimal, actual: decimal, message: string) : unit
   (+0 other overloads)
property Tests.LocalProperty: int
member Tests.LocalMethod : unit -> int

Full name: Script.Tests.LocalMethod
member Tests.( local property method ) : unit -> unit

Full name: Script.Tests.( local property method )
member Tests.LocalMethod : unit -> int
static member Tests.GlobalProperty : int

Full name: Script.Tests.GlobalProperty
member Tests.( global property getter ) : unit -> unit

Full name: Script.Tests.( global property getter )
property Tests.GlobalProperty: int
static member Tests.GlobalMethod : unit -> int

Full name: Script.Tests.GlobalMethod
member Tests.( global property method ) : unit -> unit

Full name: Script.Tests.( global property method )
static member Tests.GlobalMethod : unit -> int
Raw view Test code New version

More information

Link:http://fssnip.net/h1
Posted:11 years ago
Author:Phillip Trelford
Tags: quotations , compilation , run time