< Summary - FSharp.Interop.Dlr

Information
Class: FSharp.Interop.Dlr.Translate
Assembly: FSharp.Interop.Dlr
File(s): /home/runner/work/FSharp.Interop.Dlr/FSharp.Interop.Dlr/FSharp.Interop.Dlr/Translate.fs
Line coverage
96%
Covered lines: 210
Uncovered lines: 7
Coverable lines: 217
Total lines: 328
Line coverage: 96.7%
Branch coverage
91%
Covered branches: 206
Total branches: 226
Branch coverage: 91.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%210%
translate(...)86.84%383898.36%
Invoke(...)100%22100%
isCaptured@148(...)100%22100%
Invoke(...)100%22100%
isBuilder@150(...)100%22100%
Invoke(...)94.44%909096.87%
rewriteIn@158(...)95.83%969698.3%
Invoke(...)66.66%983663.63%
tupleVar@175(...)76.31%473881.81%
Invoke(...)100%1010100%
subst@211(...)100%1010100%
Invoke(...)100%11100%
readCell@226(...)100%11100%
Invoke(...)100%11100%
viaCells@227(...)100%11100%
Invoke(...)100%11100%
Invoke(...)100%66100%
unitBranches@263(...)100%66100%
Invoke(...)50%5466.66%
peel@274(...)50%5466.66%

File(s)

/home/runner/work/FSharp.Interop.Dlr/FSharp.Interop.Dlr/FSharp.Interop.Dlr/Translate.fs

