<Query Kind="FSharpProgram">
  <Reference>FSharp.Core.dll</Reference>
  <Reference>FSharp.Quotations.Evaluator.dll</Reference>
  <AppConfig>
    <Content>
      <configuration>
        <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
              <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
              <bindingRedirect oldVersion="0.0.0.0-9.9.9.9" newVersion="4.5.0.0" />
            </dependentAssembly>
          </assemblyBinding>
          <gcServer enabled="true" />
        </runtime>
      </configuration>
    </Content>
  </AppConfig>
</Query>

open System
open System.Threading
open System.Threading.Tasks
open System.Runtime
open FSharp.Quotations.Evaluator
open Microsoft.FSharp.Quotations

let tid () = Thread.CurrentThread.ManagedThreadId

// code as data
// http://fsprojects.github.io/FSharp.Quotations.Evaluator/tutorial.html

let x = QuotationEvaluator.Evaluate <@ 1 + 1 @>
printfn "x: %d" x

let evalTuple n = 
    let v = Expr.NewTuple (List.replicate n (Expr.Value n)) // codegen (fun x -> (x,x))
    v.EvaluateUntyped() 

let y4 = evalTuple 4 // obj = (4,4,4,4)
let y5 = evalTuple 5 // obj = (5,5,5,5,5)
printfn "y4: %A, y5: %A" y4 y5

let addPlusOne = QuotationEvaluator.Evaluate <@ fun x y -> x + y + 1 @> 

let z = addPlusOne 3 5 // 9
printfn "z: %d" z

let onePlusTwoExpression = <@ 1 + 2 @>  //  2
let expressionTree = onePlusTwoExpression.ToLinqExpressionUntyped() // an expression tree
let s = expressionTree.ToString() // "(1 + 2)"
printfn "s: %s" s
//