Skip to content

Instantly share code, notes, and snippets.

@mjul
Created April 15, 2016 10:55
Show Gist options
  • Save mjul/9596111798e37567513c79618fe38810 to your computer and use it in GitHub Desktop.
Save mjul/9596111798e37567513c79618fe38810 to your computer and use it in GitHub Desktop.
F# Quoted Expressions (writing a compiler)
// F# Quoted Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Quotations.DerivedPatterns
// A typed code quotation.
let expr : Expr<int> = <@ 1 + 1 @>
// An untyped code quotation.
let expr2 : Expr = <@@ 1 + 1 @@>
/// Abstract Syntax Tree for our Lisp
module Lisp =
type Literal =
| String of string
| Integer of int
| Symbol of string
type Expression =
| Literal of Literal
| List of Expression list
let rec formatExpression (e:Expression) =
match e with
| List exprs ->
sprintf "(%s)" ((Seq.map formatExpression exprs) |> String.concat " " )
| Literal (String s) ->
let quoted = s.Replace("\"","\\\"")
sprintf "\"%s\"" quoted
| Literal (Integer i) -> sprintf "%d" i
| Literal (Symbol name) -> sprintf "%s" name
/// Given an F# expression, compile it to a Lisp expression
let rec lisp expr =
match expr with
| Application (expr1, expr2) ->
// function Application
Lisp.List([lisp expr1; lisp expr2])
| SpecificCall <@@ (+) @@> (_, _, exprList) ->
let exprs = exprList |> List.map lisp
Lisp.List (List.append [Lisp.Literal (Lisp.Symbol "+")] exprs)
| Int32(n) ->
Lisp.Literal (Lisp.Integer n)
| String(s) ->
Lisp.Literal (Lisp.String s)
| x ->
failwith "unknown expression: %A"
lisp <@ 1 + (2 + 3)@> |> Lisp.formatExpression
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment