diff --git a/README.md b/README.md
index 0ac9992b..56181f0c 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,26 @@ stack build
stack exec -- grin grin/grin/opt-stages-high-level/stage-00.grin
```
+## nix
+
+To get a nix shell with all the required dependencies do the following in the top level folder.
+
+```
+nix-shell
+```
+
+To run the example do the following from the top level folder.
+
+```
+(cd grin; cabal run grin -- grin/opt-stages-high-level/stage-00.grin)
+```
+
+To run a local Hoogle server with Haskell documentation do the following.
+
+```
+hoogle server --port 8087 1>/dev/null 2>/dev/null&
+```
+
## Example Front-End
Read about how to generate GRIN code from a frontend language.
diff --git a/grin/default.nix b/grin/default.nix
new file mode 100644
index 00000000..f552ee06
--- /dev/null
+++ b/grin/default.nix
@@ -0,0 +1,40 @@
+{ mkDerivation, ansi-wl-pprint, base, bimap, bytestring, comonad
+, containers, criterion, deepseq, directory, extra, filepath, free
+, functor-infix, generic-random, ghc, ghc-paths, haskeline, hspec
+, hspec-discover, idris, llvm-hs, llvm-hs-pretty, llvm-hs-pure
+, logict, megaparsec, microlens, microlens-mtl, microlens-platform
+, microlens-th, monad-gen, mtl, neat-interpolation
+, optparse-applicative, pretty-show, pretty-simple, process
+, QuickCheck, recursion-schemes, stdenv, template-haskell, text
+, transformers, unix, vector
+}:
+mkDerivation {
+ pname = "grin";
+ version = "0.1.0.0";
+ src = ./.;
+ isLibrary = true;
+ isExecutable = true;
+ libraryHaskellDepends = [
+ ansi-wl-pprint base bimap bytestring comonad containers deepseq
+ directory extra filepath free functor-infix generic-random ghc
+ hspec idris llvm-hs llvm-hs-pretty llvm-hs-pure logict megaparsec
+ microlens microlens-mtl microlens-platform microlens-th monad-gen
+ mtl neat-interpolation optparse-applicative pretty-show
+ pretty-simple process QuickCheck recursion-schemes template-haskell
+ text transformers vector
+ ];
+ executableHaskellDepends = [
+ ansi-wl-pprint base containers directory filepath ghc ghc-paths
+ haskeline idris llvm-hs-pretty megaparsec microlens microlens-mtl
+ microlens-platform microlens-th mtl optparse-applicative
+ pretty-show pretty-simple process recursion-schemes text
+ transformers unix
+ ];
+ testHaskellDepends = [
+ base containers deepseq functor-infix hspec hspec-discover
+ QuickCheck vector
+ ];
+ benchmarkHaskellDepends = [ base criterion ];
+ homepage = "https://github.com/githubuser/grin#readme";
+ license = stdenv.lib.licenses.bsd3;
+}
diff --git a/nix/free.nix b/nix/free.nix
new file mode 100644
index 00000000..958978b6
--- /dev/null
+++ b/nix/free.nix
@@ -0,0 +1,20 @@
+{ mkDerivation, base, bifunctors, comonad, containers, distributive
+, exceptions, mtl, prelude-extras, profunctors, semigroupoids
+, semigroups, stdenv, template-haskell, transformers
+, transformers-compat
+}:
+mkDerivation {
+ pname = "free";
+ version = "4.12.4";
+ sha256 = "c9fe45aae387855626ecb5a0fea6afdb207143cb00af3b1f715d1032d2d08784";
+ revision = "2";
+ editedCabalFile = "0gmib9bmswrqhl47cp5b871v9f44v9yidzxpljkszy49y9qdf560";
+ libraryHaskellDepends = [
+ base bifunctors comonad containers distributive exceptions mtl
+ prelude-extras profunctors semigroupoids semigroups
+ template-haskell transformers transformers-compat
+ ];
+ homepage = "http://github.com/ekmett/free/";
+ description = "Monads for free";
+ license = stdenv.lib.licenses.bsd3;
+}
diff --git a/nix/llvm-hs-pretty.nix b/nix/llvm-hs-pretty.nix
new file mode 100644
index 00000000..e412b501
--- /dev/null
+++ b/nix/llvm-hs-pretty.nix
@@ -0,0 +1,20 @@
+{ mkDerivation, array, base, bytestring, directory, filepath
+, llvm-hs, llvm-hs-pure, mtl, pretty-show, stdenv, tasty
+, tasty-golden, tasty-hspec, tasty-hunit, text, transformers
+, wl-pprint-text
+}:
+mkDerivation {
+ pname = "llvm-hs-pretty";
+ version = "0.2.0.0";
+ sha256 = "90ce478f6386f836e3b646186c4fe4d72598cc938d8fbb150718a1bbf4f4738c";
+ libraryHaskellDepends = [
+ array base bytestring llvm-hs-pure text wl-pprint-text
+ ];
+ testHaskellDepends = [
+ base directory filepath llvm-hs llvm-hs-pure mtl pretty-show tasty
+ tasty-golden tasty-hspec tasty-hunit text transformers
+ ];
+ homepage = "https://github.com/llvm-hs/llvm-hs-pretty";
+ description = "Pretty printer for LLVM IR";
+ license = stdenv.lib.licenses.mit;
+}
diff --git a/nix/llvm-hs-pure.nix b/nix/llvm-hs-pure.nix
new file mode 100644
index 00000000..7c52a0f9
--- /dev/null
+++ b/nix/llvm-hs-pure.nix
@@ -0,0 +1,20 @@
+{ mkDerivation, attoparsec, base, bytestring, containers, fail
+, hspec, mtl, stdenv, tasty, tasty-hunit, tasty-quickcheck
+, template-haskell, text, transformers, unordered-containers
+}:
+mkDerivation {
+ pname = "llvm-hs-pure";
+ version = "5.1.2";
+ sha256 = "c4d0993aacda72107e6d34865421f128b8c27b586b95a68e2a3e94700645d954";
+ libraryHaskellDepends = [
+ attoparsec base bytestring containers fail mtl template-haskell
+ transformers unordered-containers
+ ];
+ testHaskellDepends = [
+ base bytestring containers hspec mtl tasty tasty-hunit
+ tasty-quickcheck text transformers unordered-containers
+ ];
+ homepage = "http://github.com/llvm-hs/llvm-hs/";
+ description = "Pure Haskell LLVM functionality (no FFI)";
+ license = stdenv.lib.licenses.bsd3;
+}
diff --git a/nix/llvm-hs.nix b/nix/llvm-hs.nix
new file mode 100644
index 00000000..edea0e0f
--- /dev/null
+++ b/nix/llvm-hs.nix
@@ -0,0 +1,26 @@
+{ mkDerivation, array, attoparsec, base, bytestring, Cabal
+, containers, exceptions, llvm-config, llvm-hs-pure, mtl
+, pretty-show, QuickCheck, stdenv, tasty, tasty-hunit
+, tasty-quickcheck, template-haskell, temporary, transformers
+, utf8-string
+}:
+mkDerivation {
+ pname = "llvm-hs";
+ version = "5.1.3";
+ sha256 = "ccdac4683f56135ba83ed0883231f686d1784e9bc7f072a34fcf041e0661976b";
+ revision = "1";
+ editedCabalFile = "0r8xgz6r2miw1l3az343jwz8f9jgzqywxnzl2xhanv05g3i462yh";
+ setupHaskellDepends = [ base Cabal containers ];
+ libraryHaskellDepends = [
+ array attoparsec base bytestring containers exceptions llvm-hs-pure
+ mtl template-haskell transformers utf8-string
+ ];
+ libraryToolDepends = [ llvm-config ];
+ testHaskellDepends = [
+ base bytestring containers llvm-hs-pure mtl pretty-show QuickCheck
+ tasty tasty-hunit tasty-quickcheck temporary transformers
+ ];
+ homepage = "http://github.com/llvm-hs/llvm-hs/";
+ description = "General purpose LLVM bindings";
+ license = stdenv.lib.licenses.bsd3;
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 00000000..256a363e
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,74 @@
+{ fetchFromGitHub ? (import {}).fetchFromGitHub
+# peg nix packages to specific version
+, pkgs ?
+ import
+ ( fetchFromGitHub
+ {
+ owner = "NixOS";
+ repo = "nixpkgs-channels";
+ rev = "696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f";
+ sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
+ }
+ ) {}
+}:
+let
+ # extract the Haskell dependencies of a package
+ extractHaskellDependencies = (hpkg:
+ with builtins;
+ let
+ isHaskellPkg = x: (isAttrs x) && (x ? pname) && (x ? version) && (x ? env);
+ packagesFromDrv = x:
+ let
+ inputs =
+ (x.buildInputs or []) ++
+ (x.nativeBuildInputs or []) ++
+ (x.propagatedBuildInputs or []) ++
+ (x.propagatedNativeBuildInputs or []);
+
+ in
+ (filter isHaskellPkg inputs);
+ go1 = s: xs: foldl' go2 s xs;
+ go2 = s: x:
+ if s ? "${x.pname}"
+ then s
+ else go1 (s // {"${x.pname}" = x;}) (packagesFromDrv x);
+ in assert isAttrs hpkg; attrNames (go1 {} (packagesFromDrv hpkg)));
+
+ # Haskell custom overrides
+ haskellPackages = pkgs.haskell.packages.ghc822.override (old:
+ { overrides = self: super:
+ {
+ free = self.callPackage ./nix/free.nix {};
+ functor-infix = pkgs.haskell.lib.doJailbreak (super.functor-infix);
+ llvm-hs = self.callPackage ./nix/llvm-hs.nix {llvm-config = pkgs.llvm_5;};
+ llvm-hs-pure = self.callPackage ./nix/llvm-hs-pure.nix {};
+ llvm-hs-pretty = pkgs.haskell.lib.dontCheck (self.callPackage ./nix/llvm-hs-pretty.nix {});
+ };
+ });
+
+ # the grin package
+ grin = pkgs.haskellPackages.callPackage ./grin {};
+ # grin's dependencies
+ grinDeps = extractHaskellDependencies grin;
+ # use a GHC with all the Hakell dependencies and the documentation for them and a Hoogle server to search them
+ ghcWith = haskellPackages.ghcWithHoogle (hs: map (x: builtins.getAttr x hs) grinDeps);
+
+ llc5 = pkgs.runCommand "llc5"
+ {
+ buildInputs = [pkgs.llvm_5];
+ }
+ ''
+ mkdir -p $out/bin
+ cd $out/bin
+ ln -s ${pkgs.llvm_5}/bin/llc llc-5.0
+ '';
+in
+# environment setup with all the needed tools
+pkgs.runCommand "grin-shell"
+ {
+ shellHook = ''
+ eval $(egrep ^export ${ghcWith}/bin/ghc)
+ '';
+ buildInputs = [ghcWith llc5 pkgs.llvm_5 haskellPackages.cabal-install];
+ }
+ "touch $out"