#LineLine coverage
 1namespace FSharp.Interop.Dlr
 2
 3open System
 4open System.Linq.Expressions
 5open FSharp.Quotations
 6open FSharp.Quotations.Patterns
 7open FSharp.Quotations.DerivedPatterns
 8open FSharp.Quotations.ExprShape
 9open FSharp.Reflection
 10open Microsoft.FSharp.Linq.RuntimeHelpers
 11open System.Runtime.CompilerServices
 12
 13/// Turns the reflected body of a `dlr { }` block into a delegate over the block's compiler-generated
 14/// container — a `DlrReader<'SM, 'T>` over its state machine struct, or a `Func<obj, 'T>` over its
 15/// Delay closure — with the DLR call sites baked in as constants.
 16module internal Translate =
 17    open TranslatePatterns
 18    open SiteHoisting
 19    open TranslateBlock
 20    open TranslateMembers
 21
 22    /// A compiled `dlr { }` site: a `DlrReader<'SM, 'T>` over the state machine struct, or in the
 23    /// fallback path a `Func<obj, 'T>` over the Delay closure object.
 24    type Compiled = { Delegate: Delegate }
 25
 26    /// Receives each block's expression tree, with the block's container type, once its sites are
 27    /// hoisted: on the state-machine path that is before the by-reference wrapper, which only
 28    /// copies the machine into the lambda's `sm` and is what `Compile()` then gets. Null, and then
 29    /// free, unless set: `docs/trees` sets it by reflection to generate the docs' examples.
 030    type TreeHook private () =
 31        static member val Sink : Action<Type, LambdaExpression> = null with get, set
 32
 33    /// Compiles the reflected body of one `dlr { }` block. `closureType` is the block's
 34    /// compiler-generated container — its state machine struct, or in the fallback path the
 35    /// class of its `Delay` closure: its fields, named after the captured variables, are where
 36    /// the body's free variables are read from at call time.
 37    let translate (name: string) (builderType: Type) (context: Type) (memberBody: Expr) (closureType: Type) (resultType:
 2668638        let closure = if closureType.IsValueType then Var("sm", closureType) else Var("closure", typeof<obj>)
 1334339        let fields = Captures.fields closureType
 1334340        let reached, aliases = Captures.reached fields memberBody body
 41        // Only an optimized build substitutes or splits a variable: the state machine, or in Release
 42        // the closure of `(dlr { … } : unit -> R) ()`.
 43        // The F# optimizer ran: it substitutes and captures variables of its own (#280). A Debug
 44        // build that makes state machines (the 8.0, 9.0 and 11.0 compilers) does not.
 1334345        let optimizerRan =
 1334346            not (closureType.Assembly.GetCustomAttributes(typeof<Diagnostics.DebuggableAttribute>, false)
 3337347                 |> Seq.exists (fun a -> (a :?> Diagnostics.DebuggableAttribute).IsJITOptimizerDisabled))
 2231448        let optimized = closureType.IsValueType || optimizerRan
 1334349        let block =
 1334350            { BuilderType = builderType
 1334351              Context = context
 1334352              MemberBody = memberBody
 1334353              ClosureType = closureType
 1334354              Closure = closure
 1334355              Fields = fields
 1334356              Substituted = aliases
 1334357              Ambiguous =
 1334358                  reached
 7245859                  |> List.countBy (fun v -> v.Name) |> List.filter (fun (_, n) -> n > 1) |> List.map fst |> Set.ofList
 1334360                  // Only an optimized build splits a tuple (the state machine, or in Release the closure
 1334361                  // of `(dlr { … } : unit -> R) ()`), and not one it captures whole as a field.
 1334362                  |> Set.union (
 3738363                      if optimized then Captures.elementNameClashes (fun t -> not (fields.ContainsKey t)) memberBody els
 1334364                  // Another variable of a reached name, which the definition of a value the block
 1334365                  // reads whole was built from (a tuple, a record, a union case): the optimizer may
 1334366                  // know an element is that variable and capture it too, named `y`, `y0`, … in an
 1334367                  // order of its own, so the block's own `y` read by name may get it, whatever the
 1334368                  // optimizer did to the block's `y` (#280). And a field `y0`, `y1`, … that no
 1334369                  // reached variable is named, beside a reached `y`: a second `y` captured some
 1334370                  // other way. Both refused.
 1334371                  |> Set.union (
 2003072                      if not optimizerRan then Set.empty
 1334373                      else
 1808474                          let names = reached |> List.map (fun v -> v.Name) |> Set.ofList
 1334375                          // A reached variable and what it renames, `let y = y` (a `let!` in a task
 1334376                          // binds its value so): one value under one name.
 1334377                          let own =
 1334378                              let rec renames (v: Var) =
 1143279                                  match TranslatePatterns.letDefinition v memberBody with
 7580                                  | Some(Var w) when not v.IsMutable && not w.IsMutable && w.Name = v.Name && w <> v -> 
 1142881                                  | _ -> [ v ]
 665682                              reached |> List.collect renames |> Set.ofList
 1334383                          // The variables a reached field's value holds as an element, through
 1334384                          // immutable lets, projections and tuple, record and union-case
 1334385                          // construction: what the optimizer can take back out of it. A variable a
 1334386                          // computation used (`y * 2`) it cannot.
 1334387                          let rec elementsOf (seen: Set<Var>) (e: Expr) : Set<Var> =
 477088                              match e with
 190189                              | Var v when not v.IsMutable && not (seen.Contains v) ->
 189790                                  let seen = seen.Add v
 1334391                                  // A local function's parameter is its one call's argument.
 189792                                  match TranslatePatterns.letDefinition v memberBody |> Option.orElse (TranslatePatterns
 166093                                  | Some d -> elementsOf seen d
 23794                                  | None -> seen
 66995                              | NewTuple es | NewRecord(_, es) | NewUnionCase(_, es) -> List.fold elementsOf seen es
 37896                              | PropertyGet(Some inner, _, []) | TupleGet(inner, _) | Coerce(inner, _) -> elementsOf see
 182697                              | _ -> seen
 1334398                          // Whether the block's compiled code takes `r` apart, where the optimizer
 1334399                          // can put an element's variable in its place: anything but `r` whole as
 13343100                          // a dynamic call's target or argument (boxed or not), which it passes as
 13343101                          // it is. One the block reaches only through a definition counts as apart.
 13343102                          let apart (r: Var) =
 13343103                              let rec go (whole: bool) (e: Expr) =
 42641104                                  match e with
 19821105                                  | Var v -> v = r && not whole
 13343106                                  | MemberOp(InvokeMember(target, name, args)) ->
 4224107                                      go true target || go false name
 2061108                                      || (match args with
 863109                                          | NewTuple items -> List.exists (go true) items
 1198110                                          | a -> go true a)
 2407111                                  | MemberOp(GetMember(target, name)) -> go true target || go false name
 396112                                  | MemberOp(SetMember(target, name, value)) -> go true target || go false name || go tr
 204113                                  | Coerce(inner, _) -> go whole inner
 2105114                                  | Call(None, mi, [ inner ]) when mi.DeclaringType.FullName = "Microsoft.FSharp.Core.Op
 0115                                  | ShapeVar _ -> false
 4346116                                  | ShapeLambda(_, b) -> go false b
 19033117                                  | ShapeCombination(_, es) -> List.exists (go false) es
 4269118                              not (body.GetFreeVars() |> Seq.contains r) || go false body
 13343119                          // A reached variable read from fields: its own, or its elements' (a split
 13343120                          // tuple).
 13343121                          let held (r: Var) =
 25546122                              fields.ContainsKey r.Name || (Captures.elementField fields r 0).IsSome || (Captures.elemen
 13343123                          // Of another type, a field holding it is refused by `Captures.read`'s
 13343124                          // type check, never read (a match's own `matchValue` beside a user's,
 13343125                          // #281 corpus); a ref cell of the type is read through.
 13343126                          let readAs (w: Var) =
 357127                              reached |> List.exists (fun v ->
 1011128                                  v.Name = w.Name
 411129                                  && (v.Type = w.Type || (w.Type.IsGenericType && w.Type.GetGenericTypeDefinition() = ty
 6656130                          let flowsIn =
 24740131                              set [ for r in reached do
 27246132                                      if held r && apart r then
 6814133                                          for w in elementsOf Set.empty (Expr.Var r) do
 11206134                                              if w <> r && not (own.Contains w) && readAs w then yield w.Name ]
 6656135                          let secondCapture =
 24722136                              set [ for n in names do
 22820137                                      if fields.Keys |> Seq.exists (fun f ->
 12975138                                             f.Length > n.Length && f.StartsWith(n, StringComparison.Ordinal)
 81139                                             && f |> Seq.skip n.Length |> Seq.forall Char.IsDigit
 22847140                                             && not (names.Contains f)) then
 6674141                                          yield n ]
 13343142                          Set.union flowsIn secondCapture)
 13343143              Name = name
 13343144              Names = Collections.Generic.Dictionary() }
 145
 146        /// Variables bound inside the expression being rewritten are left alone; anything else
 147        /// that is not the builder comes from the closure or the enclosing member.
 43814148        let isCaptured (bound: Set<Var>) (v: Var) = not (bound.Contains v) && v.Type <> block.BuilderType
 149
 150        let isBuilder (receiver: Expr option) =
 64349151            match receiver with
 24404152            | Some r -> r.Type = block.BuilderType
 39945153            | None -> false
 154
 155        /// Builder calls and marker operations go to their sections; everything else is generic
 156        /// rewriting: captured variables become closure reads, and the structure is rebuilt as-is
 157        /// except where the expression tree has no form for it.
 158        let rec rewriteIn (bound: Set<Var>) (e: Expr) : Expr =
 238112159            let rewrite = rewriteIn bound
 238112160            match e with
 85556161            | Call(receiver, mi, args) when isBuilder receiver -> Plumbing.call block rewriteIn bound mi args e
 162            | _ ->
 216905163            match Members.tryOperation block rewriteIn bound e with
 15784164            | Some rewritten -> rewritten
 165            | None ->
 166            // A mutable struct captured from outside the block, mutated in place (see `inPlace`).
 202594167            match inPlace (fun v -> isCaptured bound v && Captures.isCell block v) (Captures.read block rewrite) (Captur
 42168            | Some written -> written
 169            | None ->
 170            // An element of a captured tuple the optimizer split into a field per element, read
 171            // directly or through what it inlines: a local function applied to unit, or an
 172            // immutable alias of an immutable variable (that value) whose name is no other's. An
 173            // alias with a field of its own is read through it: a field `y_0` beside it is then a
 174            // user's variable, not the split of `y` (#267).
 175            let rec tupleVar (e: Expr) : Var option =
 2751176                match e with
 2976177                | Var v when isCaptured bound v && FSharp.Reflection.FSharpType.IsTuple v.Type ->
 231178                    match letDefinition v memberBody with
 48179                    | Some(Var y as d) when block.Substituted.Contains v || (not v.IsMutable && not y.IsMutable && not (
 0180                        tupleVar d |> Option.orElse (Some v)
 231181                    | _ -> Some v
 18182                | Application(Var f, Value(_, t)) when t = typeof<unit> && isCaptured bound f && not (block.Fields.Conta
 3183                    match letDefinition f memberBody with
 3184                    | Some(Lambda(_, b)) -> tupleVar b
 0185                    | _ -> None
 2517186                | _ -> None
 187            let element =
 200884188                match e with
 189                | TupleGet(inner, i) ->
 3786190                    tupleVar inner |> Option.bind (fun v -> Captures.element block v i)
 15002191                | Call(None, mi, [ inner ]) when mi.DeclaringType.FullName = "Microsoft.FSharp.Core.Operators" && (mi.Na
 1038192                    tupleVar inner |> Option.bind (fun v -> Captures.element block v (if mi.Name = "Fst" then 0 else 1))
 198136193                | _ -> None
 200875194            match element with
 30195            | Some read -> read
 196            | None ->
 200845197            match e with
 72365198            | Var v when isCaptured bound v -> Captures.read block (rewriteIn bound) v
 390199            | VarSet(v, value) when isCaptured bound v -> Captures.assign block v (rewrite value)
 52755200            | ShapeVar _ -> e
 201            // A resumable-code-typed leftover of the builder's shape (see `codeType`): the
 202            // compiler's `null` after the rethrow in an unmatched `try … with` arm.
 3711203            | Value(null, t) when isCode t -> defaultOf (codeType t)
 204            // A `let mutable` of the block has no expression-tree form: loop and try bodies are
 205            // compiled into delegates, and a tree variable cannot be assigned from inside one. So
 206            // it lives in a reference cell, as the compiler does for a captured mutable, with
 207            // reads and writes going through the cell.
 20322208            | Let(v, def, letBody) when v.IsMutable ->
 2722209                let cell = Var(v.Name, typedefof<Ref<_>>.MakeGenericType v.Type)
 2722210                let value = cell.Type.GetProperty("Value")
 211                let rec subst (e: Expr) =
 77806212                    match inPlace ((=) v) (fun _ -> Expr.PropertyGet(Expr.Var cell, value)) (fun _ x -> Expr.PropertySet
 1440213                    | Some written -> written
 214                    | None ->
 73486215                    match e with
 3872216                    | VarSet(v', x) when v' = v -> Expr.PropertySet(Expr.Var cell, value, subst x)
 26596217                    | Var v' when v' = v -> Expr.PropertyGet(Expr.Var cell, value)
 67762218                    | _ -> Quotation.rebuild subst e
 2722219                Expr.Let(cell, Expr.NewObject(cell.Type.GetConstructor([| v.Type |]), [ rewrite def ]), rewriteIn (bound
 17600220            | Let(v, def, letBody) -> Expr.Let(v, rewrite def, rewriteIn (bound.Add v) letBody)
 221            // `let rec` has no expression-tree form; tie the knot through reference cells, as the
 222            // compiler does: each binding becomes a cell, uses read the cell, and the definitions
 223            // are assigned after all cells exist so mutual recursion works too.
 224            | LetRecursive(bindings, letBody) ->
 930225                let cells = [ for (v, _) in bindings -> v, Var(v.Name + "'", typedefof<Ref<_>>.MakeGenericType v.Type) ]
 375226                let readCell (cell: Var) = Expr.PropertyGet(Expr.Var cell, cell.Type.GetProperty("Value"))
 5856227                let viaCells (e: Expr) = e.Substitute(fun v -> cells |> List.tryFind (fun (rv, _) -> rv = v) |> Option.m
 459228                let bound = cells |> List.fold (fun (b: Set<Var>) (_, c) -> b.Add c) bound
 180229                let assignments =
 555230                    [ for (_, def), (_, cell) in List.zip bindings cells ->
 375231                        Expr.PropertySet(Expr.Var cell, cell.Type.GetProperty("Value"), rewriteIn bound (viaCells def)) 
 180232                let body = rewriteIn bound (viaCells letBody)
 279233                let inner = List.foldBack (fun assign rest -> Expr.Sequential(assign, rest)) assignments body
 180234                List.foldBack
 180235                    (fun (v: Var, cell: Var) rest ->
 195236                        Expr.Let(cell, Expr.NewObject(cell.Type.GetConstructor [| v.Type |], [ Expr.Value(null, v.Type) 
 180237                    cells inner
 238            // A `try` that is not the builder's (under a lambda, inside a delegate literal, or a
 239            // `try … with` used as a value): LeafExpressionConverter has no form for it, so it runs
 240            // through the same delegates as the block's own (#158). F#'s filter only repeats the
 241            // handler's match, which ends in `reraise ()` where no case fits; the handler alone does.
 242            | TryWith(body, _, _, ex, handler) ->
 384243                let func = Plumbing.func block rewriteIn bound
 768244                Expr.Call(tryWith.MakeGenericMethod(e.Type), [ func [] body; func [ ex ] (Plumbing.rethrowing ex handler
 245            // `while` and `for i in a .. b` that are not the builder's (under a lambda, in a delegate
 246            // literal, inside an expression): no LINQ form either, so the same delegates (#162).
 247            | WhileLoop(guard, body) ->
 72248                let func = Plumbing.func block rewriteIn bound
 144249                Expr.Call(whileLoop, [ func [] guard; func [] body ])
 250            | ForIntegerRangeLoop(i, low, high, body) ->
 75251                let func = Plumbing.func block rewriteIn bound
 150252                Expr.Call(forRange, [ rewrite low; rewrite high; func [ i ] body ])
 272253            | PrimitiveRange(typed, args) -> Expr.Call(typed, List.map rewrite args)
 254            // An element of a struct tuple: the converter's TupleGet looks for a reference tuple's
 255            // property and rejects a ValueTuple's index (#162), so it is the field itself
 256            // (`Item1`…`Item7`, then `Rest`), as the byref holder reads it.
 2520257            | TupleGet(tuple, index) when tuple.Type.IsValueType ->
 720258                Binders.byRefHolderPath tuple.Type index |> List.fold (fun e f -> Expr.FieldGet(e, f)) (rewrite tuple)
 259            | TryFinally(body, compensation) ->
 150260                let func = Plumbing.func block rewriteIn bound
 261                // `use`'s compensation is `if (d :? IDisposable) then d.Dispose() else ()`: a void
 262                // call and `()` as the branches, which the converter rejects as mismatched.
 263                let rec unitBranches (c: Expr) =
 600264                    match c with
 300265                    | IfThenElse(cond, a, b) when c.Type = typeof<unit> -> Expr.IfThenElse(cond, unitBranches a, unitBra
 600266                    | _ when isUnitCall c -> Expr.Sequential(c, Expr.Value(()))
 300267                    | _ -> c
 300268                Expr.Call(tryFinally.MakeGenericMethod(e.Type), [ func [] body; func [] (unitBranches compensation) ])
 269            | NewDelegate(t, vars, delegateBody) ->
 270                // A delegate literal's lambda is the delegate itself, not an F# function: keep it
 271                // whole (on wasm, made capturing: see `capturing`). The quotation may give the
 272                // parameters as nested lambdas in the body rather than in `vars`.
 1546273                let n = (DelegateMembers.invokeOf t).GetParameters().Length
 274                let rec peel k (e: Expr) acc =
 1546275                    match e with
 0276                    | Lambda(v, b) when k > 0 -> peel (k - 1) b (v :: acc)
 1546277                    | _ -> List.rev acc, e
 1546278                let peeled, body = peel (n - vars.Length) delegateBody []
 1546279                let allVars = vars @ peeled
 4135280                let inner = allVars |> List.fold (fun b v -> Set.add v b) bound
 1546281                let body = capturing block (asUnit (rewriteIn inner body))
 282                // .NET Framework's Expression.Lambda finds `Invoke` by public lookup only, and an F#
 283                // `internal` delegate's is internal: there, the lambda is at the public delegate type
 284                // of the same signature and the delegate is bound over it (#125). Past sixteen
 285                // parameters that stand-in is emitted at run time, which a quotation must not name
 286                // on wasm (see Binders.WideSite) — never reached there: .NET Framework only.
 1546287                let standIn = DelegateMembers.standIn t
 1546288                let literalOf = typedefof<DelegateLiteral<_>>.MakeGenericType t
 1546289                match standIn with
 16290                | Some standIn -> Expr.Call(literalOf.GetMethod("From"), [ Expr.Coerce(Expr.NewDelegate(standIn, allVars
 291                // Re-wrapped so `.Method` is the delegate type's own `Invoke` (see `DelegateLiteral`).
 1530292                | None -> Expr.Call(literalOf.GetMethod("Over"), [ Expr.NewDelegate(t, allVars, body) ])
 19974293            | ShapeLambda(v, lambdaBody) -> Expr.Lambda(v, capturing block (asUnit (rewriteIn (bound.Add v) lambdaBody))
 294            // A void call where a `unit` value is expected (`ignore (list.Add x)`, `f (list.Add x)`):
 295            // the converter has no value for it, so run it, then `()`.
 47629296            | Call(receiver, mi, args) when args |> List.exists isUnitCall ->
 21297                let args' = args |> List.map (fun a -> if isUnitCall a then asUnit (rewrite a) else rewrite a)
 6298                match receiver with
 0299                | Some r -> Expr.Call(rewrite r, mi, args')
 6300                | None -> Expr.Call(mi, args')
 1005301            | Application(f, arg) when isUnitCall arg -> Expr.Application(rewrite f, asUnit (rewrite arg))
 94074302            | _ -> Quotation.rebuild rewrite e
 303
 13343304        let delegateType = typedefof<Func<_, _>>.MakeGenericType(closure.Type, resultType)
 305        let compiled =
 13343306            try
 13343307                let rewritten = asUnit (rewriteIn Set.empty (normalize body))
 13109308                let lambda = Expr.NewDelegate(delegateType, [ closure ], rewritten)
 13109309                let linq = LeafExpressionConverter.QuotationToExpression lambda :?> LambdaExpression
 13109310                let hoisted = nameNested block.NameFor (SiteHoister().Visit linq :?> LambdaExpression)
 13109311                match TreeHook.Sink with
 13103312                | null -> ()
 6313                | sink -> sink.Invoke(closureType, hoisted)
 13103314                if closureType.IsValueType then
 315                    // The machine comes by reference (a quotation variable cannot be byref):
 316                    // copy it into the by-value local the body was converted against. A byref
 317                    // cannot be closed over, and the copy is free; the reads are off the local.
 4270318                    let machine = hoisted.Parameters.[0]
 4270319                    let byRef = Expression.Parameter(closureType.MakeByRefType(), "machine")
 4270320                    let readerType = typedefof<DlrReader<_, _>>.MakeGenericType(closureType, resultType)
 4270321                    Expression.Lambda(readerType, Expression.Block(resultType, [ machine ], Expression.Assign(machine, b
 8833322                else Expression.Lambda(hoisted.Type, hoisted.Body, name, hoisted.Parameters).Compile()
 474323            with :? DlrTranslationException -> reraise ()
 324               // A static member resolved here by reflection and missing is the binder's kind of
 325               // error, as it would be at the call for an instance target.
 0326               | :? Microsoft.CSharp.RuntimeBinder.RuntimeBinderException -> reraise ()
 6327               | ex -> raise (DlrTranslationException(sprintf "dlr { } could not compile this body: %s\n%A" ex.Message b
 13262328        { Delegate = compiled }

Methods/Properties

.ctor()
translate(System.String,System.Type,System.Type,Microsoft.FSharp.Quotations.FSharpExpr,System.Type,System.Type,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpVar)
isCaptured@148(FSharp.Interop.Dlr.TranslateBlock/Block,Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpVar)
Invoke(Microsoft.FSharp.Core.FSharpOption`1<Microsoft.FSharp.Quotations.FSharpExpr>)
isBuilder@150(FSharp.Interop.Dlr.TranslateBlock/Block,Microsoft.FSharp.Core.FSharpOption`1<Microsoft.FSharp.Quotations.FSharpExpr>)
Invoke(Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
rewriteIn@158(Microsoft.FSharp.Quotations.FSharpExpr,FSharp.Interop.Dlr.TranslateBlock/Block,Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr)
tupleVar@175(Microsoft.FSharp.Quotations.FSharpExpr,FSharp.Interop.Dlr.TranslateBlock/Block,Microsoft.FSharp.Collections.FSharpSet`1<Microsoft.FSharp.Quotations.FSharpVar>,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr)
subst@211(Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpVar,System.Reflection.PropertyInfo,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Quotations.FSharpVar)
readCell@226(Microsoft.FSharp.Quotations.FSharpVar)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr)
viaCells@227(Microsoft.FSharp.Collections.FSharpList`1<System.Tuple`2<Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpVar>>,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(Microsoft.FSharp.Quotations.FSharpExpr)
unitBranches@263(Microsoft.FSharp.Quotations.FSharpExpr)
Invoke(System.Int32,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Quotations.FSharpVar>)
peel@274(System.Int32,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Collections.FSharpList`1<Microsoft.FSharp.Quotations.FSharpVar>)