-
Notifications
You must be signed in to change notification settings - Fork 146
/
Copy pathQuotationHelpers.fs
47 lines (36 loc) · 1.87 KB
/
QuotationHelpers.fs
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
46
namespace FSharp.Data.Sql
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Reflection
module QuotationHelpers =
let rec coerceValues fieldTypeLookup fields =
Array.mapi (fun i v ->
let expr =
if isNull v then simpleTypeExpr v
elif FSharpType.IsUnion (v.GetType()) then unionExpr v |> snd
elif FSharpType.IsRecord (v.GetType()) then recordExpr v |> snd
else simpleTypeExpr v
Expr.Coerce(expr, fieldTypeLookup i)
) fields |> List.ofArray
and simpleTypeExpr instance = Expr.Value(instance)
and unionExpr instance =
let caseInfo, fields = FSharpValue.GetUnionFields(instance, instance.GetType())
let fieldInfo = caseInfo.GetFields()
let fieldTypeLookup indx = fieldInfo.[indx].PropertyType
caseInfo.DeclaringType, Expr.NewUnionCase(caseInfo, coerceValues fieldTypeLookup fields)
and recordExpr instance =
let tpy = instance.GetType()
let fields = FSharpValue.GetRecordFields(instance)
let fieldInfo = FSharpType.GetRecordFields(tpy)
let fieldTypeLookup indx = fieldInfo.[indx].PropertyType
tpy, Expr.NewRecord(instance.GetType(), coerceValues fieldTypeLookup fields)
and arrayExpr (instance : 'a array) =
let typ = typeof<'a>
let arrayType = instance.GetType()
let exprs = coerceValues (fun _ -> typ) (instance |> Array.map box)
arrayType, Expr.NewArray(typ, exprs)
let inline internal createLetExpr varType instance body args =
let var = Var("instance", varType)
Expr.Let(var, instance, body args (Expr.Var(var)))
let quoteUnion instance = unionExpr instance ||> createLetExpr
let quoteRecord instance = recordExpr instance ||> createLetExpr
let quoteArray instance = arrayExpr instance ||> createLetExpr