diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/dump.cabal b/dump.cabal
new file mode 100644
--- /dev/null
+++ b/dump.cabal
@@ -0,0 +1,55 @@
+-- Initial dump.cabal generated by cabal init.  For further documentation,
+-- see http://haskell.org/cabal/users-guide/
+
+name:               dump
+version:            0.1.0
+synopsis:           Dumps the names and values of expressions to ease debugging.
+description:        Example: `let a=1 in [d|a, a+1|] == "(a) = 1, (a+1) = 2"`
+license:            MIT
+license-file:       LICENSE
+author:             Milán Nagy
+maintainer:         dumplibhs.psssst@dfgh.net
+copyright:          ©2015 Milán Nagy
+category:           Development
+build-type:         Simple
+-- extra-source-files:
+cabal-version:      >=1.10
+homepage:           https://github.com/Wizek/dump
+
+source-repository head
+  type: git
+  location: git://github.com/Wizek/dump.git
+
+library
+  exposed-modules:    Debug.Dump
+  other-modules:      Utils
+  -- other-extensions:
+  build-depends:      base >=4.8 && <4.9
+                    , template-haskell
+                    , haskell-src-meta
+                    , interpolatedstring-perl6
+                    , text
+  ghc-options:
+    --ddump-splices
+    --funbox-strict-fields
+  hs-source-dirs:     src
+  default-language:   Haskell2010
+  default-extensions: QuasiQuotes
+
+test-suite spec
+  type:               exitcode-stdio-1.0
+  build-depends:      dump
+                    , base
+                    , hspec
+
+                    , template-haskell
+                    , haskell-src-meta
+                    , interpolatedstring-perl6
+                    , text
+
+  hs-source-dirs:     spec, src
+  main-is:            Spec.hs
+  default-language:   Haskell2010
+  default-extensions: QuasiQuotes
+  ghc-options:
+    -- -ddump-splices
diff --git a/spec/Spec.hs b/spec/Spec.hs
new file mode 100644
--- /dev/null
+++ b/spec/Spec.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+import Test.Hspec
+
+import Debug.Dump
+import Utils
+
+main = hspec $ do
+  describe "wrapInParens" $ do
+    it "should work" $ do
+      wrapInParens "a" `shouldBe` "(a)"
+      wrapInParens "" `shouldBe` "()"
+
+  describe "Debug.Dump" $ do
+    -- TODO decide if this is useful enough to warrant support
+    -- it "should execute even if empty" $ do
+    --   [d||] `shouldBe` ""
+
+    it "should work with single literal" $ do
+      [d|1|] `shouldBe` "(1) = 1"
+
+    it "should work with simple expression" $ do
+      [d|1 + 1|] `shouldBe` "(1 + 1) = 2"
+
+    it "should work with bindings" $ do
+      let a = 1
+      [d|a|] `shouldBe` "(a) = 1"
+      [d|a + 1|] `shouldBe` "(a + 1) = 2"
+
+    it "should work with comma separated expressions" $ do
+      [d|1, 2|] `shouldBe` "(1) = 1, (2) = 2"
+      let i = 0.25
+      let f = (1 -)
+      [d|i, 1/i, f i, f (1/i)|] `shouldBe`
+        "(i) = 0.25, (1/i) = 4.0, (f i) = 0.75, (f (1/i)) = -3.0"
+
+    -- TODO parser, WIP on 'parse' branch
+    -- it "should step over commas in sub-expressions" $ do
+    --   [d|(1, 2), 1|] `shouldBe` "((1, 1)) = (1,1), (1) = 1"
diff --git a/src/Debug/Dump.hs b/src/Debug/Dump.hs
new file mode 100644
--- /dev/null
+++ b/src/Debug/Dump.hs
@@ -0,0 +1,37 @@
+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
+
+module Debug.Dump where
+
+import Utils
+import Data.List
+import Debug.Trace
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+import Language.Haskell.Meta.Parse
+import Text.InterpolatedString.Perl6
+
+(.>) = flip (.); infixl 9 .>
+($>) = flip ($); infixl 0 $>
+
+dump :: QuasiQuoter
+dump = QuasiQuoter {quoteExp = process}
+
+d = dump
+
+process :: String -> Q Exp
+process str = pairsOf str $> parse $> return
+  where
+    pairsOf :: String -> String
+    pairsOf str = join (map pairOf list) $> wrapInParens
+      where
+        join :: [String] -> String
+        join = intercalate ([q| ++ ", " ++ |] :: String)
+        list :: [String]
+        list = separate str
+    pairOf :: String -> String
+    pairOf str = [qq|"($stripped) = " ++ show ($str)|]
+      where
+        stripped :: String
+        stripped = strip str
+    parse :: String -> Exp
+    parse = parseExp .> either error id
diff --git a/src/Utils.hs b/src/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Utils.hs
@@ -0,0 +1,20 @@
+module Utils where
+
+import qualified Data.Text as T
+import Text.InterpolatedString.Perl6
+
+strip  = T.unpack . T.strip . T.pack
+
+wrapInParens :: String -> String
+wrapInParens s = [qq|($s)|]
+
+separate :: String -> [String]
+separate = wordsWhen (== ',')
+
+-- TODO use parsing to account for [d|1,(2,3)|]
+wordsWhen     :: (Char -> Bool) -> String -> [String]
+wordsWhen p s =  case dropWhile p s of
+                      "" -> []
+                      s' -> w : wordsWhen p s''
+                            where (w, s'') = break p s'
+
