diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+## 0.1.0
+
+Initial version
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Keito Kajitani (c) 2019
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Keito Kajitani nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# ast-path
+
+AST-path is a representation for predicting program properties.
+
+AST-path is described in the paper "A General Path-Based Representation for Predicting Program Properties" (PLDI'2018) <https://arxiv.org/abs/1803.09544>
+and used at <https://code2vec.org/> and at <https://code2seq.org/>.
+
+```
+{-# LANGUAGE DeriveGeneric #-}
+import Data.ASTPath
+
+data Tree a = Leaf a | Node (Tree a) (Tree a)
+  deriving (Eq, Show, Generic)
+
+instance AST a => AST (Tree a)
+instance AST Int where
+  astPathWithHalf = terminalPath show
+
+>>> astPath $ Node (Leaf 0) (Node (Leaf 1) (Leaf 2))
+[("Node",["Leaf","1"],["Leaf","2"]),("Node",["Leaf","0"],["Node","Leaf","1"]),("Node",["Leaf","0"],["Node","Leaf","2"])]
+```
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/ast-path.cabal b/ast-path.cabal
new file mode 100644
--- /dev/null
+++ b/ast-path.cabal
@@ -0,0 +1,55 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.1.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 7286c954518553459704368e3c5eb84afe6a8f7181d03ce1aba6dda8e981cc73
+
+name:           ast-path
+version:        0.1.2
+synopsis:       vocabulary representation for predicting program properties
+
+description:    Please see the README on GitHub at <https://github.com/ijaketak/ast-path#readme>
+category:       Data, Natural Language Processing
+homepage:       https://github.com/ijaketak/ast-path#readme
+bug-reports:    https://github.com/ijaketak/ast-path/issues
+author:         Keito Kajitani
+maintainer:     ijaketak@gmail.com
+copyright:      2019 Keito Kajitani
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/ijaketak/ast-path
+
+library
+  exposed-modules:
+      Data.ASTPath
+  other-modules:
+      Paths_ast_path
+  hs-source-dirs:
+      src
+  build-depends:
+      base >=4.7 && <5
+  default-language: Haskell2010
+
+test-suite ast-path-test
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  other-modules:
+      Paths_ast_path
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wno-missing-methods
+  build-depends:
+      ast-path
+    , base >=4.7 && <5
+    , tasty
+    , tasty-hunit
+  default-language: Haskell2010
diff --git a/src/Data/ASTPath.hs b/src/Data/ASTPath.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ASTPath.hs
@@ -0,0 +1,100 @@
+-- | AST-path is a representation for predicting program properties.
+
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Data.ASTPath
+  ( type HalfPath
+  , type ASTPath
+  , astPath
+  , AST(..)
+  , treePath
+  , terminalPath
+  , AST'(..)
+  ) where
+
+import GHC.Generics
+
+type HalfPath = [String]
+
+-- | (top node, [..., start node], [..., end node])
+type ASTPath = (String, HalfPath, HalfPath)
+
+-- | Typeclass for tree or terminal node.
+class AST a where
+  {-# MINIMAL astPathWithHalf #-}
+  -- | Generate paths and half paths for recursion.
+  astPathWithHalf
+    :: a -- ^ current tree
+    -> String -- ^ label of current root node
+    -> ([ASTPath], [HalfPath]) -- ^ paths and half paths
+  default astPathWithHalf :: (Generic a, AST' (Rep a)) => a -> String -> ([ASTPath], [HalfPath])
+  astPathWithHalf = treePath
+
+-- | Default implementation for tree type.
+treePath :: forall a. (Generic a, AST' (Rep a)) => a -> String -> ([ASTPath], [HalfPath])
+treePath a c = astPathWithHalf' (from a :: Rep a a) c
+
+-- | Typical implementation for terminal node type.
+terminalPath :: (a -> String) -> a -> String -> ([ASTPath], [HalfPath])
+terminalPath f x _ = ([], [[f x]])
+
+-- | Generate AST-paths from tree.
+astPath :: AST a => a -> [ASTPath]
+astPath a = fst $ astPathWithHalf a undefined
+
+-- | Class of generic representation types that can be parsed into paths.
+class AST' f where
+  -- | Default implementation for generic instances of `AST`.
+  astPathWithHalf' :: f a -> String -> ([ASTPath], [HalfPath])
+
+instance AST' V1 where
+  astPathWithHalf' _ _ = undefined
+
+instance AST' U1 where
+  astPathWithHalf' _ _ = ([], [])
+
+instance (AST' f, AST' g) => AST' (f :+: g) where
+  astPathWithHalf' (L1 a) = astPathWithHalf' a
+  astPathWithHalf' (R1 a) = astPathWithHalf' a
+
+instance (AST' f, AST' g) => AST' (f :*: g) where
+  astPathWithHalf' (a :*: b) c = (ps, hs)
+   where
+    (psa, hsa) = astPathWithHalf' a c
+    (psb, hsb) = astPathWithHalf' b c
+    ps = psa ++ psb ++ [ (c, p1, p2) | p1 <- hsa, p2 <- hsb ]
+    hs = hsa ++ hsb
+
+instance (AST a) => AST' (K1 i a) where
+  astPathWithHalf' (K1 a) = astPathWithHalf (a :: a)
+
+instance (AST' f, Datatype d) => AST' (D1 d f) where
+  astPathWithHalf' (M1 a) = astPathWithHalf' a
+
+instance (AST' f, Constructor c) => AST' (C1 c f) where
+  astPathWithHalf' (M1 a) _ = (ps, map (c:) hs)
+   where
+    (ps, hs) = astPathWithHalf' a c
+    c = conName (undefined :: t c f a)
+
+instance (AST' f, Selector s) => AST' (S1 s f) where
+  astPathWithHalf' (M1 a) = astPathWithHalf' a
+
+-- | Constructor of list type is ignored, same as generic product type.
+-- Hence list type itself cannot be used with `astPath`.
+-- If want to use, supply root node label.
+instance AST a => AST [a] where
+  astPathWithHalf [] _ = ([], [])
+  astPathWithHalf (x:xs) c = (ps, hs)
+   where
+    (psh, hsh) = astPathWithHalf x c
+    (pst, hst) = astPathWithHalf xs c
+    ps = psh ++ pst ++ [ (c, p1, p2) | p1 <- hsh, p2 <- hst ]
+    hs = hsh ++ hst
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE DeriveGeneric #-}
+
+module Main where
+
+import Data.ASTPath
+import GHC.Generics
+import Test.Tasty
+import Test.Tasty.HUnit
+
+data Tree a = Leaf a | Node (Tree a) (Tree a)
+  deriving (Eq, Show, Generic)
+
+data Exp2 a
+  = Val a
+  | Term (Exp1 a)
+  | Add [Exp2 a]
+  deriving (Eq, Show, Generic)
+
+data Exp1 a
+  = Par (Exp2 a)
+  | Mul [Exp1 a]
+  deriving (Eq, Show, Generic)
+
+instance AST a => AST (Tree a)
+instance AST a => AST (Exp1 a)
+instance AST a => AST (Exp2 a)
+
+instance AST Int where
+  astPathWithHalf = terminalPath show
+
+main :: IO ()
+main = do
+  defaultMain $ unitTests
+
+unitTests :: TestTree
+unitTests = testGroup "unit tests"
+  [ testCase "simple tree" $ do
+    let tr :: Tree Int
+        tr = Node (Leaf 0) (Leaf 1)
+        path = astPath tr
+        n = "Node"
+        l = "Leaf"
+    assertBool "single path" $
+      (n, [l, "0"], [l, "1"]) `elem` path
+  , testCase "complex tree" $ do
+    let tr :: Tree Int
+        tr = Node (Leaf 0) (Node (Leaf 1) (Node (Leaf 2) (Leaf 3)))
+        path = astPath tr
+        n = "Node"
+        l = "Leaf"
+    assertBool "path 1" $
+      (n, [l, "2"], [l, "3"]) `elem` path
+    assertBool "path 2" $
+      (n, [l, "1"], [n, l, "2"]) `elem` path
+    assertBool "path 3" $
+      (n, [l, "1"], [n, l, "3"]) `elem` path
+    assertBool "path 4" $
+      (n, [l, "0"], [n, l, "1"]) `elem` path
+    assertBool "path 5" $
+      (n, [l, "0"], [n, n, l, "2"]) `elem` path
+    assertBool "path 6" $
+      (n, [l, "0"], [n, n, l, "3"]) `elem` path
+  , testCase "arithmetics" $ do
+    let ex :: Exp1 Int
+        ex = Mul [Par (Add [Val 5,Val 3]), Par (Add [Val 4, Val 2,Val 1])]
+        path = astPath ex
+        v = "Val"
+        p = "Par"
+        a = "Add"
+        m = "Mul"
+    assertBool "path 1" $
+      (a, [v, "5"], [v, "3"]) `elem` path
+    assertBool "path 2" $
+      (a, [v, "2"], [v, "1"]) `elem` path
+    assertBool "path 3" $
+      (a, [v, "4"], [v, "2"]) `elem` path
+    assertBool "path 4" $
+      (a, [v, "4"], [v, "1"]) `elem` path
+    assertBool "path 5" $
+      (m, [p, a, v, "5"], [p, a, v, "4"]) `elem` path
+    assertBool "path 6" $
+      (m, [p, a, v, "5"], [p, a, v, "2"]) `elem` path
+    assertBool "path 7" $
+      (m, [p, a, v, "5"], [p, a, v, "1"]) `elem` path
+    assertBool "path 8" $
+      (m, [p, a, v, "3"], [p, a, v, "4"]) `elem` path
+    assertBool "path 9" $
+      (m, [p, a, v, "3"], [p, a, v, "2"]) `elem` path
+    assertBool "path 10" $
+      (m, [p, a, v, "3"], [p, a, v, "1"]) `elem` path
+  ]
