-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for generating F# quotations and Linq expressions (Expr and Expression) #29
Comments
Possible, yes. Easy, probably not. Nice idea though. I'll mark it as up for grabs :) |
This looks like an interesting idea 😃 – I'm just trying to understand how this could possibly work. Assuming a quotation which represents a variable open Microsoft.FSharp.Quotations
let xvar = Expr.Var(Var("x", typeof<int>)) |> Expr.Cast
// -> val xvar : Expr<int> and a quotation with the let q = <@ %xvar + 10 @>
// -> val q : Expr<int> Now, open Swensen.Unquote
let actual = q |> evalWith (Map.ofList [("x", box 2)]) So the actual value can be verified like so: open Swensen.Unquote.Assertions
test <@ 2 + 10 = actual @> In the above scenario, where could FsCheck kick-in?
|
I imagined this as a generator for the The reason I called this not easy is because essentially, this amounts to generating arbitrary typechecked F# code - though of course initial implementations can be much simpler and still useful. For example: generating arithmetic expressions, boolean expressions, sequence of method calls starting from a given type |
I would have some use for this. Not for Expr but System.Linq.Expressions (.NET lambda expressions) but basically it's the same... open System
open System.Linq.Expressions
let rnd = System.Random()
let someStopCondition = rnd.NextDouble() > 0.8
/// Usage: randomExpressionType()
let randomExpressionType =
let expTypes = Enum.GetValues(typeof<ExpressionType>)
fun () -> expTypes.GetValue(rnd.Next(expTypes.Length)) :?> ExpressionType Now, the expression tree end-node-types are always either ConstantExpressions or ParameterExpressions: Expression.Constant(rnd.NextDouble() > 0.5, typeof<bool>) :> Expression
Expression.Parameter(typeof<bool>, "p1") Bool should be supported first and then maybe int. Now, if you have created the sub-expression, then you could recursively create a little random tree surrounding it: upcast Expression.MakeUnary(e.NodeType, createSub e.Operand,e.Type,e.Method)
upcast Expression.MakeBinary(e.NodeType, createSub e.Left, createSub e.Right)
upcast Expression.TypeIs(createSub e.Expression, e.TypeOperand)
upcast Expression.Condition(createSub e.Test, createSub e.IfTrue, createSub e.IfFalse)
upcast Expression.MakeMemberAccess(createSub e.Expression, e.Member)
upcast Expression.Call(createSub e.Object, e.Method, e.Arguments |> Seq.map(fun a -> createSub a))
upcast Expression.Lambda(e.Type, createSub e.Body, e.Parameters)
upcast Expression.New(e.Constructor, e.Arguments |> Seq.map(fun a -> createSub a))
upcast Expression.New(e.Constructor, e.Arguments |> Seq.map(fun a -> createSub a), e.Members)
upcast Expression.NewArrayBounds(e.Type.GetElementType(), e.Expressions |> Seq.map(fun e -> createSub e))
upcast Expression.NewArrayInit(e.Type.GetElementType(), e.Expressions |> Seq.map(fun e -> createSub e))
upcast Expression.Invoke(createSub e.Expression, e.Arguments |> Seq.map(fun a -> createSub a))
upcast Expression.MemberInit( (createSub e.NewExpression) :?> NewExpression , e.Bindings)
upcast Expression.ListInit( (createSub e.NewExpression) :?> NewExpression, e.Initializers) Of course this would be just random little expressions. |
Yes, I saw a propietary version of an Funny you mentioned minikanren: https://github.com/kurtschelfthout/fslogic :) |
No description provided.
The text was updated successfully, but these errors were encountered: