Skip to content

Instantly share code, notes, and snippets.

@manofstick
Created March 17, 2016 20:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manofstick/44d76e6f5cbdb514387e to your computer and use it in GitHub Desktop.
Save manofstick/44d76e6f5cbdb514387e to your computer and use it in GitHub Desktop.
open FSharp.Quotations
let rec getMethodInfo = function
| Patterns.Call(_,``method``,_) -> ``method``
| Patterns.Lambda(_,body) -> getMethodInfo body
| _ -> failwith "Unexpected Form"
let getGenericMethodInfo functionExpression =
let methodInfo = getMethodInfo functionExpression
if methodInfo.IsGenericMethod then
methodInfo.GetGenericMethodDefinition ()
else
methodInfo
let ``-> +`` = getGenericMethodInfo <@ (+) @>
let ``-> *`` = getGenericMethodInfo <@ (*) @>
let add (lhs:Expr, rhs) = Expr.Call (``-> +``.MakeGenericMethod [|lhs.Type; lhs.Type; lhs.Type|], [lhs; rhs])
let mult (lhs:Expr, rhs) = Expr.Call (``-> *``.MakeGenericMethod [|lhs.Type; lhs.Type; lhs.Type|], [lhs; rhs])
open FParsec
let parseExpression, implementation = createParserForwardedToRef ()
let parseConstant = pfloat |>> Expr.Value
let xVariable = Var("x", typeof<float>)
let parseVariable = stringReturn "x" (Expr.Var xVariable)
let parseExpressionsPair =
between
(pstring "(")
(pstring ")")
(tuple2
(parseExpression .>> pstring ",")
parseExpression)
let parseAddition =
pstring "add" >>.
parseExpressionsPair
|>> add
let parseMultiplication =
pstring "mul" >>.
parseExpressionsPair
|>> mult
implementation := parseVariable <|> parseConstant <|> parseAddition <|> parseMultiplication
type Program () =
member this.Run (x:float,code:string) =
match (run parseExpression code) with
| Failure(message,_,_) ->
printfn "Malformed code: %s" message
| Success(expression,_,_) ->
let asLambda = Expr.Cast (Expr.Lambda (xVariable, expression))
let f = FSharp.Quotations.Evaluator.QuotationEvaluator.Evaluate asLambda
let result = f x
printfn "Result: %.2f" result
let program = Program()
let code = "add(x,mul(x,42))"
program.Run(10.0,code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment