Skip to content

Instantly share code, notes, and snippets.

@jdh30
Created March 26, 2017 00:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdh30/01964c37221b6fea817bc1bf029e47c0 to your computer and use it in GitHub Desktop.
Save jdh30/01964c37221b6fea817bc1bf029e47c0 to your computer and use it in GitHub Desktop.
Reverse polish compiler in F# using LLVM, derived from this 35-line Racket example http://beautifulracket.com/stacker/source-listing.html
let (|Int|_|) s =
let mutable x = 0
if System.Int32.TryParse(s, &x) then Some x else None
LLVM.NativeLibrary.LLVMDLL.Load()
LLVM.Target.InitializeNative()
let context = LLVM.Context.Global
let i32 = LLVM.IntegerType.GetInt32 context
let compile lines : System.Func<int> =
let mdl = LLVM.Module("main", context)
let ee = LLVM.ExecutionEngine mdl
let fnType = LLVM.FunctionType i32
let fn = mdl.CreateFunction("calc", fnType)
let blk = LLVM.Block("blk", context, fn)
let gen = LLVM.InstructionBuilder(context, blk)
let constant x = i32.Constant(uint64 x, true) :> LLVM.Value
let rec (|Parse|) = function
| Int x::t -> constant x, t
| "+"::Parse(x, Parse(y, t)) -> gen.Add(x, y), t
| "*"::Parse(x, Parse(y, t)) -> gen.Multiply(x, y), t
let (Parse(f, _)) = lines
ignore(gen.Return f)
let interop = LLVM.Interop.ClrInterop ee
interop.GetDelegate(fn, mdl)
let lines = stdin.ReadToEnd().Split '\n' |> List.ofSeq |> List.rev
printfn "%d" ((compile lines).Invoke())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment