diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,9 @@
+# Revision history for thrift-compiler
+
+## 0.1.0.1
+
+* Builds with GHC 9.8.x
+
+## 0.1.0.0
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+BSD License
+
+For hsthrift software
+
+Copyright (c) Facebook, Inc. and its affiliates. 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 Facebook nor the names of its 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 HOLDER 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/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+-- @nolint
+import Distribution.Simple
+main = defaultMain
diff --git a/Thrift/Compiler.hs b/Thrift/Compiler.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler.hs
@@ -0,0 +1,161 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE TypeApplications #-}
+module Thrift.Compiler
+  ( run
+  , parseAll, parseThriftFile
+  , parseAllE, parseThriftFileE
+  , typecheckInput
+  , typecheckInputE
+  ) where
+
+import Control.Concurrent.Async
+import Control.Monad
+import Data.List
+import Data.Typeable
+import Language.Haskell.Exts hiding (parse, Decl, name)
+import System.Exit
+import System.FilePath
+import qualified Data.Map.Strict as Map
+
+-- Backends
+import Thrift.Compiler.GenHaskell
+import Thrift.Compiler.GenJSON
+import Thrift.Compiler.GenJSONLoc
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.OptParse
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Pretty
+import Thrift.Compiler.Typechecker
+import Thrift.Compiler.Typechecker.Monad
+import Thrift.Compiler.Types as Thrift
+
+-- | Run the thrift compiler and return a list of paths to the generated files
+run :: ThriftLanguage l => Options l -> IO [FilePath]
+run opts@Options{..} = do
+  -- Parse and Typecheck
+  (headModule, deps) <- typecheckInput opts =<< parseAll opts optsPath
+
+  if optsLenient && not optsLenientStillGenCode then return []
+  else do
+    -- Generate Outputs
+    genFiles <- getGenerator opts headModule deps
+
+    -- Write THIRFT-MADE-GENERATED-FILES
+    case optsThriftMade of
+      Nothing -> return ()
+      Just path -> writeFile path $ unlines genFiles
+
+    return genFiles
+
+typecheckInput
+  :: ThriftLanguage l
+  => Options l
+  -> ModuleMap
+  -> IO (Program l Thrift.Loc, [Program l Thrift.Loc])
+typecheckInput opts moduleMap =
+  case typecheckInputE opts moduleMap of
+    Left es -> mapM_ putStrLn es >> exitFailure
+    Right ms -> pure ms
+
+typecheckInputE
+  :: ThriftLanguage l
+  => Options l
+  -> ModuleMap
+  -> Either [String] (Program l Thrift.Loc, [Program l Thrift.Loc])
+typecheckInputE opts moduleMap =
+  case typecheck opts moduleMap of
+    Left es ->  Left $ map renderTypeErrorPlain (sortBy orderError es)
+    Right ms -> Right ms
+
+getGenerator
+  :: ThriftLanguage l
+  => Options l
+  -> Program l Thrift.Loc
+  -> [Program l Thrift.Loc]
+  -> IO [FilePath]
+getGenerator opts@Options{..} prog deps = case optsGenMode of
+  Lint -> return []
+  EmitCode
+    | Just (hsopts, hsprogs) <- cast (opts, allProgs) ->
+        concat <$> mapConcurrently @[] (writeHsCode hsopts) hsprogs
+    | otherwise -> error
+        "Code generation is only supported for Haskell. Try using --emit-json"
+  EmitJSON WithoutLoc
+    | optsSingleOutput -> (:[]) <$> writeJSON prog mdeps
+    | otherwise -> mapConcurrently (`writeJSON` Nothing) allProgs
+  EmitJSON WithLoc
+    | optsSingleOutput -> (:[]) <$> writeJSONLoc prog mdeps
+    | otherwise -> mapConcurrently (`writeJSONLoc` Nothing) allProgs
+  where
+    (allProgs, mdeps)
+      | optsRecursive = (prog : deps, Just deps)
+      | otherwise = ([prog], Nothing)
+
+-- | Return a parse error or the result
+parseAllE :: Options l -> FilePath -> IO (Either String ModuleMap)
+parseAllE Options{..} = parseItE (Right Map.empty)
+  where
+    parseItE :: Either String ModuleMap
+             -> FilePath -> IO (Either String ModuleMap)
+    parseItE err@Left{} _path = pure err -- stop at first error
+    parseItE (Right tmap) path
+      -- If we already parsed it, don't do it again
+      | Map.member path tmap = pure (Right tmap)
+      | otherwise = do
+          e <- parseThriftFileE optsIncludePath path
+          case e of
+            Left err -> return (Left err)
+            Right file@ThriftFile{..} -> do
+              let newMap = Map.insert path file tmap
+              foldM parseItE (Right newMap) (getIncludes thriftHeaders)
+    getIncludes = foldr getInc []
+    getInc HInclude{incType=Include,..} ps = incPath : ps
+    getInc _ ps = ps
+
+-- | parse all the things recursively, starting with the input and traversing
+-- the includes
+parseAll :: Options l -> FilePath -> IO ModuleMap
+parseAll options fp = do
+  e <- parseAllE options fp
+  case e of
+    Left err -> putStrLn err >> exitFailure
+    Right x -> return x
+
+-- | Return a parse error or the result
+parseThriftFileE
+  :: FilePath -> FilePath
+  -> IO (Either String (ThriftFile SpliceFile Thrift.Loc))
+parseThriftFileE baseDir path = do
+  result <- parse baseDir path
+  case result of
+    Left err -> return (Left err)
+    Right file@ThriftFile{..} -> do
+      spliceFile <- parseHsInclude baseDir thriftHeaders
+      return (Right file { thriftSplice = spliceFile })
+
+-- | Parse a single thrift file
+parseThriftFile :: FilePath -> FilePath -> IO (ThriftFile SpliceFile Thrift.Loc)
+parseThriftFile baseDir path = do
+  e <- parseThriftFileE baseDir path
+  case e of
+      Left err -> putStrLn err >> exitFailure
+      Right x -> return x
+
+-- | Select the last hs_include header (there should be at most one)
+parseHsInclude :: FilePath -> [Header s l a] -> IO SpliceFile
+parseHsInclude baseDir headers = case foldl' getInc Nothing headers of
+  Nothing -> return Nothing
+  Just path -> Just <$> do
+    let mode = defaultParseMode { parseFilename = path }
+    fromParseResult <$> parseFileWithMode mode (baseDir </> path)
+  where
+    getInc _ HInclude{incType=HsInclude,..} = Just incPath
+    getInc ns _ = ns
diff --git a/Thrift/Compiler/GenClient.hs b/Thrift/Compiler/GenClient.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenClient.hs
@@ -0,0 +1,48 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE CPP #-}
+
+module Thrift.Compiler.GenClient
+  ( genClientDecls
+  , genClientImports
+  ) where
+
+import Language.Haskell.Exts
+import Control.Monad
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types hiding (Decl(..))
+
+genClientImports :: Text.Text -> HS Service -> Set.Set Import
+genClientImports this Service{..} =
+  case resolvedName . fst . supResolvedName <$> serviceSuper of
+    Nothing -> Set.empty
+    Just (UName n) -> mkImports this n
+    Just (QName m n) -> mkImports m n
+  where
+    mkImports m n = Set.fromList
+      [ QImport (Text.intercalate "." [m, n, "Client"]) n
+      ]
+
+genClientDecls :: HS Service -> [Decl ()]
+genClientDecls Service{..} =
+  DataDecl () (DataType ()) Nothing (DHead () (textToName serviceResolvedName)) []
+    mzero
+  : case serviceSuper of
+    Nothing -> []
+    Just Super{..} ->
+      [ TypeInsDecl ()
+        (qualType "Thrift" "Super" `appT` simpleType serviceResolvedName)
+        (case resolvedName . fst $ supResolvedName of
+           UName n -> qualType n n
+           QName _ n -> qualType n n)
+      ]
diff --git a/Thrift/Compiler/GenConst.hs b/Thrift/Compiler/GenConst.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenConst.hs
@@ -0,0 +1,35 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenConst
+  ( genConstImports
+  , genConstDecl
+  ) where
+
+import Language.Haskell.Exts.Syntax
+import qualified Data.Set as Set
+import qualified Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types
+
+genConstImports :: HS Const -> Set.Set Import
+genConstImports Const{..} = typeToImport constResolvedType
+
+genConstDecl :: HS Const -> [HS.Decl ()]
+genConstDecl Const{..} =
+  -- Type Signature
+  [ TypeSig () [ textToName constResolvedName ] (genType constResolvedType)
+  -- Const Decl
+  , FunBind ()
+    [ Match () (textToName constResolvedName) []
+      (UnGuardedRhs () $ genConst constResolvedType constResolvedVal)
+      Nothing
+    ]
+  ]
diff --git a/Thrift/Compiler/GenEnum.hs b/Thrift/Compiler/GenEnum.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenEnum.hs
@@ -0,0 +1,448 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenEnum
+  ( genEnumImports
+  , genEnumDecl
+  ) where
+
+import Prelude hiding (Enum)
+import Control.Monad
+import Data.List
+import Data.List.Extra
+import Data.Text (Text)
+import Language.Haskell.Exts.Syntax hiding (Type, Decl)
+import qualified Data.Set as Set
+import qualified Language.Haskell.Exts.Syntax as HS
+import TextShow
+
+import Thrift.Compiler.GenConst
+import Thrift.Compiler.GenTypedef
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugin
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types
+
+-- Data Type Declaration -------------------------------------------------------
+
+genEnumImports :: Set.Set Import
+genEnumImports = Set.fromList
+  [ QImport "Prelude" "Prelude"
+  , QImport "Control.Exception" "Exception"
+  , QImport "Control.DeepSeq" "DeepSeq"
+  , QImport "Data.Aeson" "Aeson"
+  , QImport "Data.Default" "Default"
+  , QImport "Data.Function" "Function"
+  , QImport "Data.HashMap.Strict" "HashMap"
+  , QImport "Data.Hashable" "Hashable"
+  , QImport "Data.Int" "Int"
+  , QImport "GHC.Magic" "GHC"
+  , SymImport "Prelude" [ ".", "++", ">", "==" ]
+  ]
+
+genEnumDecl :: HS Enum -> [HS.Decl ()]
+genEnumDecl Enum{ enumFlavour=PseudoEnum{..},..} =
+  genTypedefDecl typedef (not peThriftEnum) ++
+  concatMap genConstDecl consts ++
+  -- Instances
+  if not peThriftEnum
+  then mzero
+  else
+    [ genDefault enumResolvedName enumConstants
+    , genShow enumResolvedName enumConstants
+    , genThriftEnumInst enumResolvedName enumConstants True True
+    ]
+  where
+    typedef = Typedef
+      { tdName = enumName
+      , tdResolvedName = enumResolvedName
+      , tdTag = IsNewtype
+      , tdType = AnnotatedType enumValueType Nothing (Arity0Loc nlc)
+      , tdResolvedType = enumValueType
+      , tdLoc = TypedefLoc nlc nlc
+      , tdAnns = Nothing
+      , tdSAnns = []
+      }
+    consts = flip map enumConstants $ \EnumValue{..} -> Const
+      { constName = evName
+      , constResolvedName = evResolvedName
+      , constType = AnnotatedType (TNamed enumName) Nothing (Arity0Loc nlc)
+      , constResolvedType =
+        TNewtype (mkName enumName enumResolvedName) enumValueType noLoc
+      , constVal =
+        UntypedConst nlc $ IntConst (fromIntegral evValue) (showt evValue)
+      , constResolvedVal = Literal $ New $ fromIntegral evValue
+      , constLoc = ConstLoc nlc nlc nlc NoSep
+      , constSAnns = []
+      }
+genEnumDecl Enum{ enumFlavour=SumTypeEnum{..},..} =
+  -- Enum Declaration
+  [ DataDecl () (DataType ()) Nothing
+    (DHead () $ textToName enumResolvedName)
+    -- We generate them in sorted order so that we can derive Bounded correctly
+    ((genConstr <$> sortOn evValue enumConstants) ++ [genUnknownConstr | not enumNoUnknown])
+    -- Deriving
+    (if enumNoUnknown && null enumConstants
+     then mzero
+     else
+       pure $ deriving_ $ map (IRule () Nothing Nothing . IHCon ()) $
+       [ qualSym "Prelude" "Eq"
+       , qualSym "Prelude" "Show"
+       ] ++ [ qualSym "Prelude" "Ord" | canDeriveOrd ])
+  ] ++
+  -- Instances
+  if enumNoUnknown && null enumConstants
+  then
+    map (genEmptyInstance enumResolvedName)
+    -- Using the symbol (==) in the AST is technically wrong, but it
+    -- generates correct pretty-printed code and allows us to reuse more code
+    [ ("Prelude", "Eq", [ "(==)" ])
+    , ("Prelude", "Show", [ "show" ])
+    , ("Prelude", "Ord", [ "compare" ])
+    , ("Aeson", "ToJSON", [ "toJSON" ])
+    , ("Default", "Default", [ "def" ])
+    , ("Hashable", "Hashable", [ "hashWithSalt" ])
+    , ("DeepSeq", "NFData", [ "rnf" ])
+    ] ++
+    [genThriftEnumInst enumResolvedName enumConstants enumNoUnknown False]
+  else
+    [ genToJSON enumResolvedName
+    , genNFData enumResolvedName
+    , genDefault enumResolvedName enumConstants
+    , genHashable enumResolvedName
+    , genThriftEnumInst enumResolvedName enumConstants enumNoUnknown False
+    ] ++
+    [genOrd enumResolvedName | not canDeriveOrd]
+  where
+    genConstr :: HS EnumValue -> QualConDecl ()
+    genConstr EnumValue{..} =
+      QualConDecl () Nothing Nothing
+                      (ConDecl () (textToName evResolvedName) [])
+    -- If the stars align we can derive the Enum instance
+    -- This requires the Enum to contain exactly the values [0 .. n-1]
+    canDeriveOrd = and $ zipWith (==) [0..] $ sort $ map evValue enumConstants
+
+    -- Use 2 underscores to avoid name collisions.
+    genUnknownConstr :: QualConDecl ()
+    genUnknownConstr =
+      QualConDecl
+        ()
+        Nothing
+        Nothing
+        (ConDecl () (textToName $ enumResolvedName <> "__UNKNOWN") [genType (TSpecial HsInt)])
+
+-- Ord Instance ----------------------------------------------------------------
+
+genOrd :: Text -> HS.Decl ()
+genOrd name =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Prelude" "Ord")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "compare") []
+         (UnGuardedRhs () $
+          qvar "Function" "on" `app`
+          qvar "Prelude" "compare" `app`
+          qvar "Thrift" "fromThriftEnum")
+         Nothing
+       ]
+     ])
+
+-- Generate Show Instance --------------------------------------------------
+
+genShow :: Text -> [HS EnumValue] -> HS.Decl ()
+genShow name consts =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Prelude" "Show")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "showsPrec")
+         [ pvar "__d", PApp () (unqualSym name) [pvar "__val"] ]
+         (UnGuardedRhs () $
+          Case () (qvar "HashMap" "lookup" `app` var "__val" `app` var "__m")
+            [ Alt () (PApp () (qualSym "Prelude" "Just") [pvar "__s"])
+              (UnGuardedRhs () $ qvar "Prelude" "showString" `app` var "__s")
+              Nothing
+            , Alt () (PApp () (qualSym "Prelude" "Nothing") [])
+              (UnGuardedRhs () $ qvar "Prelude" "showParen" `app`
+                infixApp ">" (var "__d") (intLit (10 :: Int)) `app`
+                infixApp "."
+                  (qvar "Prelude" "showString" `app`
+                    stringLit (name <> "__UNKNOWN "))
+                  (qvar "Prelude" "showsPrec" `app`
+                    intLit (11 :: Int) `app` var "__val"))
+              Nothing
+            ])
+         (Just $ BDecls () [FunBind () [Match () (textToName "__m") []
+          (UnGuardedRhs () $ qvar "HashMap" "fromList" `app` pairs)
+          Nothing]])
+       ]
+     ])
+  where
+    -- https://gitlab.haskell.org/ghc/ghc/-/issues/4505
+    chunkLimit = 1000
+    pairs
+      | length consts <= chunkLimit = pairList consts
+      | otherwise = qvar "Prelude" "concat" `app` listE
+        (flip map (chunksOf chunkLimit consts) $ \chunk ->
+          qvar "GHC" "noinline" `app` qvar "Prelude" "id" `app` pairList chunk)
+    pairList cs = listE
+      [ Tuple () Boxed [intLit evValue, stringLit $ uppercase evResolvedName]
+      | EnumValue{..} <- cs
+      ]
+
+-- Aeson Instances -------------------------------------------------------------
+
+genToJSON :: Text -> HS.Decl ()
+genToJSON name =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Aeson" "ToJSON")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "toJSON") []
+         (UnGuardedRhs () $
+          qvar "Aeson" "toJSON" `compose` qvar "Thrift" "fromThriftEnum")
+         Nothing
+       ]
+     ])
+
+-- Generate NFData Instance ---------------------------------------------------
+
+genNFData :: Text -> HS.Decl ()
+genNFData name =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "DeepSeq" "NFData")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "rnf")
+         [ PApp () (unqualSym arg) [] ]
+         (UnGuardedRhs () $
+          qvar "Prelude" "seq" `app` var arg `app` unit)
+         Nothing
+       ]
+     ])
+    where
+      arg = "__" <> name
+      unit = Con () (Special () (UnitCon ()))
+
+-- Generate Default Instance --------------------------------------------------
+
+genDefault :: Text -> [HS EnumValue] -> HS.Decl ()
+genDefault name consts =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Default" "Default")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "def") []
+         (UnGuardedRhs () $
+          case consts of
+            EnumValue{..} : _ -> con evResolvedName
+            [] ->
+              qvar "Exception" "throw" `app`
+              (qvar "Thrift" "ProtocolException" `app`
+               stringLit ("def: enum " <> name <> " has no constructors")))
+         Nothing
+       ]
+     ])
+
+-- Generate Hashable Instance -------------------------------------------------
+
+genHashable :: Text -> HS.Decl ()
+genHashable name =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Hashable" "Hashable")
+       (TyCon () $ unqualSym name))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "hashWithSalt") [ pvar "_salt", pvar "_val" ]
+         (UnGuardedRhs () $
+          qvar "Hashable" "hashWithSalt" `app` var "_salt" `app`
+          (qvar "Thrift" "fromThriftEnum" `app` var "_val"))
+         Nothing
+       ]
+     ])
+
+-- Generate Empty Instance -----------------------------------------------------
+
+genEmptyInstance :: Text -> (Text, Text, [Text]) -> HS.Decl ()
+genEmptyInstance name (mname, className, methods) =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym mname className)
+       (TyCon () $ unqualSym name))
+    (Just $ map
+     (\method -> InsDecl () $ FunBind () [genEmptyMethod name method])
+     methods)
+
+genEmptyMethod :: Text -> Text -> Match ()
+genEmptyMethod name method =
+  Match () (textToName method) []
+  (UnGuardedRhs () $
+   qvar "Exception" "throw" `app`
+   (qvar "Thrift" "ProtocolException" `app`
+    stringLit
+    (mconcat
+     [ method, ": Thrift enum '", name, "' is uninhabited"])))
+  Nothing
+
+-- Thrift Enum Instance --------------------------------------------------------
+
+genThriftEnumInst :: Text -> [HS EnumValue] -> Bool -> Bool -> HS.Decl ()
+genThriftEnumInst ename consts enumNoUnknown pseudoEnum =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing
+      (IHApp ()
+       (IHCon () (qualSym "Thrift" "ThriftEnum"))
+       (TyCon () (unqualSym ename))))
+    (Just $ map (InsDecl () . FunBind ())
+       [ genThriftEnumMethod "toThriftEnum" genToEnumMatch
+          genToEnumCatchAll genToEnumUnknown genToEnumPseudo
+       , genThriftEnumMethod "fromThriftEnum" genFromEnumMatch
+          genFromEnumCatchAll genFromEnumUnknown genFromEnumPseudo
+       , genAllEnumValues consts
+       , if pseudoEnum then [genToEnumEitherPseudo]
+         else map genToEnumEitherMatch consts ++ [genToEnumEitherUnknown]
+       ]
+    )
+  where
+    genThriftEnumMethod
+      method genEnumMatch genEnumCatchAll genEnumUnknown genEnumPseudo
+      | pseudoEnum = [genEnumPseudo]
+      | enumNoUnknown && null consts = [genEmptyMethod ename method]
+      | otherwise = map genEnumMatch consts ++
+        [ if enumNoUnknown
+          then genEnumCatchAll
+          else genEnumUnknown
+        ]
+    genToEnumMatch :: HS EnumValue -> Match ()
+    genToEnumMatch EnumValue{..} =
+      Match ()
+        (textToName "toThriftEnum")
+        [ intP evValue ]
+        (UnGuardedRhs () $ Con () $ unqualSym evResolvedName)
+        Nothing
+    genToEnumCatchAll =
+      Match ()
+        (textToName "toThriftEnum")
+        [ pvar "_val" ]
+        (UnGuardedRhs () $
+          qvar "Exception" "throw" `app`
+          (qvar "Thrift" "ProtocolException" `app`
+          infixApp "++"
+          (stringLit $ "toThriftEnum: not a valid identifier for enum " <>
+                       ename <> ": ")
+          (qvar "Prelude" "show" `app` var "_val")))
+        Nothing
+    genToEnumUnknown =
+      Match ()
+        (textToName "toThriftEnum")
+        [ pvar "val" ]
+        (UnGuardedRhs () $ var (ename <> "__UNKNOWN") `app` var "val")
+        Nothing
+    genToEnumPseudo =
+      Match ()
+        (textToName "toThriftEnum")
+        [ pvar "__val" ]
+        (UnGuardedRhs () $ var ename `app`
+          (qvar "Prelude" "fromIntegral" `app` var "__val"))
+        Nothing
+    genFromEnumMatch :: HS EnumValue -> Match ()
+    genFromEnumMatch EnumValue{..} =
+      Match ()
+        (textToName "fromThriftEnum")
+        (if pseudoEnum
+          then [PApp () (unqualSym ename) [intP evValue]]
+          else [PApp () (unqualSym evResolvedName) []])
+        (UnGuardedRhs () $ intLit evValue)
+        Nothing
+    genFromEnumCatchAll =
+      Match ()
+        (textToName "fromThriftEnum")
+        [ pvar "_val" ]
+        (UnGuardedRhs () $
+          qvar "Exception" "throw" `app`
+          (qvar "Thrift" "ProtocolException" `app`
+          infixApp "++"
+          (stringLit $ "fromThriftEnum: not a valid identifier for enum " <>
+                       ename <> ": ")
+          (qvar "Prelude" "show" `app` var "_val")))
+        Nothing
+    genFromEnumUnknown =
+      Match ()
+        (textToName "fromThriftEnum")
+        [PApp () (unqualSym (ename <> "__UNKNOWN")) [pvar "val"]]
+        (UnGuardedRhs () $ var "val")
+        Nothing
+    genFromEnumPseudo =
+      Match ()
+        (textToName "fromThriftEnum")
+        [PApp () (unqualSym ename) [pvar "__val"]]
+        (UnGuardedRhs () $ qvar "Prelude" "fromIntegral" `app` var "__val")
+        Nothing
+    genToEnumEitherMatch :: HS EnumValue -> Match ()
+    genToEnumEitherMatch EnumValue{..} =
+      Match ()
+        (textToName "toThriftEnumEither")
+        [ intP evValue ]
+        (UnGuardedRhs () $ qvar "Prelude" "Right" `app` var evResolvedName)
+        Nothing
+    genToEnumEitherUnknown =
+      Match ()
+        (textToName "toThriftEnumEither")
+        [ pvar "val" ]
+        (UnGuardedRhs () $ qvar "Prelude" "Left" `app` infixApp "++"
+          (stringLit $ "toThriftEnumEither: not a valid identifier for enum " <>
+                     ename <> ": ")
+          (qvar "Prelude" "show" `app` var "val"))
+        Nothing
+    genToEnumEitherPseudo =
+      Match ()
+        (textToName "toThriftEnumEither")
+        [ pvar "val" ]
+        (UnGuardedRhs () $ If () (qvar "Prelude" "elem"
+          `app` var "__val" `app` qvar "Thrift" "allThriftEnumValues")
+          (qvar "Prelude" "Right" `app` var "__val")
+          (qvar "Prelude" "Left" `app` infixApp "++"
+            (stringLit $ "toThriftEnumEither: not a valid identifier for enum " <>
+                        ename <> ": ")
+            (qvar "Prelude" "show" `app` var "val")))
+        (Just $ BDecls () [FunBind () [Match () (textToName "__val") []
+          (UnGuardedRhs () $ var ename `app`
+            (qvar "Prelude" "fromIntegral" `app` var "val"))
+          Nothing]])
+
+genAllEnumValues :: [HS EnumValue] -> [Match ()]
+genAllEnumValues cs =
+  [ Match
+      ()
+      (textToName "allThriftEnumValues")
+      []
+      (UnGuardedRhs () $ listE (genEnumExp <$> sortOn evValue cs))
+      Nothing
+  ]
+  where
+    genEnumExp :: HS EnumValue -> Exp ()
+    genEnumExp EnumValue{..} = Con () $ unqualSym evResolvedName
diff --git a/Thrift/Compiler/GenFunction.hs b/Thrift/Compiler/GenFunction.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenFunction.hs
@@ -0,0 +1,523 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenFunction
+  ( genFunctionDecls
+  , genFunctionImports
+  ) where
+
+import Data.Maybe
+import Data.Set (union)
+import Data.Some
+import Data.Text (Text)
+import Language.Haskell.Exts.Syntax hiding (Type)
+import qualified Data.Set as Set
+import qualified Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.Types
+import Thrift.Compiler.GenStruct
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Util.HSE
+
+-- Generate Imports and Decls --------------------------------------------------
+
+genFunctionImports :: HS Function -> Set.Set Import
+genFunctionImports Function{..} =
+  foldr (union . getImports)
+  (foldr (union . getImports) baseImports funExceptions)
+  funArgs `union`
+  maybe Set.empty (`withSome` typeToImport) funResolvedType
+  where
+    getImports :: HS (Field u) -> Set.Set Import
+    getImports Field{..} = typeToImport fieldResolvedType
+    baseImports = Set.fromList
+      [ QImport "Prelude" "Prelude"
+      , QImport "Control.Arrow" "Arrow"
+      , QImport "Control.Exception" "Exception"
+      , QImport "Control.Concurrent" "Concurrent"
+      , QImport "Control.Monad" "Monad"
+      , QImport "Control.Monad.Trans.Class" "Trans"
+      , QImport "Control.Monad.Trans.Reader" "Reader"
+      , QImport "Data.ByteString.Builder" "ByteString"
+      , QImport "Data.ByteString.Lazy" "LBS"
+      , QImport "Data.Int" "Int"
+      , QImport "Data.HashMap.Strict" "HashMap"
+      , QImport "Data.List" "List"
+      , QImport "Data.Proxy" "Proxy"
+      , QImport "Thrift.Binary.Parser" "Parser"
+      , QImport "Thrift.Protocol.ApplicationException.Types" "Thrift"
+      , SymImport "Prelude" [ "==", "=<<", ">>=", "<$>", "." ]
+      , SymImport "Data.Monoid" [ "<>" ]
+      ]
+
+genFunctionDecls
+  :: HS Service -> HS Function -> [HS.Decl ()]
+genFunctionDecls service func = concatMap ($ func)
+  [ genFunctionThrift service
+  , genFunctionIO service
+  , genFunctionSend service
+  , genFunctionRecv
+  , genBuildCall
+  , genParseResponse
+  ]
+
+-- Generate the Function Call In the Thrift Monad ------------------------------
+
+genFunctionThrift
+  :: HS Service -> HS Function -> [HS.Decl ()]
+genFunctionThrift Service{..} Function{..} =
+  -- Type Signature
+  [ TypeSig () [ name ] $
+    TyForall () Nothing (commonCtx serviceResolvedName) $
+    genArgTypes funArgs
+    (qualType "Thrift" "ThriftM" `appT`
+     tvar "p" `appT`
+     tvar "c" `appT`
+     tvar "s" `appT`
+     maybe (unit_tycon ()) (`withSome` genType) funResolvedType)
+  -- Function Body
+  , FunBind ()
+    [ Match () name
+      (map (pvar . ("__field__" <>) . fieldName) funArgs)
+      (UnGuardedRhs () $ Do ()
+       [ Generator ()
+         (PApp () (qualSym "Thrift" "ThriftEnv")
+          (map pvar [ "_proxy", "_channel", "_opts", "_counter" ])) $
+         qvar "Reader" "ask"
+       , Qualifier () $
+         qvar "Trans" "lift" `app`
+         genApplyArgs funArgs
+         (var (funResolvedName <> "IO") `app`
+          var "_proxy" `app`
+          var "_channel" `app`
+          var "_counter" `app`
+          var "_opts")
+       ])
+      Nothing
+    ]
+  ]
+  where
+    name = textToName funResolvedName
+
+-- Generate the Function Call in the IO Monad ----------------------------------
+
+genFunctionIO
+  :: HS Service -> HS Function -> [HS.Decl ()]
+genFunctionIO Service{..} fun@Function{..} =
+  -- Type Signature
+  [ TypeSig () [ textToName (funResolvedName <> "IO") ] $
+    TyForall () Nothing (commonCtx serviceResolvedName) $
+    TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    TyFun () (tvar "c" `appT` tvar "s") $
+    TyFun () (qualType "Thrift" "Counter") $
+    TyFun () (qualType "Thrift" "RpcOptions") $
+    genArgTypes funArgs
+    (qualType "Prelude" "IO" `appT`
+     maybe (unit_tycon ()) (`withSome` genType) funResolvedType)
+  -- Function Body
+  , FunBind ()
+    [ Match () (textToName $ funResolvedName <> "IO")
+      (map pvar $
+       [ "_proxy", "_channel", "_counter", "_opts" ] ++
+       map (("__field__" <>) . fieldName) funArgs)
+      (UnGuardedRhs () $ genFunctionIOBody fun)
+      Nothing
+    ]
+  ]
+
+genFunctionIOBody :: HS Function -> Exp ()
+genFunctionIOBody fun@Function{..}
+  | funIsOneWay = Do () $
+    [ Generator () (pvar "_handle") $ qvar "Concurrent" "newEmptyMVar"
+    , Qualifier () $
+      genApplyArgs funArgs $
+      var (sendName fun) `app`
+      var "_proxy" `app`
+      var "_channel" `app`
+      var "_counter" `app`
+      (qvar "Concurrent" "putMVar" `app` var "_handle") `app`
+      var "_opts"
+    , Qualifier () $ infixApp ">>="
+      (qvar "Concurrent" "takeMVar" `app` var "_handle")
+      (qvar "Prelude" "maybe" `app`
+       (qvar "Prelude" "return" `app` unit_con ()) `app`
+       (qvar "Exception" "throw"))
+    ]
+  | otherwise = Do () $
+    [ Generator ()
+      (PTuple () Boxed [ pvar "_handle", pvar "_sendCob", pvar "_recvCob" ]) $
+      qvar "Thrift" "mkCallbacks" `app`
+      (var (recvName fun) `app` var "_proxy")
+    , Qualifier () $
+      genApplyArgs funArgs $
+      var (sendName fun) `app`
+      var "_proxy" `app`
+      var "_channel" `app`
+      var "_counter" `app`
+      var "_sendCob" `app`
+      var "_recvCob" `app`
+      var "_opts"
+    , Qualifier () $ qvar "Thrift" "wait" `app` var "_handle"
+    ]
+
+-- Generate Send Call ----------------------------------------------------------
+
+genFunctionSend
+  :: HS Service -> HS Function -> [HS.Decl ()]
+genFunctionSend Service{..} fun@Function{..} =
+  -- Type Signature
+  [ TypeSig () [ textToName (sendName fun) ] $
+    TyForall () Nothing (commonCtx serviceResolvedName) $
+    TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    TyFun () (tvar "c" `appT` tvar "s") $
+    TyFun () (qualType "Thrift" "Counter") $
+    TyFun () (qualType "Thrift" "SendCallback") $
+    (if funIsOneWay
+     then id
+     else TyFun () (qualType "Thrift" "RecvCallback")) $
+    TyFun () (qualType "Thrift" "RpcOptions") $
+    genArgTypes funArgs $
+    qualType "Prelude" "IO" `appT` unit_tycon ()
+  -- Function Body
+  , FunBind ()
+    [ Match () (textToName $ sendName fun)
+      (map pvar $
+       [ "_proxy", "_channel", "_counter", "_sendCob" ] ++
+       (if funIsOneWay
+        then []
+        else [ "_recvCob" ]) ++
+       "_rpcOpts" :
+       map (("__field__" <>) . fieldName) funArgs)
+      (UnGuardedRhs () $ Do ()
+       [ Generator () (pvar "_seqNum") (var "_counter")
+       , LetStmt () $ BDecls ()
+         [ PatBind () (pvar "_callMsg")
+           (UnGuardedRhs () $
+            qvar "LBS" "toStrict" `app`
+            (qvar "ByteString" "toLazyByteString" `app`
+             genApplyArgs funArgs
+             (var (buildName fun) `app`
+              var "_proxy" `app`
+              var "_seqNum")))
+           Nothing
+         ]
+       , Qualifier () $
+         if funIsOneWay
+         then
+           qvar "Thrift" "sendOnewayRequest" `app`
+           var "_channel" `app`
+           (qcon "Thrift" "Request" `app`
+            var "_callMsg" `app`
+            rpcAst) `app`
+           var "_sendCob"
+         else
+           qvar "Thrift" "sendRequest" `app`
+           var "_channel" `app`
+           (qcon "Thrift" "Request" `app`
+            var "_callMsg" `app`
+            rpcAst) `app`
+           var "_sendCob" `app`
+           var "_recvCob"
+       ])
+      Nothing
+    ]
+  ]
+  where
+    rpcAst = App ()
+      (App ()
+        (Var () (Qual () (ModuleName () "Thrift") (Ident () "setRpcPriority")))
+        (Var () (UnQual () (Ident () "_rpcOpts")))
+      )
+      (Var () (Qual () (ModuleName () "Thrift") (Ident () priorityString)))
+    priorityString = show $ case funPriority of
+      NPriorities -> NormalPriority
+      _           -> funPriority
+
+sendName :: HS Function -> Text
+sendName Function{..} = "send_" <> funResolvedName
+
+-- Generate Recv Call ----------------------------------------------------------
+
+genFunctionRecv :: HS Function -> [HS.Decl ()]
+genFunctionRecv fun@Function{..}
+  | funIsOneWay = []
+  | otherwise =
+  -- Type Signature
+  [ TypeSig () [ textToName (recvName fun) ] $
+    TyForall () Nothing
+    (Just $ CxTuple ()
+     [ classA () (qualSym "Thrift" "Protocol") [ tvar "p" ]
+     ]) $
+    TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    TyFun () (qualType "Thrift" "Response") $
+    qualType "Prelude" "Either" `appT`
+    qualType "Exception" "SomeException" `appT`
+    maybe (unit_tycon ()) (`withSome` genType) funResolvedType
+
+  -- Function Body
+  , FunBind ()
+    [ Match () (textToName $ recvName fun)
+      [ pvar "_proxy"
+      , PApp () (qualSym "Thrift" "Response")
+        [ pvar "_response", PWildCard () ]
+      ]
+      (UnGuardedRhs () $
+       app (qvar "Monad" "join") $
+       qvar "Arrow" "left" `app`
+       (qvar "Exception" "SomeException" `compose`
+        qcon "Thrift" "ProtocolException") `app`
+       (qvar "Parser" "parse" `app`
+        (var (parseName fun) `app` var "_proxy") `app`
+        var "_response"))
+       Nothing
+    ]
+  ]
+
+recvName :: HS Function -> Text
+recvName Function{..} = "recv_" <> funResolvedName
+
+-- Generate the Function Call Message Builder ----------------------------------
+
+genBuildCall :: HS Function -> [HS.Decl ()]
+genBuildCall fun@Function{..} =
+  -- Type Signature
+  [ TypeSig () [ textToName (buildName fun) ] $
+    TyForall () Nothing
+    (Just $ CxSingle () $
+     classA () (qualSym "Thrift" "Protocol") [ tvar "p" ]) $
+    TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    TyFun () (qualType "Int" "Int32") $
+    genArgTypes funArgs (qualType "ByteString" "Builder")
+  -- Function Body
+  , FunBind ()
+    [ Match () (textToName (buildName fun))
+      (pvar "_proxy" :
+       pvar "_seqNum" :
+       map (pvar . ("__field__" <>) . fieldName) funArgs)
+      (UnGuardedRhs () $
+       infixApp "<>"
+       (infixApp "<>"
+        (protocolFun "genMsgBegin" `app`
+         stringLit funName `app`
+         intLit genCALL `app`
+         var "_seqNum")
+        (genBuildFields funArgs))
+       (protocolFun "genMsgEnd"))
+      Nothing
+    ]
+  ]
+
+buildName :: HS Function -> Text
+buildName Function{..} = "_build_" <> funResolvedName
+
+-- Generate the Response Parser ------------------------------------------------
+
+genParseResponse :: HS Function -> [HS.Decl ()]
+genParseResponse func@Function{..}
+  | funIsOneWay = []
+  | otherwise =
+  -- Type Signature
+  [ TypeSig () [ textToName (parseName func) ] $
+    TyForall () Nothing
+    (Just $ CxSingle () $
+     classA () (qualSym "Thrift" "Protocol") [ tvar "p" ]) $
+    TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    qualType "Parser" "Parser" `appT`
+    (qualType "Prelude" "Either" `appT`
+     qualType "Exception" "SomeException" `appT`
+     case funResolvedType of
+       Nothing -> unit_tycon ()
+       Just (Some ty) -> genType ty)
+  -- Function Body
+  , FunBind ()
+    [ Match () (textToName (parseName func)) [ pvar "_proxy" ]
+      (UnGuardedRhs () $ Do ()
+       -- Parse the beginning of the message
+       [ Generator ()
+         (PApp () (qualSym "Thrift" "MsgBegin")
+          [ pvar "_name", pvar "_msgTy", PWildCard () ]) $
+         protocolFun "parseMsgBegin"
+       , Generator () (pvar "_result") $
+         Case () (var "_msgTy")
+         -- Case 1: CALL
+         [ Alt () (intP genCALL)
+           (UnGuardedRhs () $
+            qvar "Prelude" "fail" `app`
+            stringLit (funName <> ": expected reply but got function call"))
+           Nothing
+         -- Case 2: REPLY
+         , Alt () (intP genREPLY)
+           (GuardedRhss ()
+            [ GuardedRhs ()
+              [ Qualifier () $ infixApp "==" (var "_name") (stringLit funName) ]
+              (genParseReply func)
+            , GuardedRhs () [ Qualifier () $ qvar "Prelude" "otherwise" ] $
+              qvar "Prelude" "fail" `app`
+              stringLit "reply function does not match"
+            ])
+           Nothing
+         -- Case 3: EXCEPTION
+         , Alt () (intP genEXCEPTION)
+           (UnGuardedRhs () $
+            qvar "Prelude" "fmap" `app`
+            (qcon "Prelude" "Left" `compose`
+             qcon "Exception" "SomeException") `app`
+            ExpTypeSig ()
+            (protocolFun "parseStruct")
+            (qualType "Parser" "Parser" `appT`
+             qualType "Thrift" "ApplicationException"))
+           Nothing
+         -- Case 4: ONEWAY
+         , Alt () (intP genONEWAY)
+           (UnGuardedRhs () $
+            qvar "Prelude" "fail" `app`
+            stringLit
+            (funName <> ": expected reply but got oneway function call"))
+           Nothing
+         -- Catch All
+         , Alt () (PWildCard ())
+           (UnGuardedRhs () $
+            qvar "Prelude" "fail" `app`
+            stringLit (funName <> ": invalid message type"))
+           Nothing
+         ]
+       , Qualifier () $ protocolFun "parseMsgEnd"
+       , Qualifier () $ qvar "Prelude" "return" `app` var "_result"
+       ])
+      Nothing
+    ]
+  ]
+
+parseName :: HS Function -> Text
+parseName Function{..} = "_parse_" <> funResolvedName
+
+-- This assumes that the response is basically a union, only one response is
+-- possible.
+genParseReply :: HS Function -> Exp ()
+genParseReply Function{..} = Do ()
+  [ LetStmt () $ BDecls ()
+    [ PatBind () (pvar "_idMap")
+      (UnGuardedRhs () $
+       qvar "HashMap" "fromList" `app`
+       HS.List ()
+       (map (\Field{..} ->
+        Tuple () Boxed [ stringLit fieldName, intLit fieldId ])
+        fields))
+      Nothing
+    ]
+  , Generator () (pvar "_fieldBegin") $
+    protocolFun "parseFieldBegin" `app` intLit (0 :: Int)  `app` var "_idMap"
+  , Qualifier () $
+    Case () (var "_fieldBegin")
+    [ Alt ()
+      (PApp () (qualSym "Thrift" "FieldBegin")
+       [ pvar "_type", pvar "_id", pvar "_bool" ])
+      (UnGuardedRhs () $ Do ()
+       [ Qualifier () $ Case () (var "_id") $
+         maybeToList ((`withSome` genParseResult) <$> funResolvedType) ++
+         map genParseException funExceptions ++
+         [ Alt () (PWildCard ())
+           (UnGuardedRhs () $
+            qvar "Prelude" "fail" `app`
+            (qvar "Prelude" "unwords" `app`
+             HS.List ()
+             [ stringLit "unrecognized exception, type:"
+             , qvar "Prelude" "show" `app` var "_type"
+             , stringLit "field id:"
+             , qvar "Prelude" "show" `app` var "_id"
+             ]))
+           Nothing
+         ]
+       ])
+      Nothing
+    , Alt () (PApp () (qualSym "Thrift" "FieldEnd") [])
+      (UnGuardedRhs () $
+       case funResolvedType of
+        Nothing ->
+          qvar "Prelude" "return" `app`
+          (qcon "Prelude" "Right" `app` unit_con ())
+        Just{} -> qvar "Prelude" "fail" `app` stringLit "no response")
+      Nothing
+    ]
+  ]
+  where
+    resultField :: HSType t -> HS (Field 'StructField)
+    resultField ty = Field
+      { fieldId     = 0
+      , fieldName   = funName <> "_success"
+      , fieldResolvedType   = ty
+      , fieldRequiredness = Default
+      , fieldTag = STRUCT_FIELD
+      -- The following are placeholders since the fields aren't needed
+      , fieldResolvedName = ""
+      , fieldType = AnnotatedType I8 Nothing (Arity0Loc nlc)
+      , fieldResolvedVal = Nothing
+      , fieldVal = Nothing
+      , fieldLaziness = Lazy
+      , fieldLoc = FieldLoc nlc "0" nlc nlc Nothing NoSep
+      , fieldAnns = Nothing
+      , fieldSAnns = []
+      }
+    structify
+      :: HS (Field 'ThrowsField)
+      -> HS (Field 'StructField)
+    structify Field{ fieldRequiredness = Default, ..} =
+      Field{ fieldTag = STRUCT_FIELD, fieldRequiredness = Default, .. }
+    fields = maybe id (`withSome` ((:) . resultField)) funResolvedType $
+             map structify funExceptions
+
+genParseResult :: HSType t -> Alt ()
+genParseResult ty =
+  Alt () (intP (0 :: Int))
+  (GuardedRhss ()
+   [ GuardedRhs ()
+     [ Qualifier () $ infixApp "==" (var "_type") (genThriftType ty) ] $
+     qvar "Prelude" "fmap" `app`
+     qcon "Prelude" "Right" `app`
+     genParseType P_FieldMode ty
+   ])
+  Nothing
+
+genParseException :: HS (Field 'ThrowsField) -> Alt ()
+genParseException Field{..} =
+  Alt () (intP fieldId)
+  (GuardedRhss ()
+   [ GuardedRhs ()
+     [ Qualifier () $ infixApp "==" (var "_type")
+       (genThriftType fieldResolvedType) ] $
+     qvar "Prelude" "fmap" `app`
+     (qvar "Prelude" "Left" `compose` qvar "Exception" "SomeException") `app`
+     ExpTypeSig ()
+     (genParseType P_FieldMode fieldResolvedType)
+     (qualType "Parser" "Parser" `appT` genType fieldResolvedType)
+   ])
+  Nothing
+
+-- Helpers ---------------------------------------------------------------------
+
+commonCtx :: Text -> Maybe (HS.Context ())
+commonCtx sname = Just $ CxTuple ()
+  -- Protocol Constraint
+  [ classA () (qualSym "Thrift" "Protocol") [ tvar "p" ]
+  -- ClientChannel Constraint
+  , classA () (qualSym "Thrift" "ClientChannel")  [ tvar "c" ]
+  -- Service Subtyping Constraint
+  , classA ()
+    (Qual () (ModuleName () "Thrift") (Symbol () "<:"))
+    [ tvar "s"
+    , simpleType sname
+    ]
+  ]
+
+genArgTypes :: [HS (Field 'Argument)] -> HS.Type () -> HS.Type ()
+genArgTypes = flip $ foldr (\Field{..} -> TyFun () $ genType fieldResolvedType)
+
+genApplyArgs :: [HS (Field 'Argument)] -> Exp () -> Exp ()
+genApplyArgs =
+  flip $ foldl (\f Field{..} -> f `app` var ("__field__" <> fieldName))
diff --git a/Thrift/Compiler/GenHaskell.hs b/Thrift/Compiler/GenHaskell.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenHaskell.hs
@@ -0,0 +1,330 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenHaskell
+  ( genHsCode
+  , writeHsCode
+  , writeModule, showModule
+  , ThriftModule(..)
+  , commonPragmas
+  ) where
+
+import Data.List
+import Data.List.Extra
+import Data.Text (Text)
+import Language.Haskell.Exts hiding (parse, Decl, name, app)
+import System.Directory
+import System.FilePath
+import Text.Printf
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.GenClient
+import Thrift.Compiler.GenConst
+import Thrift.Compiler.GenEnum
+import Thrift.Compiler.GenFunction
+import Thrift.Compiler.GenService
+import Thrift.Compiler.GenStruct
+import Thrift.Compiler.GenTypedef
+import Thrift.Compiler.GenUnion
+import Thrift.Compiler.GenUtils
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types as Thrift hiding (noLoc)
+
+data InstancesFile a = InstancesFile
+  { ifPragmas :: [ModulePragma a]
+  , ifImports :: [ImportDecl a]
+  , ifDecls   :: [HS.Decl a]
+  }
+
+data ThriftModule = ThriftModule
+  { tmPath :: FilePath
+  , tmContents :: String
+  , tmModuleName :: String
+  }
+
+writeHsCode :: Options Haskell -> Program Haskell Thrift.Loc -> IO [FilePath]
+writeHsCode opts prog =
+  -- Write the Generated Files
+  mapM writeModule =<< genHsCode opts prog
+
+genHsCode :: Options Haskell -> Program Haskell Thrift.Loc -> IO [ThriftModule]
+genHsCode Options{..} prog@Program{..} = do
+  let
+    progHSPath = Text.unpack $ Text.replace "." "/" progHSName
+    HsOpts{..} = optsLangSpecific
+    dir = progOutPath </> hsoptsGenPrefix </> progHSPath
+  relativeDir <- makeRelativeToCurrentDirectory dir
+
+  let
+    (typesModuleName, typesModuleBase) =
+      genTypesModule prog hsoptsExtensions hsoptsExtraHasFields
+    -- Get instances file if it exists
+    typesModuleBody = case progInstances of
+      Just (Module _ _ pragmas imports decls) ->
+        showModuleWithInstances (relativeDir </> "Types.hs") typesModuleBase $
+        InstancesFile pragmas imports decls
+      _ -> showThriftModule typesModuleBase
+
+  return $
+    ThriftModule
+      (dir </> "Types.hs")
+      typesModuleBody
+      typesModuleName :
+    concat
+      [ [ ThriftModule
+          (dir </> Text.unpack serviceResolvedName </> "Client.hs")
+          (showThriftModule clientModule)
+          clientModuleName
+        , ThriftModule
+          (dir </> Text.unpack serviceResolvedName </> "Service.hs")
+          (showThriftModule serviceModule)
+          serviceModuleName
+        ]
+      | D_Service s@Service{..} <- progDecls
+      , let
+          (clientModuleName, clientModule) = genClientModule prog s
+          (serviceModuleName, serviceModule) = genServiceModule prog s
+      ]
+
+genTypesModule
+  :: Program Haskell Thrift.Loc -> [Text] -> Bool -> (String, Module ())
+genTypesModule prog@Program{..} extensions extraHasFields =
+  genModule prog "Types" pragmas
+    (concat exports)
+    (map genImportModule $ Set.toList imports)
+    (concat decls)
+  where
+    pragmas = commonPragmas (options progEnv) ++
+              map (LanguagePragma () . (:[]) . textToName)
+                (("GeneralizedNewtypeDeriving" : extensions) ++
+                (if extraHasFields then hasFieldsExtensions else []))
+
+    hasFieldsExtensions =
+      [ "DataKinds"
+      , "FlexibleInstances"
+      , "MultiParamTypeClasses"
+      ]
+
+    (decls, imports, exports) = foldr genDecl ([], baseImports, []) progDecls
+    baseImports = Set.fromList $
+      [ QImport "Thrift.CodegenTypesOnly" "Thrift"
+      , QImport "Prelude" "Prelude"
+      ] ++
+      map importFromInclude progIncludes
+
+    genDecl decl (ds, is, es) = (d : ds, Set.union i is, e : es)
+      where
+        (d, i, e) = case decl of
+          D_Struct s ->
+            ( genStructDecl extraHasFields s
+            , genStructImports s
+            , [structExport s]
+            )
+          D_Union u ->
+            (genUnionDecl u, genUnionImports u, [unionExport u])
+          D_Typedef t ->
+            (genTypedefDecl t True, genTypedefImports t, [tdefExport t])
+          D_Enum en -> (genEnumDecl en, genEnumImports, enumExport en)
+          D_Const c -> (genConstDecl c, genConstImports c, [constExport c])
+          -- Services are not included in this module
+          D_Service{} -> mempty
+          -- Interactions are not included in this module
+          D_Interaction{} -> mempty
+
+        tdefExport Typedef{..} = case tdTag of
+          IsNewtype -> newtypeExport tdResolvedName
+          IsTypedef -> EAbs () (NoNamespace ()) $ unqualSym tdResolvedName
+        newtypeExport name =
+          EThingWith () (NoWildcard ()) (unqualSym name)
+          [ ConName () (textToName name)
+          , VarName () (textToName $ "un" <> name)
+          ]
+        structExport :: HS Struct -> ExportSpec ()
+        structExport Struct{..} =
+          EThingWith () (NoWildcard ()) (unqualSym structResolvedName) $
+          ConName () (textToName structResolvedName) :
+          [ VarName () (textToName fieldResolvedName)
+          | Field{..} <- structMembers ]
+        unionExport :: HS Union -> ExportSpec ()
+        unionExport Union{..} =
+          EThingWith () (NoWildcard ()) (unqualSym unionResolvedName) $
+          (case unionHasEmpty of
+             HasEmpty -> (ConName () (textToName unionEmptyName) :)
+             NonEmpty -> id)
+          [ ConName () (textToName altResolvedName) | UnionAlt{..} <- unionAlts ]
+        enumExport :: HS Thrift.Enum -> [ExportSpec ()]
+        enumExport Enum{..} = case enumFlavour of
+          PseudoEnum{} ->
+            newtypeExport enumResolvedName :
+            [ EVar () $ unqualSym evResolvedName
+            | EnumValue{..} <- enumConstants
+            ]
+          SumTypeEnum{..} ->
+            [ EThingWith () (NoWildcard ()) (unqualSym enumResolvedName) $
+              [ ConName () (textToName evResolvedName)
+              | EnumValue{..} <- enumConstants
+              ] ++
+              [ ConName () (textToName $ enumResolvedName <> "__UNKNOWN")
+              | not enumNoUnknown
+              ]
+            ]
+        constExport = EVar () . unqualSym . constResolvedName
+
+genClientModule :: Program Haskell Thrift.Loc -> HS Service -> (String, Module ())
+genClientModule prog@Program{..} service@Service{..} =
+  genModule prog (serviceResolvedName <> ".Client") pragmas exports imports decls
+  where
+    theseFunctions = getServiceFunctions service
+    pragmas = commonPragmas opts ++
+              map (LanguagePragma () . (:[]) . textToName)
+              (["FlexibleContexts", "TypeFamilies", "TypeOperators"] ++
+               hsoptsExtensions optsLangSpecific)
+    exports = EAbs () (NoNamespace ()) (unqualSym serviceResolvedName) :
+              concatMap
+              (\Function{..} ->
+                map (EVar () . unqualSym . ($ funResolvedName)) $
+                [ id, (<> "IO"), ("send_" <>), ("_build_" <>) ] ++
+                (if funIsOneWay then [] else [ ("recv_" <>), ("_parse_"<>) ]))
+              theseFunctions
+    imports = map genImportModule $ Set.toList $ Set.unions $
+              Set.singleton (QImport "Thrift.Codegen" "Thrift") :
+              Set.singleton (TypesImport progHSName) :
+              Set.fromList (map importFromInclude progIncludes) :
+              genClientImports progHSName service :
+              map genFunctionImports theseFunctions
+    decls   = genClientDecls service ++
+              concatMap (genFunctionDecls service) theseFunctions
+    opts@Options{..} = options progEnv
+
+genServiceModule :: Program Haskell Thrift.Loc -> HS Service -> (String, Module ())
+genServiceModule prog@Program{..} service@Service{..} =
+  genModule prog (serviceResolvedName <> ".Service") pragmas exports imports decls
+  where
+    pragmas = commonPragmas (options progEnv) ++
+              [ LanguagePragma () [textToName "GADTs"]
+              ]
+    exports = genServiceExports service
+    imports = map genImportModule $ Set.toList $ Set.unions $
+              Set.singleton (QImport "Thrift.Codegen" "Thrift") :
+              Set.singleton (QImport (progHSName <> ".Types") "Types") :
+              Set.fromList (map importFromInclude progIncludes) :
+              [genServiceImports progHSName service]
+    decls   = genServiceDecls service
+
+commonPragmas :: Options Haskell -> [ModulePragma ()]
+commonPragmas Options{ optsLangSpecific = HsOpts{..} } =
+  (if hsoptsDupNames
+   then (LanguagePragma () [textToName "DuplicateRecordFields"] :)
+   else id)
+  [ LanguagePragma () [textToName "OverloadedStrings"]
+  , LanguagePragma () [textToName "BangPatterns"]
+  , OptionsPragma () (Just GHC) "-fno-warn-unused-imports"
+  , OptionsPragma () (Just GHC) "-fno-warn-overlapping-patterns"
+  , OptionsPragma () (Just GHC) "-fno-warn-incomplete-patterns"
+  , OptionsPragma () (Just GHC) "-fno-warn-incomplete-uni-patterns"
+  , OptionsPragma () (Just GHC) "-fno-warn-incomplete-record-updates"
+  ]
+
+genModule
+  :: Program Haskell Thrift.Loc
+  -> Text
+  -> [ModulePragma ()]
+  -> [ExportSpec ()]
+  -> [ImportDecl ()]
+  -> [HS.Decl ()]
+  -> (String, Module ())
+genModule Program{..} moduleName pragmas exports imports decls =
+  ( fullName
+  , Module ()
+      (Just
+       (ModuleHead () (ModuleName () fullName)
+        Nothing
+        (Just $ ExportSpecList () exports)))
+      pragmas
+      imports
+      decls
+  )
+  where
+    fullName = Text.unpack $ progHSName <> "." <> moduleName
+
+writeModule :: ThriftModule -> IO FilePath
+writeModule ThriftModule{..} = do
+  let (dir, _fname) = breakOnEnd "/" tmPath
+  createDirectoryIfMissing True dir
+  writeFile tmPath tmContents
+  return tmPath
+
+showThriftModule :: Module () -> String
+showThriftModule = showModule autogenComment
+
+showModule :: String -> Module () -> String
+showModule header = (header ++) . prettyPrintWithMode baseMode . (noLoc <$)
+
+showModuleWithInstances
+  :: FilePath
+  -> Module ()
+  -> InstancesFile SrcSpanInfo
+  -> String
+showModuleWithInstances path baseModule InstancesFile{..} = fileBody
+  where
+    -- Put everything together
+    fileBody = foldl1 catWithPragma
+               [ fileHeader, fileImports, fileDecls ]
+    catWithPragma a b = a ++ linePragma (length (lines a)) ++ b
+    linePragma n = printf "{-# LINE %d \"%s\" #-}\n" (n + 2) path
+
+    fileHeader = autogenComment ++ extraPragmas
+    fileImports = unlines imports ++ extraImports
+    fileDecls   = unlines decls ++ extraDecls
+
+    (imports, decls) = splitAt lastImport baseFile
+    baseFile = lines $ prettyPrintWithMode baseMode $ noLoc <$ baseModule
+
+    lenBase = length baseFile
+    lastImport = maybe lenBase (lenBase -) $
+                 findIndex (isPrefixOf "import") $ reverse baseFile
+    -- Pretty Print the extras
+    extraPragmas = annot ifPragmas
+    extraImports = annot ifImports
+    extraDecls   = annot ifDecls
+    annot xs = unlines $ map pp xs
+
+    pp :: (HS.Annotated s, Pretty (s SrcSpanInfo))
+       => s SrcSpanInfo -> String
+    pp d =
+      printf "{-# LINE %d \"%s\" #-}\n" srcSpanStartLine srcSpanFilename
+       ++ prettyPrintWithMode baseMode d
+      where
+        SrcSpanInfo SrcSpan{..} _ = ann d
+
+autogenComment :: String
+autogenComment = unlines
+  [ "-----------------------------------------------------------------"
+  , "-- Autogenerated by Thrift"
+  , "--"
+  , "-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING"
+  , "--  @" ++ "generated"
+  , "-----------------------------------------------------------------"
+  ]
+
+baseMode :: PPHsMode
+baseMode = defaultMode
+  { classIndent   = 2
+  , doIndent      = 3
+  , multiIfIndent = 3
+  , caseIndent    = 2
+  , letIndent     = 2
+  , whereIndent   = 2
+  , onsideIndent  = 2
+  , spacing       = True
+  , layout        = PPOffsideRule
+  }
diff --git a/Thrift/Compiler/GenJSON.hs b/Thrift/Compiler/GenJSON.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenJSON.hs
@@ -0,0 +1,384 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenJSON
+  ( genJSON
+  , writeJSON
+  , getAstPath
+  ) where
+
+import Prelude hiding (Enum)
+import Data.Aeson
+import Data.Aeson.Encode.Pretty
+import Data.ByteString.Builder
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import Data.Proxy
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Lazy as Lazy
+import qualified Data.Text.Lazy.Encoding as Lazy
+import GHC.TypeLits
+import System.Directory
+import System.FilePath
+
+import Util.Aeson
+
+import Thrift.Compiler.Typechecker
+import Thrift.Compiler.Types as Types
+import Thrift.Compiler.Options as Options
+import Thrift.Compiler.Plugin
+
+writeJSON
+  :: Typecheckable l
+  => Program l a         -- ^ Top level program ti generate
+  -> Maybe [Program l a] -- ^ Dependencies if using recursive mode
+  -> IO FilePath
+writeJSON prog deps = do
+  createDirectoryIfMissing True dir
+  LBS.writeFile path $ prettyJSON $ genJSON prog deps
+  return path
+  where
+    path = dir </> file
+    (dir, file) = getAstPath prog
+    prettyJSON = encodePretty' defConfig { confCompare = compare }
+
+getAstPath :: Program l a -> (FilePath, FilePath)
+getAstPath Program{..} = (progOutPath, Text.unpack progName ++ ".ast")
+
+genJSON :: Typecheckable l => Program l a -> Maybe [Program l a] -> Value
+genJSON prog Nothing = Object $ genJSONProg prog
+genJSON prog (Just deps) = toJSON $ genJSONProg prog : map genJSONProg deps
+
+genJSONProg :: Typecheckable l => Program l a -> Object
+genJSONProg Program{..} = objectFromList
+  [ "name"     .= progHSName
+  , "path"     .= progPath
+  , "includes" .= map Types.progPath progIncludes
+  , "typedefs" .= map genTypedef dTdefs
+  , "enums"    .= map genEnum dEnums
+  , "consts"   .= map genConst dConsts
+  , "structs"  .= map genStruct dStructs
+  , "unions"   .= map genUnion dUnions
+  , "services" .= map genService dServs
+  , "options"  .= genOptions (options progEnv)
+  ]
+  where
+    Decls{..} = partitionDecls progDecls
+
+-- Typedefs --------------------------------------------------------------------
+
+genTypedef :: Typecheckable l => Typedef 'Resolved l a -> Object
+genTypedef Typedef{..} = objectFromList
+  [ "name" .= tdResolvedName
+  , "type" .= genType tdResolvedType
+  , "newtype" .= case tdTag of { IsNewtype -> True ; IsTypedef -> False }
+  ]
+
+-- Enums -----------------------------------------------------------------------
+
+genEnum :: Typecheckable l => Enum 'Resolved l a -> Object
+genEnum Enum{..} = objectFromList
+  [ "name"      .= enumResolvedName
+  , "constants" .= map genEnumConst enumConstants
+  , "flavour" .= case enumFlavour of
+      SumTypeEnum{} -> "sum_type" :: Text
+      PseudoEnum{} -> "pseudo"
+  ]
+
+genEnumConst :: EnumValue 'Resolved l a -> Object
+genEnumConst EnumValue{..} = objectFromList
+  [ "name"  .= evResolvedName
+  , "value" .= evValue
+  ]
+
+-- Constants -------------------------------------------------------------------
+
+genConst :: Typecheckable l => Const 'Resolved l a -> Object
+genConst Const{..} = objectFromList
+  [ "name"  .= constResolvedName
+  , "type"  .= genType constResolvedType
+  , "value" .= genConstVal constResolvedType constResolvedVal
+  ]
+
+-- Structs, Exceptions, and Unions ---------------------------------------------
+
+genStruct :: Typecheckable l => Struct 'Resolved l a -> Object
+genStruct Struct{..} = objectFromList
+  [ "name" .= structResolvedName
+  , "struct_type" .= case structType of
+      StructTy    -> "STRUCT" :: Text
+      ExceptionTy -> "EXCEPTION"
+  , "fields" .= map genField structMembers
+  ]
+
+genField :: Typecheckable l => Field u 'Resolved l a -> Object
+genField Field{..} = objectFromList $
+  [ "name"  .= fieldResolvedName
+  , "id"    .= fieldId
+  , "type"  .= genType fieldResolvedType
+  ] ++
+  (case fieldResolvedVal of
+     Nothing -> []
+     Just val -> [ "default_value" .= genConstVal fieldResolvedType val ]) ++
+  (case fieldTag of
+     STRUCT_FIELD -> [ "requiredness" .=
+                       case fieldRequiredness of
+                         Default    -> "default" :: Text
+                         Required{} -> "required"
+                         Optional{} -> "optional"
+                     ]
+     _ -> [])
+
+genUnion :: Typecheckable l => Union 'Resolved l a -> Object
+genUnion Union{..} = objectFromList
+  [ "name"   .= unionResolvedName
+  , "fields" .= map genAlt unionAlts
+  ]
+
+genAlt :: Typecheckable l => UnionAlt 'Resolved l a -> Object
+genAlt UnionAlt{..} = objectFromList
+  [ "name" .= altResolvedName
+  , "id"   .= altId
+  , "type" .= genType altResolvedType
+  ]
+
+-- Services and Functions ------------------------------------------------------
+
+genService :: Typecheckable l => Service 'Resolved l a -> Object
+genService s@Service{..} = objectFromList $
+  [ "name"      .= serviceResolvedName
+  , "functions" .= map genFunction (getServiceFunctions s)
+  ] ++
+  (case serviceSuper of
+     Nothing -> []
+     Just Super{..} -> [ "super" .= genName (fst supResolvedName) ])
+
+genFunction :: Typecheckable l => Function 'Resolved l a -> Object
+genFunction Function{..} = objectFromList
+  [ "name" .= funResolvedName
+  , "return_type" .= case funResolvedType of
+      Nothing -> simpleType "void"
+      Just ty -> withSome ty genType
+  , "args"   .= map genField funArgs
+  , "throws" .= map genField funExceptions
+  , "oneway" .= funIsOneWay
+  ]
+
+-- Types and Constants ---------------------------------------------------------
+
+genType :: Typecheckable l => Type l t -> Object
+
+-- Base Types
+genType I8  = simpleType "byte"
+genType I16 = simpleType "i16"
+genType I32 = simpleType "i32"
+genType I64 = simpleType "i64"
+genType TFloat  = simpleType "float"
+genType TDouble = simpleType "double"
+genType TBool   = simpleType "bool"
+genType TText   = simpleType "string"
+genType TBytes  = simpleType "binary"
+
+-- Collections
+genType (TSet u)       = collectionType "set" u
+genType (THashSet u)   = collectionType "hash_set" u
+genType (TList u)      = collectionType "list" u
+genType (TMap k v)     = mapType "map" k v
+genType (THashMap k v) = mapType "hash_map" k v
+
+-- Named Types
+genType (TStruct name _loc)    = namedType "struct" name
+genType (TException name _loc) = namedType "exception" name
+genType (TUnion name _loc)     = namedType "union" name
+genType (TEnum name _loc _) = namedType "enum" name
+genType (TTypedef name ty _loc) = objectFromList
+  [ "type" .= ("typedef" :: Text)
+  , "name" .= genName name
+  , "inner_type" .= genType ty
+  ]
+genType (TNewtype name ty _loc) = objectFromList
+  [ "type" .= ("newtype" :: Text)
+  , "name" .= genName name
+  , "inner_type" .= genType ty
+  ]
+genType (TSpecial ty) = case backTranslateType ty of
+  (Some u, tag) -> genType u <> objectFromList [ "special" .= tag ]
+
+simpleType :: Text -> Object
+simpleType tyName = objectFromList ["type" .= (String tyName)]
+
+collectionType :: Typecheckable l => Text -> Type l t -> Object
+collectionType tyName u = objectFromList
+  [ "type" .= tyName
+  , "inner_type" .= genType u
+  ]
+
+mapType :: Typecheckable l => Text -> Type l u -> Type l v -> Object
+mapType tyName k v = objectFromList
+  [ "type" .= tyName
+  , "key_type" .= genType k
+  , "val_type" .= genType v
+  ]
+
+namedType :: Text -> Name -> Object
+namedType tyName name = objectFromList
+  [ "type" .= tyName
+  , "name" .= genName name
+  ]
+
+genName :: Name -> Object
+genName Name{..} = objectFromList $
+  [ "name" .= localName resolvedName ] ++
+  [ "src" .= m | QName m _ <- [sourceName] ]
+
+genConstVal :: Typecheckable l => Type l t -> TypedConst l t -> Object
+genConstVal ty (Literal x) =
+  objectFromList [ "literal" .= genLiteral ty x ]
+genConstVal _ (Identifier name _ _loc) =
+  objectFromList [ "named_constant" .= genName name ]
+genConstVal _ (WeirdEnumToInt _ name _ _loc) =
+  objectFromList [ "named_constant_enumToInt" .= genName name ]
+
+genLiteral :: Typecheckable l => Type l t -> t -> Object
+
+-- Base Types
+genLiteral ty@I8  n = simpleLiteral ty n
+genLiteral ty@I16 n = simpleLiteral ty n
+genLiteral ty@I32 n = simpleLiteral ty n
+genLiteral ty@I64 n =
+  -- We need to include the string representation because JSON does not support
+  -- 64 bit integers
+  simpleLiteral ty n <> objectFromList [ "string" .= show n ]
+genLiteral ty@TFloat n =
+  simpleLiteral ty n <>
+  objectFromList [ "binary" .= toLazyText (floatHexFixed n) ]
+genLiteral ty@TDouble n =
+  simpleLiteral ty n <>
+  objectFromList [ "binary" .= toLazyText (doubleHexFixed n) ]
+genLiteral ty@TBool b = simpleLiteral ty b
+genLiteral ty@TText s = simpleLiteral ty s
+-- Serialized as a hexidecimal string
+genLiteral ty@TBytes s = simpleLiteral ty $ toLazyText $ byteStringHex s
+
+-- Collections
+genLiteral (TSet u)       (Set xs)     = listLiteral "set" u xs
+genLiteral (THashSet u)   (HashSet xs) = listLiteral "hash_set" u xs
+genLiteral (TList u)      (List xs)    = listLiteral "list" u xs
+genLiteral (TMap k v)     (Map xs)     = mapLiteral "map" k v xs
+genLiteral (THashMap k v) (HashMap xs) = mapLiteral "hash_map" k v xs
+
+-- Named Types
+genLiteral TStruct{} (Some sval) = genStructVal sval
+genLiteral TException{} (Some (EV sval)) = genStructVal sval
+genLiteral TUnion{} (Some uval) = genUnionVal uval
+genLiteral TEnum{} (EnumVal name _loc) = objectFromList
+  [ "type"  .= ("enum" :: Text)
+  , "value" .= genName name
+  ]
+genLiteral (TTypedef _ ty _loc) x = genLiteral ty x
+genLiteral (TNewtype _ ty _loc) (New x) = objectFromList
+  [ "type"  .= ("newtype" :: Text)
+  , "value" .= genLiteral ty x
+  ]
+genLiteral st@(TSpecial ty) val = case backTranslateLiteral ty val of
+  ThisLit u x -> objectFromList
+    [ "type"  .= genType st
+    , "value" .= genLiteral u x
+    ]
+
+simpleLiteral :: (Typecheckable l, ToJSON a) => Type l t -> a -> Object
+simpleLiteral ty x = genType ty <> objectFromList [ "value" .= x ]
+
+listLiteral :: Typecheckable l => Text -> Type l t -> [TypedConst l t] -> Object
+listLiteral tyName ty xs = objectFromList
+  [ "type"  .= tyName
+  , "value" .= map (genConstVal ty) xs
+  ]
+
+mapLiteral
+  :: Typecheckable l
+  => Text
+  -> Type l k
+  -> Type l v
+  -> [(TypedConst l k, TypedConst l v)]
+  -> Object
+mapLiteral tyName kt vt xs = objectFromList
+  [ "type"  .= tyName
+  , "value" .= map (genPair kt vt) xs
+  ]
+
+genPair
+  :: Typecheckable l
+  => Type l k
+  -> Type l v
+  -> (TypedConst l k, TypedConst l v)
+  -> Value
+genPair kt vt (k, v) = Object $ objectFromList
+  [ "key" .= genConstVal kt k
+  , "val" .= genConstVal vt v
+  ]
+
+genStructVal :: Typecheckable l => StructVal l s -> Object
+genStructVal s = objectFromList
+  [ "type"  .= ("struct" :: Text)
+  , "value" .= genStructFields s
+  ]
+
+genStructFields :: Typecheckable l => StructVal l s -> [Object]
+genStructFields Empty = []
+genStructFields (ConsVal proxy ty c s) =
+  genFieldVal proxy ty c : genStructFields s
+genStructFields (ConsDefault proxy ty s) = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_type"  .= genType ty
+  , "field_value" .=
+    HashMap.singleton ("default" :: Text) Null
+  ] :
+  genStructFields s
+genStructFields (ConsJust proxy ty c s) =
+  genFieldVal proxy ty c : genStructFields s
+genStructFields (ConsNothing proxy s) = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_value" .= Null
+  ] :
+  genStructFields s
+
+genUnionVal :: Typecheckable l => UnionVal l s -> Object
+genUnionVal (UnionVal proxy ty c _) = objectFromList
+  -- This isn't technically a thrift type, but we'll use it anyway
+  [ "type"  .= ("union" :: Text)
+  , "value" .= genFieldVal proxy ty c
+  ]
+
+genFieldVal
+  :: (Typecheckable l, KnownSymbol s)
+  => Proxy s
+  -> Type l t
+  -> TypedConst l t
+  -> Object
+genFieldVal proxy ty c = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_type"  .= genType ty
+  , "field_value" .= genConstVal ty c
+  ]
+
+toLazyText :: Builder -> Lazy.Text
+toLazyText = Lazy.decodeUtf8 . toLazyByteString
+
+-- Options ---------------------------------------------------------------------
+
+genOptions :: Options.Options l -> Object
+genOptions Options.Options{..} = objectFromList
+  [ "path" .= optsPath
+  , "out_path" .= optsOutPath
+  , "include_path" .= optsIncludePath
+  , "recursive" .= optsRecursive
+  , "genfiles" .= optsThriftMade
+  ]
diff --git a/Thrift/Compiler/GenJSONLoc.hs b/Thrift/Compiler/GenJSONLoc.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenJSONLoc.hs
@@ -0,0 +1,607 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE NamedFieldPuns #-}
+module Thrift.Compiler.GenJSONLoc
+  ( -- * Main generation
+    genJSONLoc
+  , writeJSONLoc
+  , getAstPathLoc
+   -- * Utility functions
+  , displayAnnotatedType
+  , genType
+  ) where
+
+import Prelude hiding (Enum)
+import Data.Aeson
+import Data.Aeson.Encode.Pretty
+import Data.ByteString.Builder
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import Data.Proxy
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Lazy as Lazy
+import qualified Data.Text.Lazy.Encoding as Lazy
+import GHC.TypeLits
+import System.Directory
+import System.FilePath
+
+import Util.Aeson
+
+import Thrift.Compiler.Typechecker
+import Thrift.Compiler.Types as Types
+import Thrift.Compiler.Options as Options
+import Thrift.Compiler.Plugin
+-- import Thrift.Compiler.Types as Thrift hiding (noLoc)
+
+writeJSONLoc
+  :: Typecheckable l
+  => Program l Loc         -- ^ Top level program ti generate
+  -> Maybe [Program l Loc] -- ^ Dependencies if using recursive mode
+  -> IO FilePath
+writeJSONLoc prog deps = do
+  createDirectoryIfMissing True dir
+  LBS.writeFile path $ prettyJSON $ genJSONLoc prog deps
+  return path
+  where
+    path = dir </> file
+    (dir, file) = getAstPathLoc prog
+    prettyJSON = encodePretty' defConfig { confCompare = compare }
+
+getAstPathLoc :: Program l a -> (FilePath, FilePath)
+getAstPathLoc Program{..} = (progOutPath, Text.unpack progName ++ ".ast")
+
+genJSONLoc :: Typecheckable l => Program l Loc -> Maybe [Program l Loc] -> Value
+genJSONLoc prog Nothing = Object $ genJSONProg prog
+genJSONLoc prog (Just deps) = toJSON $ genJSONProg prog : map genJSONProg deps
+
+genJSONProg :: Typecheckable l => Program l Loc -> Object
+genJSONProg Program{..} = objectFromList
+  [ "name"     .= progHSName
+  , "path"     .= progPath
+  , "includes" .= map Types.progPath progIncludes
+  , "typedefs" .= map genTypedef dTdefs
+  , "enums"    .= map genEnum dEnums
+  , "consts"   .= map genConst dConsts
+  , "structs"  .= map genStruct dStructs
+  , "unions"   .= map genUnion dUnions
+  , "services" .= map genService dServs
+  , "options"  .= genOptions (options progEnv)
+  ]
+  where
+    Decls{..} = partitionDecls progDecls
+
+-- Locs ------------------------------------------------------------------------
+
+tx :: Text -> Text
+tx = id
+
+displayLoc :: Loc -> Text
+displayLoc = Text.pack . show
+
+displayLocated :: Located Loc -> Text
+displayLocated = displayLoc . lLocation
+
+displayTypeLoc :: TypeLoc n Loc -> [Text]
+displayTypeLoc x = map displayLocated $ case x of
+   Arity0Loc{..} -> [a0Ty]
+   Arity1Loc{..} -> [a1Ty, a1OpenBrace, a1CloseBrace]
+   Arity2Loc{..} -> [a2Ty, a2OpenBrace, a2Comma, a2CloseBrace]
+
+displaySeparator :: Separator Loc -> Object
+displaySeparator (Semicolon loc) = objectFromList
+  [ "sep_type" .= tx "Semicolon"
+  , "loc" .= displayLocated loc
+  ]
+displaySeparator (Comma loc) = objectFromList
+  [ "sep_type" .= tx "Comma"
+  , "loc" .= displayLocated loc
+  ]
+displaySeparator NoSep = objectFromList
+  [ "sep_type" .= tx"NoSep"
+  ]
+
+displayAnnValue :: AnnValue -> Object
+displayAnnValue (IntAnn i v) = objectFromList
+  [ "ann_value_type" .= tx "IntAnn"
+  , "i" .= i
+  , "v" .= v
+  ]
+displayAnnValue (TextAnn t q) = objectFromList
+  [ "ann_value_type" .=  tx "TextAnn"
+  , "t" .= t
+  , "q" .= Text.pack (show q)
+  ]
+
+displayAnnotation :: Annotation Loc -> Object
+displayAnnotation SimpleAnn{..} = objectFromList
+  [ "ann_type" .= tx "SimpleAnn"
+  , "ann_tag" .= saTag
+  , "loc" .= displayLocated saLoc
+  , "sep" .= displaySeparator saSep
+  ]
+displayAnnotation ValueAnn{..} = objectFromList
+  [ "ann_type" .= tx "ValueAnn"
+  , "tag" .= vaTag
+  , "val" .= displayAnnValue vaVal
+  , "loc_tag" .= displayLocated vaTagLoc
+  , "loc_equal" .= displayLocated vaEqual
+  , "loc_val" .= displayLocated vaValLoc
+  , "sep" .= displaySeparator vaSep
+  ]
+
+displayAnnotations :: Annotations Loc -> Object
+displayAnnotations Annotations{..} = objectFromList
+  [ "loc_open" .= displayLocated annOpenParen
+  , "loc_close" .= displayLocated annCloseParen
+  , "loc_ann_list" .= map displayAnnotation annList
+  ]
+
+displayAnnotatedType :: forall t. AnnotatedType Loc t -> Object
+displayAnnotatedType AnnotatedType{..} = objectFromList
+  [ "type" .= (genTType (atType :: Un t) :: Object)
+  , "anns" .= maybe Null (Object . displayAnnotations) atAnnotations
+  , "loc" .= displayTypeLoc atLoc
+  ]
+
+-- Reconstruct -----------------------------------------------------------------
+
+-- The resolved Loc is in mkTypemap, mkSchemaMap, etc in typecheckModule.
+-- I expect that the cross-ref are discovered in envLookup and envCtxLookup
+-- when run during resolveDecls, but only implicitly.
+--
+-- Here the correspondance is reconstructed
+
+reconstructXRef
+  :: Typecheckable l
+  =>  AnnotatedType Loc v
+  -> Type l t
+  -> [(Loc, Loc)]
+reconstructXRef atIn@AnnotatedType{atType, atLoc} rt = case (atType, rt) of
+    (TSet at1, TSet rt1) -> reconstructXRef at1 rt1
+    (THashSet at1, THashSet rt1) -> reconstructXRef at1 rt1
+    (TList at1, TList rt1) -> reconstructXRef at1 rt1
+    (TMap ak av, TMap rk rv) ->
+      reconstructXRef ak rk ++ reconstructXRef av rv
+    (THashMap ak av, THashMap rk rv) ->
+      reconstructXRef ak rk ++ reconstructXRef av rv
+    (TNamed{}, TTypedef _ _ rtLoc) -> [(getTypeLoc atLoc, rtLoc)]
+    (TNamed{}, TNewtype _ _ rtLoc) -> [(getTypeLoc atLoc, rtLoc)]
+    (TNamed{}, TStruct _ rtLoc) -> [(getTypeLoc atLoc, rtLoc)]
+    (TNamed{}, TException _ rtLoc) -> [(getTypeLoc atLoc, rtLoc)]
+    (TNamed{}, TUnion _ rtLoc) -> [(getTypeLoc atLoc, rtLoc)]
+    (TNamed{}, TEnum _ rtLoc _) -> [(getTypeLoc atLoc, rtLoc)]
+    (_, TSpecial st) -> case backTranslateType st of
+      (Some rtSimple, _) -> reconstructXRef atIn rtSimple
+    _ -> []
+
+displayXRef
+  ::  Typecheckable l
+  =>  AnnotatedType Loc v
+  -> Type l t
+  -> [Value]
+displayXRef at rt = map oneXRef (reconstructXRef at rt)
+
+-- | JSON encode a pair of location, fst is usage and snd is definition. Want
+-- to hyperlink from usage to destination, and perhaps list all usages of the
+-- destination.
+oneXRef :: (Loc, Loc) -> Value
+oneXRef (aLoc, rLoc) = Object $ objectFromList
+  [ "aLoc" .= displayLoc aLoc
+  , "rLoc" .= displayLoc rLoc ]
+
+-- | Make this notice when the const value is another const or enum value
+-- and reference the defintion. Enrich the Identifier and EnumVal
+-- constructors to easily link them.
+reconstructXRefConst
+  :: Typecheckable l
+  => UntypedConst Loc
+  -> TypedConst l t
+  -> Type l t
+  -> [(Loc, Loc)]
+reconstructXRefConst UntypedConst{ucLoc} (Identifier _name _rt rLoc) _ =
+  [(lLocation ucLoc, rLoc)]
+reconstructXRefConst UntypedConst{ucLoc} (WeirdEnumToInt _ _ _ rLoc) _ =
+  [(lLocation ucLoc, rLoc)]
+reconstructXRefConst UntypedConst{ucLoc} (Literal ev) (TEnum _ _loc _) =
+  let EnumVal _name rLocVal = ev in [(lLocation ucLoc, rLocVal)]
+reconstructXRefConst _ Literal{} _ = []
+
+-- | Eventually make this notice when the const value is another const
+-- and hyperlink that value (Identifier)
+displayXRefConst
+  :: Typecheckable l
+  => UntypedConst Loc
+  -> TypedConst l t
+  -> Type l t
+  -> [Value]
+displayXRefConst uc tc ty = map oneXRef (reconstructXRefConst uc tc ty)
+
+-- Typedefs --------------------------------------------------------------------
+
+genTypedef :: Typecheckable l => Typedef 'Resolved l Loc -> Object
+genTypedef Typedef{..} = objectFromList
+  [ "name" .= tdResolvedName
+  , "type" .= genType tdResolvedType
+  , "ann_type" .= displayAnnotatedType tdType
+  , "newtype" .= case tdTag of { IsNewtype -> True ; IsTypedef -> False }
+  , "loc_keyword" .= displayLocated (tdlKeyword tdLoc)
+  , "loc_name" .= displayLocated (tdlName tdLoc)
+  , "anns" .= maybe Null (Object . displayAnnotations) tdAnns
+  , "xref" .= displayXRef tdType tdResolvedType
+  ]
+
+-- Enums -----------------------------------------------------------------------
+
+genEnum :: Typecheckable l => Enum 'Resolved l Loc -> Object
+genEnum Enum{..} = objectFromList
+  [ "name"      .= enumResolvedName
+  , "constants" .= map genEnumConst enumConstants
+  , "flavour" .= case enumFlavour of
+      SumTypeEnum{} -> "sum_type" :: Text
+      PseudoEnum{} -> "pseudo"
+  , "loc_keyword" .= displayLocated (slKeyword enumLoc)
+  , "loc_name" .= displayLocated (slName enumLoc)
+  ]
+
+genEnumConst :: EnumValue 'Resolved l Loc -> Object
+genEnumConst EnumValue{..} = objectFromList
+  [ "name"  .= evResolvedName
+  , "value" .= evValue
+  , "loc_name" .= displayLocated (evlName evLoc)
+  ]
+
+-- Constants -------------------------------------------------------------------
+
+genConst :: Typecheckable l => Const 'Resolved l Loc -> Object
+genConst Const{..} = objectFromList
+  [ "name"  .= constResolvedName
+  , "type"  .= genType constResolvedType
+  , "value" .= genConstVal constResolvedType constResolvedVal
+  , "ann_type" .= displayAnnotatedType constType
+  , "loc_keyword" .= displayLocated (clKeyword constLoc)
+  , "loc_name" .= displayLocated (clName constLoc)
+  , "xref" .= (displayXRef constType constResolvedType
+                ++ displayXRefConst constVal constResolvedVal constResolvedType)
+  ]
+
+-- Structs, Exceptions, and Unions ---------------------------------------------
+
+genStruct :: Typecheckable l => Struct 'Resolved l Loc -> Object
+genStruct Struct{..} = objectFromList
+  [ "name" .= structResolvedName
+  , "struct_type" .= case structType of
+      StructTy    -> "STRUCT" :: Text
+      ExceptionTy -> "EXCEPTION"
+  , "fields" .= map genField structMembers
+  , "loc_keyword" .= displayLocated (slKeyword structLoc)
+  , "loc_name" .= displayLocated (slName structLoc)
+  ]
+
+genField :: Typecheckable l => Field u 'Resolved l Loc -> Object
+genField Field{..} = objectFromList $
+  [ "name"  .= fieldResolvedName
+  , "id"    .= fieldId
+  , "type"  .= genType fieldResolvedType
+  , "xref"  .= displayXRef fieldType fieldResolvedType
+  , "loc_name" .= displayLocated (flName fieldLoc)
+  ] ++
+  (case fieldResolvedVal of
+     Nothing -> []
+     Just val -> [ "default_value" .= genConstVal fieldResolvedType val ]) ++
+  (case fieldTag of
+     STRUCT_FIELD -> [ "requiredness" .=
+                       case fieldRequiredness of
+                         Default    -> "default" :: Text
+                         Required{} -> "required"
+                         Optional{} -> "optional"
+                     ]
+     _ -> [])
+
+genUnion :: Typecheckable l => Union 'Resolved l Loc -> Object
+genUnion Union{..} = objectFromList
+  [ "name"   .= unionResolvedName
+  , "fields" .= map genAlt unionAlts
+  , "loc_keyword" .= displayLocated (slKeyword unionLoc)
+  , "loc_name" .= displayLocated (slName unionLoc)
+  ]
+
+genAlt :: Typecheckable l => UnionAlt 'Resolved l Loc -> Object
+genAlt UnionAlt{..} = objectFromList
+  [ "name" .= altResolvedName
+  , "id"   .= altId
+  , "type" .= genType altResolvedType
+  , "loc_name" .= displayLocated (flName altLoc)
+  ]
+
+-- Services and Functions ------------------------------------------------------
+
+genService :: Typecheckable l => Service 'Resolved l Loc -> Object
+genService s@Service{..} = objectFromList $
+  [ "name"      .= serviceResolvedName
+  , "functions" .= map genFunction (getServiceFunctions s)
+  , "loc_keyword" .= displayLocated (slKeyword serviceLoc)
+  , "loc_name" .= displayLocated (slName serviceLoc)
+  ] ++
+  (case serviceSuper of
+     Nothing -> []
+     Just Super{..} -> [ "super" .= genName (fst supResolvedName) ])
+
+genFunction :: Typecheckable l => Function 'Resolved l Loc -> Object
+genFunction Function{..} = objectFromList
+  [ "name" .= funResolvedName
+  , "return_type" .= case funResolvedType of
+      Nothing -> simpleType "void"
+      Just ty -> withSome ty genType
+  , "args"   .= map genField funArgs
+  , "throws" .= map genField funExceptions
+  , "oneway" .= funIsOneWay
+  , "loc_name" .= displayLocated (fnlName funLoc)
+  ]
+
+
+-- Unresolved Types and Constants ----------------------------------------------
+
+type Un t = TType 'Unresolved () Loc t
+
+genTType :: Un t -> Object
+
+-- Base Types
+genTType I8  = simpleType "byte"
+genTType I16 = simpleType "i16"
+genTType I32 = simpleType "i32"
+genTType I64 = simpleType "i64"
+genTType TFloat  = simpleType "float"
+genTType TDouble = simpleType "double"
+genTType TBool   = simpleType "bool"
+genTType TText   = simpleType "string"
+genTType TBytes  = simpleType "binary"
+
+-- Collections
+genTType (TSet u)       = collectionTType "set" u
+genTType (THashSet u)   = collectionTType "hash_set" u
+genTType (TList u)      = collectionTType "list" u
+genTType (TMap k v)     = mapTType "map" k v
+genTType (THashMap k v) = mapTType "hash_map" k v
+
+-- Named Types
+
+genTType (TNamed n) = simpleName n
+
+collectionTType :: Text -> AnnotatedType Loc t -> Object
+collectionTType tyName u = objectFromList
+  [ "type" .= tyName
+  , "inner_type" .= displayAnnotatedType u
+  ]
+
+mapTType :: Text -> AnnotatedType Loc k -> AnnotatedType Loc v -> Object
+mapTType tyName k v = objectFromList
+  [ "type" .= tyName
+  , "key_type" .= displayAnnotatedType k
+  , "val_type" .= displayAnnotatedType v
+  ]
+
+simpleName :: Text -> Object
+simpleName tyName = objectFromList ["name" .= (String tyName)]
+
+-- Types and Constants ---------------------------------------------------------
+
+genType :: Typecheckable l => Type l t -> Object
+
+-- Base Types
+genType I8  = simpleType "byte"
+genType I16 = simpleType "i16"
+genType I32 = simpleType "i32"
+genType I64 = simpleType "i64"
+genType TFloat  = simpleType "float"
+genType TDouble = simpleType "double"
+genType TBool   = simpleType "bool"
+genType TText   = simpleType "string"
+genType TBytes  = simpleType "binary"
+
+-- Collections
+genType (TSet u)       = collectionType "set" u
+genType (THashSet u)   = collectionType "hash_set" u
+genType (TList u)      = collectionType "list" u
+genType (TMap k v)     = mapType "map" k v
+genType (THashMap k v) = mapType "hash_map" k v
+
+-- Named Types
+genType (TStruct name loc)    = namedType "struct" name loc
+genType (TException name loc) = namedType "exception" name loc
+genType (TUnion name loc)     = namedType "union" name loc
+genType (TEnum name loc _)      = namedType "enum" name loc
+genType (TTypedef name ty loc) = objectFromList
+  [ "type" .= ("typedef" :: Text)
+  , "name" .= genName name
+  , "inner_type" .= genType ty
+  , "loc" .= displayLoc loc
+  ]
+genType (TNewtype name ty loc) = objectFromList
+  [ "type" .= ("newtype" :: Text)
+  , "name" .= genName name
+  , "inner_type" .= genType ty
+  , "loc" .= displayLoc loc
+  ]
+genType (TSpecial ty) = case backTranslateType ty of
+  (Some u, tag) -> genType u <> objectFromList [ "special" .= tag ]
+
+simpleType :: Text -> Object
+simpleType tyName = objectFromList ["type" .= (String tyName)]
+
+collectionType :: Typecheckable l => Text -> Type l t -> Object
+collectionType tyName u = objectFromList
+  [ "type" .= tyName
+  , "inner_type" .= genType u
+  ]
+
+mapType :: Typecheckable l => Text -> Type l u -> Type l v -> Object
+mapType tyName k v = objectFromList
+  [ "type" .= tyName
+  , "key_type" .= genType k
+  , "val_type" .= genType v
+  ]
+
+namedType :: Text -> Name -> Loc -> Object
+namedType tyName name loc = objectFromList
+  [ "type" .= tyName
+  , "name" .= genName name
+  , "loc" .= displayLoc loc
+  ]
+
+genName :: Name -> Object
+genName Name{..} = objectFromList $
+  [ "name" .= localName resolvedName ] ++
+  [ "src" .= m | QName m _ <- [sourceName] ]
+
+genConstVal :: Typecheckable l => Type l t -> TypedConst l t -> Object
+genConstVal ty (Literal x) =
+  objectFromList [ "literal" .= genLiteral ty x ]
+genConstVal _ (Identifier name _ _loc) =
+  objectFromList [ "named_constant" .= genName name ]
+genConstVal _ (WeirdEnumToInt _ name _ _loc) =
+  objectFromList [ "named_constant_enumToInt" .= genName name ]
+
+genLiteral :: Typecheckable l => Type l t -> t -> Object
+
+-- Base Types
+genLiteral ty@I8  n = simpleLiteral ty n
+genLiteral ty@I16 n = simpleLiteral ty n
+genLiteral ty@I32 n = simpleLiteral ty n
+genLiteral ty@I64 n =
+  -- We need to include the string representation because JSON does not support
+  -- 64 bit integers
+  simpleLiteral ty n <> objectFromList [ "string" .= show n ]
+genLiteral ty@TFloat n =
+  simpleLiteral ty n <>
+  objectFromList [ "binary" .= toLazyText (floatHexFixed n) ]
+genLiteral ty@TDouble n =
+  simpleLiteral ty n <>
+  objectFromList [ "binary" .= toLazyText (doubleHexFixed n) ]
+genLiteral ty@TBool b = simpleLiteral ty b
+genLiteral ty@TText s = simpleLiteral ty s
+-- Serialized as a hexidecimal string
+genLiteral ty@TBytes s = simpleLiteral ty $ toLazyText $ byteStringHex s
+
+-- Collections
+genLiteral (TSet u)       (Set xs)     = listLiteral "set" u xs
+genLiteral (THashSet u)   (HashSet xs) = listLiteral "hash_set" u xs
+genLiteral (TList u)      (List xs)    = listLiteral "list" u xs
+genLiteral (TMap k v)     (Map xs)     = mapLiteral "map" k v xs
+genLiteral (THashMap k v) (HashMap xs) = mapLiteral "hash_map" k v xs
+
+-- Named Types
+genLiteral TStruct{} (Some sval) = genStructVal sval
+genLiteral TException{} (Some (EV sval)) = genStructVal sval
+genLiteral TUnion{} (Some uval) = genUnionVal uval
+genLiteral TEnum{} (EnumVal name _loc) = objectFromList
+  [ "type"  .= ("enum" :: Text)
+  , "value" .= genName name
+  ]
+genLiteral (TTypedef _ ty _loc) x = genLiteral ty x
+genLiteral (TNewtype _ ty _loc) (New x) = objectFromList
+  [ "type"  .= ("newtype" :: Text)
+  , "value" .= genLiteral ty x
+  ]
+genLiteral st@(TSpecial ty) val = case backTranslateLiteral ty val of
+  ThisLit u x -> objectFromList
+    [ "type"  .= genType st
+    , "value" .= genLiteral u x
+    ]
+
+simpleLiteral :: (Typecheckable l, ToJSON a) => Type l t -> a -> Object
+simpleLiteral ty x = genType ty <> objectFromList [ "value" .= x ]
+
+listLiteral :: Typecheckable l => Text -> Type l t -> [TypedConst l t] -> Object
+listLiteral tyName ty xs = objectFromList
+  [ "type"  .= tyName
+  , "value" .= map (genConstVal ty) xs
+  ]
+
+mapLiteral
+  :: Typecheckable l
+  => Text
+  -> Type l k
+  -> Type l v
+  -> [(TypedConst l k, TypedConst l v)]
+  -> Object
+mapLiteral tyName kt vt xs = objectFromList
+  [ "type"  .= tyName
+  , "value" .= map (genPair kt vt) xs
+  ]
+
+genPair
+  :: Typecheckable l
+  => Type l k
+  -> Type l v
+  -> (TypedConst l k, TypedConst l v)
+  -> Value
+genPair kt vt (k, v) = Object $ objectFromList
+  [ "key" .= genConstVal kt k
+  , "val" .= genConstVal vt v
+  ]
+
+genStructVal :: Typecheckable l => StructVal l s -> Object
+genStructVal s = objectFromList
+  [ "type"  .= ("struct" :: Text)
+  , "value" .= genStructFields s
+  ]
+
+genStructFields :: Typecheckable l => StructVal l s -> [Object]
+genStructFields Empty = []
+genStructFields (ConsVal proxy ty c s) =
+  genFieldVal proxy ty c : genStructFields s
+genStructFields (ConsDefault proxy ty s) = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_type"  .= genType ty
+  , "field_value" .=
+    HashMap.singleton ("default" :: Text) Null
+  ] :
+  genStructFields s
+genStructFields (ConsJust proxy ty c s) =
+  genFieldVal proxy ty c : genStructFields s
+genStructFields (ConsNothing proxy s) = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_value" .= Null
+  ] :
+  genStructFields s
+
+genUnionVal :: Typecheckable l => UnionVal l s -> Object
+genUnionVal (UnionVal proxy ty c _) = objectFromList
+  -- This isn't technically a thrift type, but we'll use it anyway
+  [ "type"  .= ("union" :: Text)
+  , "value" .= genFieldVal proxy ty c
+  ]
+
+genFieldVal
+  :: (Typecheckable l, KnownSymbol s)
+  => Proxy s
+  -> Type l t
+  -> TypedConst l t
+  -> Object
+genFieldVal proxy ty c = objectFromList
+  [ "field_name"  .= symbolVal proxy
+  , "field_type"  .= genType ty
+  , "field_value" .= genConstVal ty c
+  ]
+
+toLazyText :: Builder -> Lazy.Text
+toLazyText = Lazy.decodeUtf8 . toLazyByteString
+
+-- Options ---------------------------------------------------------------------
+
+genOptions :: Options.Options l -> Object
+genOptions Options.Options{..} = objectFromList
+  [ "path" .= optsPath
+  , "out_path" .= optsOutPath
+  , "include_path" .= optsIncludePath
+  , "recursive" .= optsRecursive
+  , "genfiles" .= optsThriftMade
+  ]
diff --git a/Thrift/Compiler/GenService.hs b/Thrift/Compiler/GenService.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenService.hs
@@ -0,0 +1,463 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE CPP #-}
+
+module Thrift.Compiler.GenService
+  ( genServiceDecls
+  , genServiceImports
+  , genServiceExports
+  ) where
+
+import Control.Monad
+#if __GLASGOW_HASKELL__ <= 804
+import Data.Monoid ((<>))
+#endif
+import Data.Maybe (isNothing)
+import qualified Data.Set as Set
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.GenStruct
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types hiding (Decl(..))
+
+
+-- | All things required to generate a Service.hs file
+
+genServiceExports :: HS Service -> [HS.ExportSpec ()]
+genServiceExports s =
+  (if isEmptyService s
+  then HS.EAbs () (NoNamespace ()) (unqualSym $ commandTypeName s)
+  else HS.EThingWith () (EWildcard () 0) (unqualSym $ commandTypeName s) [])
+  : map (HS.EVar () . UnQual () . Ident ())
+    ["reqName'", "reqParser'", "respWriter'", "methodsInfo'"]
+
+genServiceImports :: Text.Text -> HS Service -> Set.Set Import
+genServiceImports this s@Service{..} =
+  foldr (Set.union . importsForFunc) baseImports (getServiceFunctions s)
+  where
+    importsForFunc Function{..} =
+      foldr (Set.union . getImports) (retImport funResolvedType) funArgs
+      where
+        retImport Nothing = Set.empty
+        retImport (Just (Some i)) = typeToImport i
+
+    getImports :: HS (Field u) -> Set.Set Import
+    getImports Field{..} = typeToImport fieldResolvedType
+
+    baseImports = Set.fromList
+      [ QImport "Prelude" "Prelude"
+      , QImport "Control.Exception" "Exception"
+      , QImport "Control.Monad.ST.Trans" "ST"
+      , QImport "Control.Monad.Trans.Class" "Trans"
+      , QImport "Data.ByteString.Builder" "Builder"
+      , QImport "Data.Default" "Default"
+      , QImport "Data.HashMap.Strict" "HashMap"
+      , QImport "Data.Map.Strict" "Map"
+      , QImport "Data.Int" "Int"
+      , QImport "Data.Proxy" "Proxy"
+      , QImport "Data.Text" "Text"
+      , QImport "Thrift.Binary.Parser" "Parser"
+      , QImport "Thrift.Protocol.ApplicationException.Types" "Thrift"
+      , QImport "Thrift.Processor" "Thrift"
+      , SymImport "Prelude"
+        [ "<$>", "<*>", "++", ".", "==" ]
+      , SymImport "Control.Applicative" [ "<*", "*>" ]
+      , SymImport "Data.Monoid" [ "<>" ]
+      ] `Set.union`
+      (case resolvedName . fst . supResolvedName <$> serviceSuper of
+        Nothing -> Set.empty
+        Just (UName n) -> mkImport this n
+        Just (QName m n) -> mkImport m n)
+    mkImport m n =
+      Set.singleton $ QImport (Text.intercalate "." [m, n, "Service"]) n
+
+genServiceDecls :: HS Service -> [HS.Decl ()]
+genServiceDecls s =
+  [ genCommandDT s
+  , processorInstance
+  ] ++ concat
+  [ genReqName s
+  , genReqParser s
+  , genRespWriter s
+  , genMethodsInfo s
+  ]
+
+  where
+    processorInstance = HS.InstDecl () Nothing
+      (HS.IRule () Nothing Nothing $
+       HS.IHApp ()
+         (HS.IHCon () $ qualSym "Thrift" "Processor")
+         (HS.TyCon () $ unqualSym $ commandTypeName s)
+      )
+      (Just $ classFuns ++ additional)
+
+    classFuns = flip map [ "reqName" , "reqParser" , "respWriter" ] $ \fn ->
+      HS.InsDecl () $ HS.FunBind () [ HS.Match () (textToName fn) []
+        (HS.UnGuardedRhs () $ con (fn <> "'")) Nothing
+      ]
+
+    additional =
+      [ HS.InsDecl () $ HS.FunBind ()
+        [ HS.Match () (textToName "methodsInfo") [HS.PWildCard ()]
+          (HS.UnGuardedRhs () $ var "methodsInfo'") Nothing
+        ]
+      ]
+
+-- | Generates a GADT for all functions that the service can implement
+-- If extending a service, adds a "Super<Name>" constructor to forward
+-- requests along
+genCommandDT :: HS Service -> HS.Decl ()
+genCommandDT s@Service{..} = HS.GDataDecl () (HS.DataType ()) Nothing
+  (HS.DHApp ()
+     (HS.DHead () (textToName $ commandTypeName s))
+     (HS.UnkindedVar () (HS.Ident () "a")))
+  Nothing
+  genFunctions
+  mzero
+  where
+    genFunctions = map genDTFunction (getServiceFunctions s) ++
+      case fst . supResolvedName <$> serviceSuper of
+        Nothing -> []
+        Just Name{..} -> [genSuper $ localName resolvedName]
+
+    genSuper superName =
+      HS.GadtDecl () (textToName $ "Super" <> superName)
+#if MIN_VERSION_haskell_src_exts(1,21,0)
+        Nothing Nothing
+#endif
+        Nothing $
+        HS.TyFun ()
+        (qualType superName (superName <> "Command") `appT` simpleType "a")
+        (simpleType (commandTypeName s) `appT` tvar "a")
+
+    genDTFunction Function{..} =
+      HS.GadtDecl () (textToName $ toCamel funName)
+#if MIN_VERSION_haskell_src_exts(1,21,0)
+        Nothing Nothing
+#endif
+        Nothing (mkArgs funArgs)
+      where
+        mkArgs = foldr
+          (\Field{..} ->
+            HS.TyFun () $ genType $ qualifyType "Types" fieldResolvedType)
+          (simpleType (commandTypeName s) `appT`
+            maybe (HS.unit_tycon ())
+            (`withSome` (genType . qualifyType "Types")) funResolvedType)
+
+-- | Generates a function that returns a Text name for the given function
+genReqName :: HS Service -> [HS.Decl ()]
+genReqName s@Service{..} =
+  [ HS.TypeSig () [textToName "reqName'"] $ HS.TyFun ()
+      (HS.TyApp () (simpleType $ commandTypeName s) (simpleType "a"))
+      (qualType "Text" "Text")
+  ] ++ map genFunction theseFunctions ++
+    case fst . supResolvedName <$> serviceSuper of
+      Nothing -> noParentBody (null theseFunctions)
+      Just Name{..} -> [genSuper $ localName resolvedName]
+
+  where
+    theseFunctions = getServiceFunctions s
+    genSuper superName = HS.FunBind ()
+      [ HS.Match () (textToName "reqName'")
+        [HS.PParen () $ HS.PApp ()
+           (HS.UnQual () $ textToName $ "Super" <> superName) [pvar "x"]]
+        (HS.UnGuardedRhs () $ qvar superName "reqName'" `app` var "x")
+        Nothing
+      ]
+
+    genFunction Function{..} = HS.FunBind ()
+      [ HS.Match () (textToName "reqName'")
+        [HS.PApp () (unqualSym $ toCamel funName) $
+          map (\Field{..} -> pvar ("__field__" <> fieldName)) funArgs]
+        (HS.UnGuardedRhs () $ stringLit funName)
+        Nothing
+      ]
+
+    noParentBody False = []
+
+    noParentBody True = [ HS.FunBind ()
+      [ HS.Match () (textToName "reqName'")
+        [ HS.PWildCard () ]
+        (HS.UnGuardedRhs () (stringLit "unknown function"))
+        Nothing
+      ]]
+
+-- | Generates a function that parses the input message as appropriate
+genReqParser :: HS Service -> [HS.Decl ()]
+genReqParser s@Service{..} =
+  [ HS.TypeSig () [textToName "reqParser'"] $
+    HS.TyForall () Nothing
+#if MIN_VERSION_haskell_src_exts(1,22,0)
+      (Just $ HS.CxSingle () $ HS.TypeA () (HS.TyApp () (HS.TyCon () (qualSym "Thrift" "Protocol"))
+        (tvar "p" ))) $
+#else
+      (Just $ HS.CxSingle () $ HS.ClassA () (qualSym "Thrift" "Protocol")
+        [ tvar "p" ]) $
+#endif
+    HS.TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    HS.TyFun () (qualType "Text" "Text") $
+    HS.TyApp () (qualType "Parser" "Parser") $ HS.TyParen () $
+      qualType "Thrift" "Some" `appT` simpleType (commandTypeName s)
+  ] ++
+  map genFunction (getServiceFunctions s) ++
+  genSuper serviceSuper
+  where
+    genSuper Nothing = [ HS.FunBind ()
+      [ HS.Match () (textToName "reqParser'")
+        [ HS.PWildCard (), pvar "funName"]
+        (HS.UnGuardedRhs () (qvar "Prelude" "errorWithoutStackTrace" `app` HS.Paren ()
+           (infixApp "++" (stringLit "unknown function call: ")
+           (qvar "Text" "unpack" `app` var "funName"))))
+        Nothing
+      ]]
+    genSuper (Just Super{..}) =
+      let n = localName $ resolvedName $ fst supResolvedName in
+      [ HS.FunBind ()
+      [ HS.Match () (textToName "reqParser'")
+        [ pvar "_proxy", pvar "funName" ]
+        (HS.UnGuardedRhs () $ HS.Do ()
+          [ HS.Generator () (HS.PApp () (qualSym "Thrift" "Some") [ pvar "x" ])
+             (qvar (toCamel n) "reqParser'" `app`
+              var "_proxy" `app`
+              var "funName")
+          , HS.Qualifier ()
+             (qvar "Prelude" "return" `app` HS.Paren ()
+               (qcon "Thrift" "Some" `app`
+                HS.Paren () (
+                  con ("Super" <> n) `app`
+                  var "x"
+                )))
+          ])
+        Nothing
+      ]]
+
+    genFunction Function{..} = HS.FunBind ()
+      [ HS.Match () (textToName "reqParser'")
+        [ pvar "_proxy", stringP funName ]
+        (genFieldParser (map (qualifyField "Types") funArgs)
+         (toCamel funName)
+         (app (qcon "Thrift" "Some")))
+        Nothing
+      ]
+
+-- | Generates a function that builds the appropriate response type
+genRespWriter :: HS Service -> [HS.Decl ()]
+genRespWriter s@Service{..} =
+  [ HS.TypeSig () [textToName "respWriter'"] $
+    HS.TyForall () Nothing
+#if MIN_VERSION_haskell_src_exts(1,22,0)
+      (Just $ HS.CxSingle () $ HS.TypeA () (HS.TyApp () (HS.TyCon () (qualSym "Thrift" "Protocol"))
+        (tvar "p" ))) $
+#else
+      (Just $ HS.CxSingle () $ HS.ClassA () (qualSym "Thrift" "Protocol")
+        [ tvar "p" ]) $
+#endif
+    HS.TyFun () (qualType "Proxy" "Proxy" `appT` tvar "p") $
+    HS.TyFun () (qualType "Int" "Int32") $
+    HS.TyFun () (simpleType (commandTypeName s) `appT` tvar "a") $
+    HS.TyFun ()
+    (qualType "Prelude" "Either" `appT`
+     qualType "Exception" "SomeException" `appT`
+     tvar "a") $
+    HS.TyTuple () Boxed
+      [ qualType "Builder" "Builder"
+      , qualType "Prelude" "Maybe" `appT`
+          HS.TyTuple() Boxed
+            [ qualType "Exception" "SomeException"
+            , qualType "Thrift" "Blame"
+            ]
+      ]
+  ] ++
+  map genFunction theseFunctions ++
+  genSuper serviceSuper (null theseFunctions)
+  where
+    theseFunctions = getServiceFunctions s
+    genSuper Nothing True =
+      [ HS.FunBind ()
+        [ HS.Match () (textToName "respWriter'")
+          [ HS.PWildCard () ]
+          (HS.UnGuardedRhs () (qvar "Prelude" "errorWithoutStackTrace" `app` HS.Paren ()
+            (stringLit "unknown function")))
+          Nothing
+        ]
+      ]
+    genSuper Nothing False = []
+    genSuper (Just Super{..}) _ =
+      let n = localName $ resolvedName $ fst supResolvedName
+      in
+        [ HS.FunBind ()
+          [ HS.Match () (textToName "respWriter'")
+            [ pvar "_proxy"
+            , pvar "_seqNum"
+            , HS.PParen () $ HS.PApp ()
+              (HS.UnQual () $ textToName $ "Super" <> n) [pvar "_x"]
+            , pvar "_r" ]
+            (HS.UnGuardedRhs () $
+             qvar n "respWriter'" `app`
+             var "_proxy" `app`
+             var "_seqNum" `app`
+             var "_x" `app`
+             var "_r"
+            )
+            Nothing
+          ]]
+
+    genFunction :: HS Function -> Decl ()
+    genFunction Function{..} = HS.FunBind ()
+      [ HS.Match () (textToName "respWriter'")
+        [ pvar "_proxy"
+        , pvar "_seqNum"
+        , HS.PRec () (unqualSym $ toCamel funName) []
+        , pvar "_r" ]
+        (HS.UnGuardedRhs () $
+          Tuple () Boxed
+         [ infixApp "<>"
+            (infixApp "<>"
+              (protocolFun "genMsgBegin" `app`
+              stringLit funName `app`
+              var "_msgType" `app`
+              var "_seqNum")
+              (var "_msgBody"))
+            (protocolFun "genMsgEnd")
+          , var "_msgException" ])
+        (Just $ BDecls ()
+         [ PatBind () (PTuple () Boxed
+            [ pvar "_msgType"
+            , pvar "_msgBody"
+            , pvar "_msgException" ])
+           (UnGuardedRhs () $ Case () (var "_r")
+            [ Alt () (PApp () (qualSym "Prelude" "Left") [ pvar "_ex" ])
+              (GuardedRhss () $
+               [ GuardedRhs ()
+                 [ Generator ()
+                   (PApp () (qualSym "Prelude" "Just")
+                    [ PAsPat () (textToName "_e") $
+                      PRec () (qualSym "Thrift" "ApplicationException") []
+                    ]) $
+                   qvar "Exception" "fromException" `app` var "_ex"
+                 ] $
+                 genRespTup genEXCEPTION
+                  (protocolFun "buildStruct" `app` var "_e")
+                  (Just (var "_ex", "ServerError"))
+               ] ++
+               map genExceptionCase funExceptions ++
+               [ GuardedRhs () [ Qualifier () $ qvar "Prelude" "otherwise" ] $
+                 Let ()
+                  (BDecls ()
+                    [ PatBind ()
+                        (pvar "_e")
+                        (UnGuardedRhs () $
+                          qcon "Thrift" "ApplicationException" `app`
+                          (qvar "Text" "pack" `app`
+                            (qvar "Prelude" "show" `app` var "_ex")) `app`
+                          qcon "Thrift"
+                            "ApplicationExceptionType_InternalError")
+                        Nothing ]) $
+                  genRespTup genEXCEPTION
+                    (protocolFun "buildStruct" `app` var "_e")
+                    (Just
+                      ( qvar "Exception" "toException" `app` var "_e"
+                      , "ServerError" ))
+               ])
+              Nothing
+            , Alt () (PApp () (qualSym "Prelude" "Right") [ pvar "_result" ])
+              (UnGuardedRhs () $ genRespTup genREPLY
+                (protocolFun "genStruct" `app`
+                  HS.List ()
+                    (genResp $ qualifyResolvedType "Types" funResolvedType))
+                Nothing)
+              Nothing
+            ])
+           Nothing
+         ])
+      ]
+      where
+        genExceptionCase :: HS (Field 'ThrowsField) -> GuardedRhs ()
+        genExceptionCase Field{..} =
+          case fieldTag of
+            THROWS_RESOLVED -> GuardedRhs ()
+              [ Generator ()
+                (PApp () (qualSym "Prelude" "Just")
+                 [ PAsPat () (textToName "_e") $
+                   PRec () (genConstructor (Just "Types") fieldResolvedType) []
+                 ])
+                 (qvar "Exception" "fromException" `app` var "_ex")
+              ] $
+              genRespTup genREPLY
+                (protocolFun "genStruct" `app`
+                  HS.List ()
+                  [ genFieldBase fieldResolvedType fieldName fieldId
+                     (intLit (0 :: Int))
+                   (  var "_e")
+                  ])
+                (Just (var "_ex", "ClientError"))
+
+        genRespTup int body exc = Tuple () Boxed
+          [ intLit int
+          , body
+          , case exc of
+              Just (e,blame) -> qcon "Prelude" "Just" `app`
+                Tuple () Boxed [ e, qcon "Thrift" blame ]
+              Nothing -> qcon "Prelude" "Nothing"
+          ]
+
+        genResp Nothing = []
+        genResp (Just (Some t)) =
+          [ genFieldBase t "" 0 (intLit (0 :: Int)) (var "_result") ]
+
+genMethodsInfo :: HS Service -> [HS.Decl ()]
+genMethodsInfo service =
+  [ signature
+  , HS.FunBind ()
+    [ HS.Match () (textToName methodsInfo') []
+        (HS.UnGuardedRhs () infos) Nothing
+    ]
+  ]
+  where
+    signature = HS.TypeSig () [textToName methodsInfo'] $
+      qualType "Map" "Map"
+        `appT` qualType "Text" "Text"
+        `appT` HS.TyCon () (qualSym "Thrift" "MethodInfo")
+
+    methodsInfo' = "methodsInfo'"
+
+    superMethodsInfo :: Maybe (HS.Exp ())
+    superMethodsInfo = do
+      (Name{..}, _) <- supResolvedName <$> serviceSuper service
+      return $ qvar (localName resolvedName) methodsInfo'
+
+    instanceMethodsInfo = qvar "Map" "fromList" `app`
+      listE (genInfoTuple <$> getServiceFunctions service)
+
+    infos = case superMethodsInfo of
+      Nothing -> instanceMethodsInfo
+      Just s -> qvar "Map" "union" `app` instanceMethodsInfo `app` s
+
+    genInfoTuple f@Function{..} =
+      Tuple () Boxed
+        [ stringLit funName
+        , genOneMethodInfo f
+        ]
+
+    genOneMethodInfo :: HS Function -> HS.Exp ()
+    genOneMethodInfo Function{..} =
+      qcon "Thrift" "MethodInfo"
+        `app` qcon "Thrift" (Text.pack $ show funPriority)
+        `app` qcon "Prelude" (Text.pack $ show funIsOneWay)
+
+commandTypeName :: HS Service -> Text
+commandTypeName Service{..} = serviceResolvedName <> "Command"
+
+isEmptyService :: HS Service -> Bool
+isEmptyService s@Service{..} = null (getServiceFunctions s) && isNothing serviceSuper
diff --git a/Thrift/Compiler/GenStruct.hs b/Thrift/Compiler/GenStruct.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenStruct.hs
@@ -0,0 +1,935 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenStruct
+  ( genStructDecl
+  , genStructImports
+  -- * Helpers
+  , fixToJSONValue
+  , ParseMode(..)
+  , genFieldParser
+  , genBuildValue, genBuildFields, genFieldBase, genParseType
+  , getUn
+  , transformValue, mkHashable, mkOrd
+  ) where
+
+import Prelude hiding (exp)
+import Data.Maybe
+import Data.Set (union)
+import Data.Text (Text)
+import Language.Haskell.Exts.Syntax hiding
+  (Name, Type, Annotation, Decl)
+import Language.Haskell.Exts.Pretty (prettyPrint)
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types
+
+-- Generate Datatype -----------------------------------------------------------
+
+genStructImports :: HS Struct -> Set.Set Import
+genStructImports Struct{..} =
+  foldr (Set.union . getImports) baseImports structMembers
+  where
+    getImports :: HS (Field u) -> Set.Set Import
+    getImports Field{..} = typeToImport fieldResolvedType
+    baseImports = Set.fromList
+                  [ QImport "Prelude" "Prelude"
+                  , QImport "Control.DeepSeq" "DeepSeq"
+                  , QImport "Control.Monad" "Monad"
+                  , QImport "Control.Monad.ST.Trans" "ST"
+                  , QImport "Control.Monad.Trans.Class" "Trans"
+                  , QImport "Data.Aeson" "Aeson"
+                  , QImport "Data.Aeson.Types" "Aeson"
+                  , QImport "Data.Default" "Default"
+                  , QImport "Data.HashMap.Strict" "HashMap"
+                  , QImport "Data.Hashable" "Hashable"
+                  , QImport "Data.List" "List"
+                  , QImport "Data.Ord" "Ord"
+                  , QImport "Thrift.Binary.Parser" "Parser"
+                  , SymImport "Prelude"
+                    [ ".", "<$>", "<*>", ">>=", "==", "/=", "<", "++" ]
+                  , SymImport "Control.Applicative" [ "<|>", "*>", "<*" ]
+                  , SymImport "Data.Aeson" [ ".:", ".:?", ".=", ".!=" ]
+                  , SymImport "Data.Monoid" [ "<>" ]
+                  ] `union`
+                  (case structType of
+                     StructTy -> Set.empty
+                     ExceptionTy ->
+                       Set.singleton $
+                       QImport "Control.Exception" "Exception")
+
+genStructDecl :: Bool -> HS Struct -> [HS.Decl ()]
+genStructDecl extraHasFields struct@Struct{..} =
+  -- Struct Declaration
+  [ DataDecl () (dataOrNew ()) Nothing
+    (DHead () $ textToName structResolvedName)
+    -- Record Constructor
+    [QualConDecl () Nothing Nothing
+      (RecDecl () (textToName structResolvedName) (map genFieldDecl structMembers))
+    ]
+    -- Deriving
+    (pure $ deriving_ $ map (IRule () Nothing Nothing . IHCon ()) $
+           [ qualSym "Prelude" "Eq"
+           , qualSym "Prelude" "Show"
+           ] ++
+           [ qualSym "Prelude" "Ord" | deriveOrd ])
+  -- Aeson Instances
+  , genToJSONInst struct
+  -- ThriftStruct Instance
+  , genThriftStruct struct
+  -- Other Instances
+  , genNFData struct
+  , genDefault struct
+  , genHashable struct
+  ] ++
+  [ genOrd struct | not deriveOrd ] ++
+  (case structType of
+    StructTy -> []
+    ExceptionTy -> [ genException struct ]) ++
+  (if extraHasFields
+    then genExtraHasFields struct
+    else []
+  )
+ where
+   dataOrNew = case structMembers of
+     -- Make the struct a newtype iff it has exactly one element
+     [_] -> NewType
+     _ -> DataType
+   deriveOrd = canDeriveOrd struct
+
+genFieldType :: HS (Field u) -> HS.Type ()
+genFieldType Field{..} = opTy
+  where
+    baseTy = genType fieldResolvedType
+    opTy =
+      case fieldRequiredness of
+        Optional{} -> TyApp () (qualType "Prelude" "Maybe") baseTy
+        _          -> baseTy
+
+genFieldDecl :: HS (Field u) -> FieldDecl ()
+genFieldDecl field@Field{..} = FieldDecl () [textToName fieldResolvedName] ty
+  where
+    baseTy = genFieldType field
+    ty =
+      case fieldLaziness of
+        Lazy -> baseTy
+        Strict | isBaseType fieldResolvedType ->
+                   TyBang () (BangedTy ()) (Unpack ()) baseTy
+               | otherwise            ->
+                   TyBang () (BangedTy ()) (NoUnpack ()) baseTy
+
+-- Generate Aeson Instances ----------------------------------------------------
+
+genToJSONInst :: HS Struct -> HS.Decl ()
+genToJSONInst struct@Struct{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Aeson" "ToJSON")
+       (TyCon () $ unqualSym structResolvedName))
+    (Just $ map (InsDecl ())
+     [ genToJSON "toJSON" ":" (qvar "Aeson" "object") struct
+     ])
+
+genToJSON :: Text -> Text -> Exp () -> HS Struct -> HS.Decl ()
+genToJSON name op combine Struct{..} =
+  FunBind ()
+  [ Match ()
+    (textToName name)
+    [ PApp () (unqualSym structResolvedName) $
+      map (\Field{..} -> pvar ("__field__" <> fieldName)) structMembers
+    ]
+    (UnGuardedRhs () $
+     combine `app`
+     foldr (genToJSONField op) (qvar "Prelude" "mempty") structMembers)
+    Nothing
+  ]
+
+genToJSONField :: Text -> HS (Field u) -> Exp () -> Exp ()
+genToJSONField op Field{..} exps =
+  case fieldRequiredness of
+    Optional{} ->
+      qvar "Prelude" "maybe" `app`
+      qvar "Prelude" "id" `app`
+      (Var () (UnQual () (Symbol () (Text.unpack op))) `compose`
+       LeftSection () (stringLit fieldName)
+       (QVarOp () (UnQual () (Symbol () ".=")))) `app`
+      fieldValue `app`
+      exps
+    _ ->
+      infixApp op
+        (infixApp ".=" (stringLit fieldName) fieldValue)
+        exps
+  where
+    fieldValue =
+      case (fieldRequiredness, fixToJSONValue fieldResolvedType) of
+        (_, Nothing) -> val
+        (Optional{}, Just f) -> qvar "Prelude" "fmap" `app` f `app` val
+        (_         , Just f) -> f `app` val
+
+    val = var $ "__field__" <> fieldName
+
+fixToJSONValue :: HSType t -> Maybe (Exp ())
+fixToJSONValue I8 = Nothing
+fixToJSONValue I16 = Nothing
+fixToJSONValue I32 = Nothing
+fixToJSONValue I64 = Nothing
+fixToJSONValue (TSpecial HsInt) = Nothing
+fixToJSONValue TFloat = Nothing
+fixToJSONValue TDouble = Nothing
+fixToJSONValue TBool = Nothing
+fixToJSONValue (TSpecial HsString) = Nothing
+fixToJSONValue (TSpecial HsByteString) = Just $ qvar "Text" "decodeUtf8"
+fixToJSONValue TText = Nothing
+fixToJSONValue TBytes = Just $ qvar "Thrift" "encodeBase64Text"
+fixToJSONValue (TList u)    = app (qvar "Prelude" "map") <$> fixToJSONValue u
+fixToJSONValue (TSpecial (HsVector vec u)) =
+  app (qvar (hsVectorQual vec) "map") <$> fixToJSONValue u
+fixToJSONValue (TSet u)     = app (qvar "Set" "map") <$> fixToJSONValue u
+fixToJSONValue (THashSet u) = app (qvar "HashSet" "map") <$> fixToJSONValue u
+fixToJSONValue (TMap k v) =
+  fixToJSONMap (qvar "Map" "mapKeys") (qvar "Map" "map") k v
+fixToJSONValue (THashMap k v) =
+  fixToJSONMap (qvar "Thrift" "hmMapKeys") (qvar "HashMap" "map") k v
+fixToJSONValue TEnum{} = Nothing
+fixToJSONValue TStruct{} = Nothing
+fixToJSONValue TException{} = Nothing
+fixToJSONValue TUnion{} = Nothing
+fixToJSONValue (TTypedef _ ty _loc) = fixToJSONValue ty
+fixToJSONValue (TNewtype name ty _loc) = Just $
+  maybe id compose (fixToJSONValue ty) $ getUn name
+
+fixToJSONMap
+  :: Exp () -> Exp () -> HSType k -> HSType v -> Maybe (Exp ())
+fixToJSONMap mapK mapV k v
+  | t:ts <- catMaybes [ keyToStr, fixK, fixV ] =
+      Just $ foldl compose t ts
+  | otherwise = Nothing
+  where
+    keyToStr
+      | isAesonKey k = Nothing
+      | otherwise = Just $ mapK `app` qvar "Thrift" "keyToStr"
+    fixK = app mapK <$> fixToJSONValue k
+    fixV = app mapV <$> fixToJSONValue v
+
+getUn :: Name -> Exp ()
+getUn Name{..} = case resolvedName of
+  UName name -> var $ "un" <> name
+  QName m name -> qvar m $ "un" <> name
+
+isAesonKey :: HSType t -> Bool
+isAesonKey TText = True
+isAesonKey (TSpecial HsString) = True
+-- ByteString isn't actually an Aeson key, but it will be transformed to Text by
+-- fixToJSONValue, so we don't want to encode it twice
+isAesonKey TBytes = True
+isAesonKey (TSpecial HsByteString) = True
+isAesonKey _ = False
+
+-- Generate ThriftStruct Instance ----------------------------------------------
+
+genThriftStruct :: HS Struct -> HS.Decl ()
+genThriftStruct struct@Struct{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Thrift" "ThriftStruct")
+       (TyCon () $ unqualSym structResolvedName))
+    (Just $ map (InsDecl ())
+     [ genBuilder struct
+     , genParser struct
+     ])
+
+data ParseMode = P_FieldMode | P_ListMode
+
+insertParens :: ParseMode -> Exp () -> Exp ()
+insertParens P_FieldMode = id
+insertParens P_ListMode = Paren ()
+
+genBuilder :: HS Struct -> HS.Decl ()
+genBuilder Struct{..} =
+  FunBind ()
+  [ Match ()
+    (textToName "buildStruct")
+    [ PVar () $ textToName "_proxy"
+    , PApp () (unqualSym structResolvedName) $
+      map (PVar () . textToName . ("__field__" <>) . fieldName) structMembers
+    ]
+    (UnGuardedRhs () $ genBuildFields structMembers)
+    Nothing
+  ]
+
+genBuildFields :: [HS (Field u)] -> Exp ()
+genBuildFields fields =
+  protocolFun "genStruct" `app`
+  (case genBuildField NoField fields of
+     NoField -> id
+     ReqField _ f -> f
+     OptField _ f -> f)
+  (HS.List () [])
+
+data PreviousField
+   = NoField
+   -- Both ReqField and OptField contain continuations for building the output
+   -- of the function
+   | ReqField FieldId (Exp () -> Exp ())
+   | OptField Text (Exp () -> Exp ())
+
+genBuildField :: PreviousField -> [HS (Field u)] -> PreviousField
+genBuildField prev [] = prev
+genBuildField prev (Field{..} : fs) = flip genBuildField fs $
+  case fieldRequiredness of
+    Optional{} | null fs ->
+      ReqField fieldId $ \e -> combine $
+        Case () (var ("__field__" <> fieldName))
+        [ Alt () (PApp () (qualSym "Prelude" "Just") [ pvar "_val" ])
+          (UnGuardedRhs () $
+           infixApp ":"
+            (genField $ var "_val")
+            e)
+          Nothing
+        , Alt () (PApp () (qualSym "Prelude" "Nothing") [])
+          (UnGuardedRhs () e)
+          Nothing
+        ]
+    Optional{} ->
+      OptField fieldName $ \e -> combine $
+        Let ()
+          (BDecls ()
+           [ PatBind () (PTuple () Boxed
+                         [ pvar ("__cereal__" <> fieldName)
+                         , pvar ("__id__" <> fieldName)
+                         ])
+             (UnGuardedRhs () $
+              Case () (var ("__field__" <> fieldName))
+              [ Alt () (PApp () (qualSym "Prelude" "Just") [ pvar "_val" ])
+                (UnGuardedRhs () $
+                 Tuple () Boxed
+                 [ Con () (UnQual () (Symbol () ":")) `app`
+                   genField (var "_val")
+                 , intLit fieldId
+                 ])
+                Nothing
+              , Alt () (PApp () (qualSym "Prelude" "Nothing") [])
+                (UnGuardedRhs () $
+                 Tuple () Boxed
+                 [ qvar "Prelude" "id"
+                 , lastId
+                 ])
+                Nothing
+              ])
+             Nothing
+           ]) $
+            (var $ "__cereal__" <> fieldName) `app` e
+    _ -> ReqField fieldId $
+         combine .
+         infixApp ":"
+         (genField $ var $ "__field__" <> fieldName)
+  where
+    genField = genFieldBase fieldResolvedType fieldName fieldId lastId
+    (lastId, combine) =
+      case prev of
+        NoField -> (intLit (0 :: FieldId), id)
+        ReqField fid f -> (intLit fid, f)
+        OptField name f -> (var $ "__id__" <> name, f)
+
+genFieldBase :: HSType t -> Text -> FieldId -> Exp () -> Exp () -> Exp ()
+genFieldBase ty name fid lastId arg =
+  case getPrim ty of
+   Nothing ->
+     protocolFun "genField" `app`
+     stringLit name `app`
+     genThriftType ty `app`
+     intLit fid `app`
+     lastId `app`
+     (genBuildValue ty `app` arg)
+   Just P_Bool ->
+     protocolFun "genFieldBool" `app`
+     stringLit name `app`
+     intLit fid `app`
+     lastId `app`
+     arg
+   Just primTy ->
+     protocolFun "genFieldPrim" `app`
+     stringLit name `app`
+     genThriftType ty `app`
+     intLit fid `app`
+     lastId `app`
+     genBuildPrim primTy `app`
+     arg
+
+genBuildValue :: HSType t -> Exp ()
+-- Primatives
+genBuildValue I8  = protocolFun "genByte"
+genBuildValue I16 = protocolFun "genI16"
+genBuildValue I32 = protocolFun "genI32"
+genBuildValue I64 = protocolFun "genI64"
+genBuildValue (TSpecial HsInt) =
+  protocolFun "genI64" `compose`
+  qvar "Prelude" "fromIntegral"
+genBuildValue TFloat  = protocolFun "genFloat"
+genBuildValue TDouble = protocolFun "genDouble"
+genBuildValue TBool = protocolFun "genBool"
+genBuildValue TText = protocolFun "genText"
+genBuildValue (TSpecial HsString) =
+  genBuildValue TText `compose` qvar "Text" "pack"
+genBuildValue (TSpecial HsByteString) = protocolFun "genByteString"
+genBuildValue TBytes = protocolFun "genBytes"
+-- Containers
+genBuildValue (TList ty) = genBuildList ty
+genBuildValue (TSpecial (HsVector vec ty)) =
+  genBuildList ty `compose` qvar (hsVectorQual vec) "toList"
+genBuildValue (TSet ty) =
+  genBuildList ty `compose` qvar "Set" "toList"
+genBuildValue (THashSet ty) =
+  genBuildList ty `compose` qvar "HashSet" "toList"
+genBuildValue (TMap k v) =
+  genBuildMap k v `compose` qvar "Map" "toList"
+genBuildValue (THashMap k v) =
+  genBuildMap k v `compose` qvar "HashMap" "toList"
+-- Named Types
+genBuildValue (TTypedef _ ty _loc) = genBuildValue ty
+genBuildValue (TNewtype name ty _loc) =
+  genBuildValue ty `compose` getUn name
+genBuildValue (TStruct _ _loc) = protocolFun "buildStruct"
+genBuildValue (TException _ _loc) = protocolFun "buildStruct"
+genBuildValue (TUnion _ _loc) = protocolFun "buildStruct"
+genBuildValue (TEnum _ _loc _) =
+  protocolFun "genI32" `compose`
+  qvar "Prelude" "fromIntegral" `compose`
+  qvar "Thrift" "fromThriftEnum"
+
+genBuildPrim :: PrimType -> Exp ()
+genBuildPrim P_I8 = protocolFun "genBytePrim"
+genBuildPrim P_I16 = protocolFun "genI16Prim"
+genBuildPrim P_I32 = protocolFun "genI32Prim"
+genBuildPrim P_I64 = protocolFun "genI64Prim"
+genBuildPrim P_Bool = protocolFun "genBoolPrim"
+
+genBuildList :: HSType t -> Exp ()
+genBuildList ty =
+  case getPrim ty of
+    Just primTy ->
+      protocolFun "genListPrim" `app`
+      genThriftType ty `app`
+      genBuildPrim primTy
+    Nothing ->
+      protocolFun "genList" `app`
+      genThriftType ty `app`
+      genBuildValue ty
+
+genBuildMap :: HSType k -> HSType v -> Exp ()
+genBuildMap k v =
+  case (getPrim k, getPrim v) of
+    (Just primK, Just primV) ->
+      protocolFun "genMapPrim" `app`
+      genThriftType k `app`
+      genThriftType v `app`
+      qcon "Prelude" (if isStringType k then "True" else "False") `app`
+      genBuildPrim primK `app`
+      genBuildPrim primV
+    _ ->
+      protocolFun "genMap" `app`
+      genThriftType k `app`
+      genThriftType v `app`
+      qcon "Prelude" (if isStringType k then "True" else "False") `app`
+      genBuildValue k `app`
+      genBuildValue v
+
+isStringType :: HSType t -> Bool
+isStringType (TSpecial HsString) = True
+isStringType (TSpecial HsByteString) = True
+isStringType TText = True
+isStringType TBytes = True
+isStringType (TTypedef _ t _loc) = isStringType t
+isStringType (TNewtype _ t _loc) = isStringType t
+isStringType _ = False
+
+genFieldParser
+  :: [HS (Field u)] -> Text -> (Exp () -> Exp ()) -> Rhs ()
+genFieldParser fields constructorName constructorWrapper = UnGuardedRhs () $
+  qvar "ST" "runSTT" `app`
+  Do ()
+  -- We need this because of some issue in runST (t10447741)
+  ( Qualifier () (qvar "Prelude" "return" `app` unit_con ()) :
+  -- field <- newSTRef Nothing
+  map
+   (\field@Field{..} ->
+    Generator () (pvar ("__field__" <> fieldName))
+    (qvar "ST" "newSTRef" `app`
+     case fieldRequiredness of
+       Default -> genFieldDefault field
+       _ -> qcon "Prelude" "Nothing"))
+   fields ++
+   -- let __parse = do {..}
+   [ LetStmt () $
+     BDecls ()
+     [ FunBind ()
+       -- the __parse function recursively builds the output and stores the
+       -- parsed values in STRefs that are initialized in the outer scope
+       [ Match () (textToName "_parse") [ pvar "_lastId" ]
+         (UnGuardedRhs () $ Do ()
+          -- Field Case: pattern match on parsed field id
+          [ Generator () (pvar "_fieldBegin") $
+            qvar "Trans" "lift" `app`
+            (protocolFun "parseFieldBegin" `app`
+             var "_lastId" `app`
+             var "_idMap")
+          , Qualifier () $ Case () (var "_fieldBegin")
+            [ Alt ()
+              (PApp () (qualSym "Thrift" "FieldBegin")
+               [ pvar "_type", pvar "_id", pvar "_bool" ])
+              (UnGuardedRhs () $ Do ()
+               [ Qualifier () $ Case () (var "_id") $
+                 map genParseValue fields ++
+                 [ Alt () (PWildCard ())
+                   (UnGuardedRhs () $
+                    qvar "Trans" "lift" `app`
+                    (protocolFun "parseSkip" `app`
+                     var "_type" `app`
+                     (qcon "Prelude" "Just" `app` var "_bool")))
+                   Nothing
+                 ]
+               , Qualifier () $ var "_parse" `app` var "_id"
+               ])
+              Nothing
+            , Alt () (PApp () (qualSym "Thrift" "FieldEnd") [])
+              (UnGuardedRhs () $ Do () $
+               -- Get the values from the STRefs
+               map (\Field{..} ->
+                    Generator ()
+                    (PBangPat () $ case fieldRequiredness of
+                       Required{} -> pvar $ "__maybe__" <> fieldName
+                       _ -> pvar $ "__val__" <> fieldName) $
+                    qvar "ST" "readSTRef" `app` var ("__field__" <> fieldName))
+               fields ++
+               [ Qualifier () $
+                 foldr matchArg buildOutput fields
+               ])
+              Nothing
+            ]
+          ])
+         Nothing
+       ]
+     , PatBind () (pvar "_idMap")
+       (UnGuardedRhs () $
+        qvar "HashMap" "fromList" `app`
+        HS.List ()
+        (map (\Field{..} ->
+         Tuple () Boxed [ stringLit fieldName, intLit fieldId ])
+        fields))
+       Nothing
+       ]
+   -- call _parse
+   , Qualifier () $ var "_parse" `app` intLit (0 :: Int)
+   ])
+  where
+    buildOutput =
+      qvar "Prelude" "pure" `app` constructorWrapper
+      (foldl app (con constructorName) (map mkFieldName fields))
+    mkFieldName Field{..} = var $ "__val__" <> fieldName
+    matchArg :: HS (Field u) -> Exp () -> Exp ()
+    matchArg Field{..} exp =
+      case fieldRequiredness of
+        Required{} ->
+          Case () (var $ "__maybe__" <> fieldName)
+          [ Alt () (PApp () (qualSym "Prelude" "Nothing") [])
+            (UnGuardedRhs () $
+             qvar "Prelude" "fail" `app`
+             stringLit
+               ("Error parsing type "
+               <> constructorName
+               <> ": missing required field " <> fieldName
+               <> " of type " <> Text.pack (
+                 prettyPrint $ genType fieldResolvedType)
+               ))
+            Nothing
+          , Alt () (PApp () (qualSym "Prelude" "Just")
+                    [ pvar ("__val__" <> fieldName) ])
+            (UnGuardedRhs () exp)
+            Nothing
+          ]
+        _ -> exp
+
+genParser :: HS Struct -> HS.Decl ()
+genParser Struct{..} =
+  FunBind ()
+  [ Match ()
+    (textToName "parseStruct")
+    [ pvar "_proxy" ]
+    (genFieldParser structMembers structResolvedName (Paren ()))
+    Nothing
+  ]
+
+genParseValue :: HS (Field u) -> Alt ()
+genParseValue Field{..} =
+  Alt ()
+  (PLit ()
+   (if fieldId < 0 then Negative () else Signless ())
+   (Int () (abs $ fromIntegral fieldId) (show fieldId)))
+  (GuardedRhss ()
+   -- check that the parsed type is correct
+   [ GuardedRhs ()
+     [ Qualifier () $
+       infixApp "==" (var "_type") (genThriftType fieldResolvedType)
+     ] $
+     Do ()
+     [ Generator () (PBangPat () $ pvar "_val") $
+       qvar "Trans" "lift" `app` genParseType P_FieldMode fieldResolvedType
+     , Qualifier () $
+       qvar "ST" "writeSTRef" `app`
+       var ("__field__" <> fieldName) `app`
+       case fieldRequiredness of
+         Default -> var "_val"
+         _ -> qcon "Prelude" "Just" `app` var "_val"
+     ]
+   ])
+  Nothing
+
+genParseType :: ParseMode -> HSType t -> Exp ()
+-- Base types
+genParseType _ I8  = protocolFun "parseByte"
+genParseType _ I16 = protocolFun "parseI16"
+genParseType _ I32 = protocolFun "parseI32"
+genParseType _ I64 = protocolFun "parseI64"
+genParseType m (TSpecial HsInt) = insertParens m $
+  infixApp "<$>" (qvar "Prelude" "fromIntegral") (protocolFun "parseI64")
+genParseType _ TFloat  = protocolFun "parseFloat"
+genParseType _ TDouble = protocolFun "parseDouble"
+genParseType P_FieldMode TBool = protocolFun "parseBoolF" `app` var "_bool"
+genParseType P_ListMode  TBool = protocolFun "parseBool"
+genParseType _ TText = protocolFun "parseText"
+genParseType m (TSpecial HsString) = insertParens m $
+  infixApp "<$>" (qvar "Text" "unpack") (protocolFun "parseText")
+genParseType _ (TSpecial HsByteString) = protocolFun "parseByteString"
+genParseType _ TBytes = protocolFun "parseBytes"
+-- Containers
+genParseType _ (TList ty) =
+  infixApp "<$>" (qvar "Prelude" "snd") (genParseList ty)
+genParseType m (TSpecial (HsVector vec ty)) = insertParens m $
+  infixApp "<$>"
+    (qvar "Prelude" "uncurry" `app` qvar (hsVectorQual vec) "fromListN")
+    (genParseList ty)
+genParseType m (TSet ty) = insertParens m $
+  infixApp "<$>"
+    (qvar "Set" "fromList" `compose` qvar "Prelude" "snd")
+    (genParseList ty)
+genParseType m (THashSet ty) = insertParens m $
+  infixApp "<$>"
+    (qvar "HashSet" "fromList" `compose` qvar "Prelude" "snd")
+    (genParseList ty)
+genParseType m (TMap k v) = insertParens m $
+  infixApp "<$>" (qvar "Map" "fromList") (genParseMap k v)
+genParseType m (THashMap k v) = insertParens m $
+  infixApp "<$>" (qvar "HashMap" "fromList") (genParseMap k v)
+-- Named Types
+genParseType m (TTypedef _ ty _loc) = genParseType m ty
+genParseType m (TNewtype name ty _loc) =
+  qvar "Prelude" "fmap" `app` Con () (nameToQName name) `app` genParseType m ty
+genParseType _ TStruct{} = protocolFun "parseStruct"
+genParseType _ TException{} = protocolFun "parseStruct"
+genParseType _ TUnion{} = protocolFun "parseStruct"
+genParseType _ (TEnum Name{..} _loc nounknown) =
+  qvar "Thrift" (parseEnumFun nounknown) `app`
+  var "_proxy" `app`
+  stringLit (localName resolvedName)
+  where
+    parseEnumFun :: Bool -> Text
+    parseEnumFun True = "parseEnumNoUnknown"
+    parseEnumFun False = "parseEnum"
+
+genParseList :: HSType t -> Exp ()
+genParseList ty = protocolFun "parseList" `app` genParseType P_ListMode ty
+
+genParseMap :: HSType k -> HSType v -> Exp ()
+genParseMap k v =
+  protocolFun "parseMap" `app`
+  genParseType P_ListMode k `app`
+  genParseType P_ListMode v `app`
+  qcon "Prelude" (if isStringType k then "True" else "False")
+
+-- Generate NFData Instance ----------------------------------------------------
+
+genNFData :: HS Struct -> HS.Decl ()
+genNFData Struct{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "DeepSeq" "NFData")
+       (TyCon () $ unqualSym structResolvedName))
+    (Just $ map (InsDecl ())
+     [ FunBind ()
+       [ Match () (textToName "rnf")
+         [ PApp () (unqualSym structResolvedName) $ map mkPattern structMembers ]
+         (UnGuardedRhs () $
+          foldr seqify (Con () (Special () (UnitCon ()))) structMembers)
+         Nothing
+       ]
+     ])
+    where
+      seqify field = InfixApp () (forcedField field) infixSeq
+      infixSeq = QVarOp () $ qualSym "Prelude" "seq"
+      forcedField Field{..} =
+        qvar "DeepSeq" "rnf" `app` var ("__field__" <> fieldName)
+
+mkPattern :: HS (Field u) -> Pat ()
+mkPattern Field{..} = pvar $ "__field__" <> fieldName
+
+-- Generate Default Instance ---------------------------------------------------
+
+genDefault :: HS Struct -> HS.Decl ()
+genDefault Struct{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Default" "Default")
+       (TyCon () $ unqualSym structResolvedName))
+    (Just $ map (InsDecl ())
+     [ FunBind ()
+       [ Match () (textToName "def") []
+         (UnGuardedRhs () $
+          foldl app (con structResolvedName) $ map genFieldDefault structMembers)
+         Nothing
+       ]
+     ])
+
+genFieldDefault :: HS (Field u) -> Exp ()
+genFieldDefault Field{..} =
+  case fieldRequiredness of
+    Optional{} -> qcon "Prelude" "Nothing"
+    _ -> case fieldResolvedVal of
+           Just val -> genConst fieldResolvedType val
+           Nothing  -> typeToDefault fieldResolvedType
+
+-- Generate Hashable Instance --------------------------------------------------
+
+genHashable :: HS Struct -> HS.Decl ()
+genHashable Struct{..} =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp () (IHCon () (qualSym "Hashable" "Hashable")) $
+   simpleType structResolvedName)
+  (Just
+   [ InsDecl () $ FunBind ()
+     [ Match () (textToName "hashWithSalt")
+       [ pvar "__salt"
+       , PApp () (unqualSym structResolvedName) $
+         map (\Field{..} -> pvar $ "_" <> fieldName) structMembers
+       ]
+       (UnGuardedRhs () $ foldl
+        (\salt Field{..} ->
+          qvar "Hashable" "hashWithSalt" `app`
+          salt `app`
+          transformValue mkHashable fieldRequiredness fieldResolvedType
+          (var $ "_" <> fieldName))
+        (var "__salt")
+        structMembers)
+       Nothing
+     ]
+   ])
+
+-- Some thrift types aren't hashable, so we need to modify them before passing
+-- them to hashWithSalt
+mkHashable :: HSType t -> Maybe (Exp ())
+mkHashable = \case
+  I8 -> Nothing
+  I16 -> Nothing
+  I32 -> Nothing
+  I64 -> Nothing
+  (TSpecial HsInt) -> Nothing
+  TFloat -> Nothing
+  TDouble -> Nothing
+  TText -> Nothing
+  TBool -> Nothing
+  (TSpecial HsString) -> Nothing
+  (TSpecial HsByteString) -> Nothing
+  TBytes -> Nothing
+  -- elems gives the set elements in ascending order, so we do not need to
+  -- sort the result
+  (TSet u) -> Just $ mapTransform mkHashable u $ qvar "Set" "elems"
+  (THashSet u) ->
+    Just $ qvar "List" "sort" `compose`
+    mapTransform mkHashable u (qvar "HashSet" "toList")
+  (TList u) -> (qvar "Prelude" "map" `app`) <$> mkHashable u
+  (TSpecial (HsVector vec u)) ->
+    Just $ mapTransform mkHashable u $ qvar (hsVectorQual vec) "toList"
+  (TMap k v) -> Just $ mapTransformPair mkHashable k v $ qvar "Map" "toAscList"
+  (THashMap k v) ->
+    Just $ qvar "List" "sort" `compose`
+    mapTransformPair mkHashable k v (qvar "HashMap" "toList")
+  TStruct{} -> Nothing
+  TException{} -> Nothing
+  TUnion{} -> Nothing
+  TEnum{} -> Nothing
+  (TTypedef _ u _loc) -> mkHashable u
+  TNewtype{} -> Nothing
+
+transformValue
+  :: (HSType t -> Maybe (Exp ()))
+  -> Requiredness u a
+  -> HSType t
+  -> Exp ()
+  -> Exp ()
+transformValue transform req ty exp =
+  case (req, transform ty) of
+    (_, Nothing) -> exp
+    (Optional{}, Just f) -> qvar "Prelude" "fmap" `app` f `app` exp
+    (_, Just f) -> f `app` exp
+
+mapTransform
+  :: (HSType t -> Maybe (Exp ())) -> HSType t -> Exp () -> Exp ()
+mapTransform transform u =
+  case transform u of
+    Nothing -> id
+    Just f -> compose $ qvar "Prelude" "map" `app` f
+
+mapTransformPair
+  :: (forall t. HSType t -> Maybe (Exp ()))
+  -> HSType k
+  -> HSType v
+  -> Exp ()
+  -> Exp ()
+mapTransformPair transform k v = compose $
+  qvar "Prelude" "map" `app`
+  Lambda () [ PTuple () Boxed [ pvar "_k", pvar "_v" ] ]
+  (Tuple () Boxed [ applyT transform k "_k", applyT transform v "_v" ])
+
+applyT :: (forall u. HSType u -> Maybe (Exp ())) -> HSType t -> Text -> Exp ()
+applyT transform u v =
+  case transform u of
+    Nothing -> var v
+    Just f  -> f `app` var v
+
+canDerive :: (forall t. HSType t -> Maybe a) -> HS Struct -> Bool
+canDerive f Struct{..} =
+  all (\Field{..} -> isNothing $ f fieldResolvedType) structMembers
+
+-- Generate Hashable Instance --------------------------------------------------
+
+genOrd :: HS Struct -> HS.Decl ()
+genOrd Struct{..} =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp () (IHCon () (qualSym "Ord" "Ord")) $
+   simpleType structResolvedName)
+  (Just
+   [ InsDecl () $ FunBind ()
+     [ Match () (textToName "compare")
+       [ pvar "__a"
+       , pvar "__b"
+       ]
+       (UnGuardedRhs () $ case structMembers of
+         [] -> qcon "Ord" "EQ"
+         _:_ -> foldr1
+           (\scrutinee continue ->
+             Case () scrutinee
+             [ Alt () (PApp () (qualSym "Ord" c) [])
+               (UnGuardedRhs () result)
+               Nothing
+             | (c, result) <-
+               [ ("LT", qcon "Ord" "LT")
+               , ("GT", qcon "Ord" "GT")
+               , ("EQ", continue)
+               ]
+             ])
+           [ qvar "Ord" "compare" `app`
+             f (var fieldResolvedName `app` var "__a") `app`
+             f (var fieldResolvedName `app` var "__b")
+           | Field{..} <- structMembers
+           , let f = transformValue mkOrd fieldRequiredness fieldResolvedType
+           ])
+       Nothing
+     ]
+   ])
+
+mkOrd :: HSType t -> Maybe (Exp ())
+mkOrd = \case
+  I8 -> Nothing
+  I16 -> Nothing
+  I32 -> Nothing
+  I64 -> Nothing
+  (TSpecial HsInt) -> Nothing
+  TFloat -> Nothing
+  TDouble -> Nothing
+  TText -> Nothing
+  TBool -> Nothing
+  (TSpecial HsString) -> Nothing
+  TBytes -> Nothing
+  (TSpecial HsByteString) -> Nothing
+  (TSet u) -> (qvar "Set" "map" `app`) <$> mkOrd u
+  (THashSet u) ->
+    Just $ qvar "List" "sort" `compose`
+    mapTransform mkOrd u (qvar "HashSet" "toList")
+  (TList u) -> (qvar "Prelude" "map" `app`) <$> mkOrd u
+  (TSpecial (HsVector vec u)) ->
+    (qvar (hsVectorQual vec) "map" `app`) <$> mkOrd u
+  (TMap k v) -> case (mkOrd k, mkOrd v) of
+    (Nothing, Nothing) -> Nothing
+    _ -> Just $ mapTransformPair mkOrd k v $ qvar "Map" "toAscList"
+  (THashMap k v) -> Just $ qvar "List" "sort" `compose`
+    mapTransformPair mkOrd k v (qvar "HashMap" "toList")
+  TStruct{} -> Nothing
+  TException{} -> Nothing
+  TUnion{} -> Nothing
+  TEnum{} -> Nothing
+  (TTypedef _ u _loc) -> mkOrd u
+  TNewtype{} -> Nothing
+
+canDeriveOrd :: HS Struct -> Bool
+canDeriveOrd = canDerive mkOrd
+
+-- Generate Exception Instance -------------------------------------------------
+
+genException :: HS Struct -> HS.Decl ()
+genException Struct{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Exception" "Exception")
+       (TyCon () $ unqualSym structResolvedName))
+    Nothing
+
+-- Generate Extra HasField Instances -------------------------------------------
+
+genExtraHasFields :: HS Struct -> [HS.Decl ()]
+genExtraHasFields Struct{..} = genHasField structResolvedName <$> structMembers
+
+genHasField :: Text -> HS (Field u) -> HS.Decl ()
+genHasField name field@Field{..} = InstDecl ()
+  Nothing
+  (IRule () Nothing Nothing ihead)
+  (Just [InsDecl () getFieldDecl])
+  where
+    ihead =
+      IHApp ()
+        (IHApp ()
+          (IHApp () (IHCon () $ qualSym "Thrift" "HasField") promotedName)
+          (TyCon () $ unqualSym name)
+        )
+        (TyParen () $ genFieldType field)
+
+    promotedName = promoteText fieldName
+
+    getFieldDecl = FunBind () . (:[]) $
+      Match ()
+        (textToName "getField")
+        mempty
+        (UnGuardedRhs () (var fieldResolvedName))
+        Nothing
+
+promoteText :: Text -> HS.Type ()
+promoteText s = TyPromoted ()
+  $ PromotedString () fieldNameString fieldNameString
+  where
+    -- We need the thrift_ prefix in order to prevent naming conflicts between
+    -- fields like struct.val and struct.struct_val
+    fieldNameString = Text.unpack s
diff --git a/Thrift/Compiler/GenTypedef.hs b/Thrift/Compiler/GenTypedef.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenTypedef.hs
@@ -0,0 +1,131 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenTypedef
+  ( genTypedefDecl
+  , genTypedefImports
+  ) where
+
+import Control.Monad
+import Data.Maybe
+import Data.Set (union)
+import Data.Text (Text)
+import Language.Haskell.Exts.Syntax hiding (Type)
+import qualified Data.Set as Set
+
+import Thrift.Compiler.GenStruct
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types hiding (Decl(..))
+
+genTypedefImports :: HS Typedef -> Set.Set Import
+genTypedefImports Typedef{..} =
+  typeToImport tdResolvedType `union`
+  case tdTag of
+    IsTypedef -> Set.empty
+    IsNewtype -> Set.fromList
+      [ QImport "Prelude" "Prelude"
+      , QImport "Control.DeepSeq" "DeepSeq"
+      , QImport "Data.Aeson" "Aeson"
+      , QImport "Data.Hashable" "Hashable"
+      ]
+
+genTypedefDecl :: HS Typedef -> Bool -> [Decl ()]
+genTypedefDecl Typedef{..} deriveShow = case tdTag of
+  IsTypedef ->
+    [ TypeDecl () (DHead () $ textToName tdResolvedName)
+      (genType tdResolvedType)
+    ]
+  IsNewtype ->
+    [ DataDecl () (NewType ()) Nothing (DHead () name)
+      -- Constructor Declaration
+      [ QualConDecl () Nothing Nothing
+        (RecDecl () name
+         [ FieldDecl () [ textToName ("un" <> tdResolvedName) ]
+           (genType tdResolvedType)
+         ])
+      ]
+      -- Deriving
+      (pure $ deriving_ $ map (IRule () Nothing Nothing . IHCon ()) $ catMaybes
+        [ qualSym "Prelude" "Eq"     <$ guard True
+        , qualSym "Prelude" "Show"   <$ guard deriveShow
+        , qualSym "DeepSeq" "NFData" <$ guard True
+        , qualSym "Prelude" "Ord"    <$ guard deriveOrd
+        ])
+      -- Instances
+    , genHashable tdResolvedType tdResolvedName
+    , genToJSON tdResolvedType tdResolvedName
+    ] ++
+    [ genOrd tdResolvedType tdResolvedName | not deriveOrd ]
+  where
+    name = textToName tdResolvedName
+    deriveOrd = isNothing $ mkOrd tdResolvedType
+
+-- Hashable --------------------------------------------------------------------
+
+genHashable :: HSType t -> Text -> Decl ()
+genHashable ty alias =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp () (IHCon () (qualSym "Hashable" "Hashable")) $
+   simpleType alias)
+  (Just
+   [ InsDecl () $ FunBind ()
+     [ Match () (textToName "hashWithSalt")
+       [ pvar "__salt"
+       , PApp () (unqualSym alias) [ pvar "__val" ]
+       ]
+       (UnGuardedRhs () $
+        qvar "Hashable" "hashWithSalt" `app`
+        var "__salt" `app`
+        transformValue mkHashable Default ty (var "__val"))
+       Nothing
+     ]
+   ])
+
+-- Ord -------------------------------------------------------------------------
+
+genOrd :: HSType t -> Text -> Decl ()
+genOrd ty alias =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp () (IHCon () (qualSym "Prelude" "Ord")) $
+   simpleType alias)
+  (Just
+   [ InsDecl () $ FunBind ()
+     [ Match () (textToName "compare")
+       [ PApp () (unqualSym alias) [ pvar "__x" ]
+       , PApp () (unqualSym alias) [ pvar "__y" ]
+       ]
+       (UnGuardedRhs () $
+        qvar "Prelude" "compare" `app`
+        transformValue mkOrd Default ty (var "__x") `app`
+        transformValue mkOrd Default ty (var "__y"))
+       Nothing
+     ]
+   ])
+
+-- Ord -------------------------------------------------------------------------
+
+genToJSON :: HSType t -> Text -> Decl ()
+genToJSON ty alias =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp () (IHCon () (qualSym "Aeson" "ToJSON")) $
+   simpleType alias)
+  (Just
+   [ InsDecl () $ FunBind ()
+     [ Match () (textToName "toJSON")
+       [ PApp () (unqualSym alias) [ pvar "__val" ] ]
+       (UnGuardedRhs () $ app (qvar "Aeson" "toJSON") $
+        case fixToJSONValue ty of
+          Nothing -> var "__val"
+          Just f  -> f `app` var "__val")
+       Nothing
+     ]
+   ])
diff --git a/Thrift/Compiler/GenUnion.hs b/Thrift/Compiler/GenUnion.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenUnion.hs
@@ -0,0 +1,397 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenUnion
+  ( genUnionDecl
+  , genUnionImports
+  ) where
+
+import Prelude hiding (exp)
+import Data.Maybe
+import Data.Text (Text)
+import Language.Haskell.Exts.Syntax hiding
+  (Name, Type, Annotation, Decl)
+import qualified Data.Set as Set
+import qualified Language.Haskell.Exts.Syntax as HS
+
+import Thrift.Compiler.GenStruct
+import Thrift.Compiler.GenUtils
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types
+
+-- Generate Datatype -----------------------------------------------------------
+
+genUnionImports :: HS Union -> Set.Set Import
+genUnionImports Union{..} =
+  foldr (Set.union . getImports) baseImports unionAlts
+  where
+    getImports :: HS UnionAlt -> Set.Set Import
+    getImports UnionAlt{..} = typeToImport altResolvedType
+    baseImports = Set.fromList
+                  [ QImport "Prelude" "Prelude"
+                  , QImport "Control.DeepSeq" "DeepSeq"
+                  , QImport "Control.Exception" "Exception"
+                  , QImport "Data.Aeson" "Aeson"
+                  , QImport "Data.Aeson.Types" "Aeson"
+                  , QImport "Data.Default" "Default"
+                  , QImport "Data.Hashable" "Hashable"
+                  , QImport "Data.HashMap.Strict" "HashMap"
+                  , QImport "Data.List" "List"
+                  , QImport "Data.Ord" "Ord"
+                  , SymImport "Prelude" [ ".", "<$>", "<*>", ">>=", "==", "++" ]
+                  , SymImport "Data.Aeson" [ ".:", ".=" ]
+                  , SymImport "Data.Monoid" [ "<>" ]
+                  ]
+
+genUnionDecl :: HS Union -> [HS.Decl ()]
+genUnionDecl union@Union{..} =
+  -- Union Declaration
+  [ DataDecl () (DataType ()) Nothing
+    (DHead () $ textToName unionResolvedName)
+    -- Data Constructors
+    (map genAltDecl unionAlts ++
+     case unionHasEmpty of
+       NonEmpty -> []
+       HasEmpty ->
+         [ QualConDecl () Nothing Nothing $
+           ConDecl () (textToName unionEmptyName) []
+         ])
+
+    -- Deriving
+    (pure $ deriving_ $ map (IRule () Nothing Nothing . IHCon ()) $
+           [ qualSym "Prelude" "Eq"
+           , qualSym "Prelude" "Show"
+           ] ++
+           [ qualSym "Prelude" "Ord" | deriveOrd ])
+  -- Aeson Instances
+  , genToJSONInst union
+  -- ThriftStruct Instance
+  , genThriftStruct union
+  -- Other Instances
+  , genNFData union
+  , genDefault union
+  , genHashable union
+  ] ++
+  [ genOrd union | not deriveOrd ]
+  where
+    deriveOrd =
+      all (\UnionAlt{..} -> isNothing $ mkOrd altResolvedType) unionAlts
+
+genAltDecl :: HS UnionAlt -> QualConDecl ()
+genAltDecl UnionAlt{..} =
+  QualConDecl () Nothing Nothing $
+  ConDecl () (textToName altResolvedName) [ genType altResolvedType ]
+
+-- Generate Aeson Instances ----------------------------------------------------
+
+genToJSONInst :: HS Union -> HS.Decl ()
+genToJSONInst Union{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Aeson" "ToJSON")
+       (TyCon () $ unqualSym unionResolvedName))
+    (Just [ InsDecl () $ FunBind () $
+            map genToJSONAlt unionAlts ++
+            case unionHasEmpty of
+              NonEmpty -> []
+              HasEmpty -> [ genToJSONEmpty unionEmptyName ]
+          ])
+
+genToJSONAlt :: HS UnionAlt -> Match ()
+genToJSONAlt UnionAlt{..} =
+  Match () (textToName "toJSON")
+  [ PApp () (unqualSym altResolvedName) [ pvar arg ] ]
+  (UnGuardedRhs () $
+     qvar "Aeson" "object" `app`
+     HS.List ()
+     [ infixApp ".=" (stringLit altName) $
+       case fixToJSONValue altResolvedType of
+         Nothing -> var arg
+         Just f  -> f `app` var arg
+     ])
+  Nothing
+  where
+    arg = "__" <> altName
+
+genToJSONEmpty :: Text -> Match ()
+genToJSONEmpty uname =
+  Match () (textToName "toJSON")
+  [ PApp () (unqualSym uname) [] ]
+  (UnGuardedRhs () $
+     qvar "Aeson" "object" `app` HS.List () [])
+  Nothing
+
+-- Generate ThriftStruct Instance ----------------------------------------------
+
+genThriftStruct :: HS Union -> HS.Decl ()
+genThriftStruct union@Union{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Thrift" "ThriftStruct")
+       (TyCon () $ unqualSym unionResolvedName))
+    (Just $ map (InsDecl ())
+     [ genBuilder union
+     , genParser union
+     ])
+
+genBuilder :: HS Union -> HS.Decl ()
+genBuilder Union{..} =
+  FunBind () $
+  (flip map unionAlts $ \UnionAlt{..} ->
+    let arg = "__" <> altName in
+    mkMatch (PApp () (unqualSym altResolvedName) [ pvar arg ])
+    [ genFieldBase altResolvedType altName altId lastId (var arg) ]) ++
+  case unionHasEmpty of
+    NonEmpty -> []
+    HasEmpty -> [ mkMatch (PApp () (unqualSym unionEmptyName) []) [] ]
+  where
+    lastId = intLit (0 :: Int)
+    mkMatch pat fields =
+      Match () (textToName "buildStruct")
+      [ pvar "_proxy", pat ]
+      (UnGuardedRhs () $
+       protocolFun "genStruct" `app`
+       HS.List () fields)
+      Nothing
+
+genParser :: HS Union -> HS.Decl ()
+genParser Union{..} =
+  FunBind ()
+  [ Match ()
+    (textToName "parseStruct")
+    [ pvar "_proxy" ]
+    (UnGuardedRhs () $ Do ()
+     [ Generator () (pvar "_fieldBegin") $
+       protocolFun "parseFieldBegin" `app` lastId `app` var "_idMap"
+     , Qualifier () $
+       Case () (var "_fieldBegin")
+       [ Alt ()
+         (PApp () (qualSym "Thrift" "FieldBegin")
+          [ pvar "_type", pvar "_id", pvar "_bool" ])
+         (UnGuardedRhs () $ Do ()
+          [ Qualifier () $ Case () (var "_id") $
+            map genParseValue unionAlts ++
+            [ Alt () (PWildCard ())
+              (UnGuardedRhs () $ case unionHasEmpty of
+                NonEmpty ->
+                  qvar "Prelude" "fail" `app`
+                  (infixApp "++"
+                   (stringLit
+                    ("unrecognized alternative for union '" <>
+                     unionName <>
+                     "': "))
+                   (qvar "Prelude" "show" `app` var "_id"))
+                HasEmpty -> Do ()
+                  [ Qualifier () $
+                      protocolFun "parseSkip" `app`
+                      var "_type" `app`
+                      qcon "Prelude" "Nothing"
+                  , Qualifier () $ protocolFun "parseStop"
+                  , Qualifier () $
+                      qvar "Prelude" "return" `app` con unionEmptyName
+                  ])
+              Nothing
+            ]
+          ])
+         Nothing
+       , Alt () (PApp () (qualSym "Thrift" "FieldEnd") [])
+         (UnGuardedRhs () $
+          case unionHasEmpty of
+            NonEmpty -> qvar "Prelude" "fail" `app`
+                        stringLit ("union '" <> unionName <> "' is empty")
+            HasEmpty -> qvar "Prelude" "return" `app` con unionEmptyName)
+         Nothing
+       ]
+     ])
+    (Just $ BDecls ()
+     [ PatBind () (pvar "_idMap")
+       (UnGuardedRhs () $
+        qvar "HashMap" "fromList" `app`
+        HS.List ()
+        (map (\UnionAlt{..} ->
+         Tuple () Boxed [ stringLit altName, intLit altId ])
+         unionAlts))
+       Nothing
+     ])
+  ]
+  where
+    lastId = intLit (0 :: Int)
+
+genParseValue :: HS UnionAlt -> Alt ()
+genParseValue UnionAlt{..} =
+  Alt ()
+  (PLit ()
+   (if altId < 0 then Negative () else Signless ())
+   (Int () (abs $ fromIntegral altId) (show altId)))
+  (GuardedRhss ()
+   -- check that the parsed type is correct
+   [ GuardedRhs ()
+     [ Qualifier () $
+       infixApp "==" (var "_type") (genThriftType altResolvedType)
+     ] $ Do ()
+     [ Generator () (pvar "_val") $ genParseType P_FieldMode altResolvedType
+     , Qualifier () $ protocolFun "parseStop"
+     , Qualifier () $
+       qvar "Prelude" "return" `app`
+       (con altResolvedName `app` var "_val")
+     ]
+   ])
+  Nothing
+
+-- Generate NFData Instance ----------------------------------------------------
+
+genNFData :: HS Union -> HS.Decl ()
+genNFData Union{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "DeepSeq" "NFData")
+       (TyCon () $ unqualSym unionResolvedName))
+    (Just
+     [ InsDecl () $ FunBind () $
+       (flip map unionAlts $ \UnionAlt{..} ->
+         Match () (textToName "rnf")
+         [ PApp () (unqualSym altResolvedName) [ pvar ("__" <> altName) ] ]
+         (UnGuardedRhs () $ qvar "DeepSeq" "rnf" `app` var ("__" <> altName))
+         Nothing) ++
+       case unionHasEmpty of
+         NonEmpty -> []
+         HasEmpty ->
+           [ Match () (textToName "rnf")
+             [ PApp () (unqualSym unionEmptyName) [] ]
+             (UnGuardedRhs () $ unit_con ())
+             Nothing
+           ]
+     ])
+
+-- Generate Default Instance ---------------------------------------------------
+
+genDefault :: HS Union -> HS.Decl ()
+genDefault Union{..} =
+  InstDecl () Nothing
+    (IRule () Nothing Nothing $
+     IHApp ()
+       (IHCon () $ qualSym "Default" "Default")
+       (TyCon () $ unqualSym unionResolvedName))
+    (Just
+     [ InsDecl () $ FunBind ()
+       [ Match () (textToName "def") []
+         (UnGuardedRhs () $
+          case (unionHasEmpty, unionAlts) of
+            (HasEmpty, _) -> con unionEmptyName
+            (NonEmpty, UnionAlt{..} : _) ->
+              con altResolvedName `app` typeToDefault altResolvedType
+            (NonEmpty, []) ->
+              qvar "Exception" "throw" `app`
+              (qcon "Thrift" "ProtocolException" `app`
+               stringLit
+               ("def: no default value for empty union '" <> unionResolvedName
+                <> "'")))
+         Nothing
+       ]
+     ])
+
+-- Generate Default Instance ---------------------------------------------------
+
+genHashable :: HS Union -> HS.Decl ()
+genHashable Union{..} =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp ()
+   (IHCon () $ qualSym "Hashable" "Hashable")
+   (TyCon () $ unqualSym unionResolvedName))
+  (Just
+   [ InsDecl () $ FunBind () $
+     map genHashWithSalt unionAlts ++
+     case unionHasEmpty of
+       NonEmpty -> []
+       HasEmpty -> [ genHashWithSaltEmpty unionEmptyName ]
+   ])
+
+genHashWithSalt :: HS UnionAlt -> Match ()
+genHashWithSalt UnionAlt{..} =
+  Match () (textToName "hashWithSalt")
+  [ pvar "__salt"
+  , PApp () (unqualSym altResolvedName)
+    [ pvar $ "_" <> altName ]
+  ]
+  (UnGuardedRhs () $
+   qvar "Hashable" "hashWithSalt" `app`
+   var "__salt" `app`
+   (qvar "Hashable" "hashWithSalt" `app`
+    intLit altId `app`
+    transformValue mkHashable Default altResolvedType (var $ "_" <> altName)))
+  Nothing
+
+genHashWithSaltEmpty :: Text -> Match ()
+genHashWithSaltEmpty uname =
+  Match () (textToName "hashWithSalt")
+  [ pvar "__salt"
+  , PApp () (unqualSym uname) []
+  ]
+  (UnGuardedRhs () $
+   qvar "Hashable" "hashWithSalt" `app`
+   var "__salt" `app`
+   ExpTypeSig () (intLit (0 ::Int)) (qualType "Prelude" "Int"))
+  Nothing
+
+-- Generate Default Instance ---------------------------------------------------
+
+genOrd :: HS Union -> HS.Decl ()
+genOrd Union{..} =
+  InstDecl () Nothing
+  (IRule () Nothing Nothing $
+   IHApp ()
+   (IHCon () $ qualSym "Ord" "Ord")
+   (TyCon () $ unqualSym unionName))
+  (Just
+   [ InsDecl () $ FunBind () $
+     concatMap genCompare unionAlts ++
+     case unionHasEmpty of
+       NonEmpty -> []
+       HasEmpty -> genCompareEmpty unionEmptyName
+   ])
+
+genCompare :: HS UnionAlt -> [Match ()]
+genCompare UnionAlt{..} =
+  [ Match () (textToName "compare")
+    [ PApp () (unqualSym altResolvedName) [pvar "__a"]
+    , PApp () (unqualSym altResolvedName) [pvar "__b"]
+    ]
+    (UnGuardedRhs () $
+     qvar "Ord" "compare" `app`
+     transform (var "__a") `app`
+     transform (var "__b"))
+    Nothing
+  , Match () (textToName "compare")
+    [ PApp () (unqualSym altResolvedName) [PWildCard ()]
+    , PWildCard ()
+    ]
+    (UnGuardedRhs () $ qcon "Ord" "LT")
+    Nothing
+  ]
+  where
+    transform = transformValue mkOrd Default altResolvedType
+
+genCompareEmpty :: Text -> [Match ()]
+genCompareEmpty uname =
+  [ Match () (textToName "compare")
+    [ PApp () (unqualSym uname) []
+    , PApp () (unqualSym uname) []
+    ]
+    (UnGuardedRhs () $ qcon "Ord" "EQ")
+    Nothing
+  , Match () (textToName "compare")
+    [ PApp () (unqualSym uname) []
+    , PWildCard ()
+    ]
+    (UnGuardedRhs () $ qcon "Ord" "GT")
+    Nothing
+  ]
diff --git a/Thrift/Compiler/GenUtils.hs b/Thrift/Compiler/GenUtils.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/GenUtils.hs
@@ -0,0 +1,525 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.GenUtils
+  ( textToName
+  , qualSym, unqualSym, nameToQName
+  , qualType, simpleType
+  , qvar, var, pvar, con, qcon, tvar
+  , app, appT, infixApp, compose
+  , genImportModule, importFromInclude, typeToImport
+  , intLit, stringLit, intP, stringP, listE
+  , deriving_
+  , genType, isBaseType, genThriftType, genConst, typeToDefault
+  , qualifyType, qualifyField, qualifyResolvedType
+  , genConstructor
+  , Import(..)
+  , protocolFun
+  , genCALL, genREPLY, genEXCEPTION, genONEWAY
+  , PrimType(..), getPrim
+  ) where
+
+import Data.Proxy
+import Data.Set (union)
+import Data.Some
+import Data.Text (Text)
+import Data.Text.Encoding hiding (Some)
+import GHC.TypeLits
+import Language.Haskell.Exts.Syntax hiding (List, Name, Type)
+import qualified Language.Haskell.Exts.Syntax as HS
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Types
+
+data Import
+   = QImport Text Text
+   | SymImport Text [Text]
+   | TypesImport Text
+   deriving (Show, Eq, Ord)
+
+textToName :: Text -> HS.Name ()
+textToName = Ident () . Text.unpack
+
+genImportModule :: Import -> ImportDecl ()
+genImportModule (QImport modName modAs) = ImportDecl
+  { importAnn       = ()
+  , importModule    = ModuleName () $ Text.unpack modName
+  , importQualified = True
+  , importSrc       = False
+  , importSafe      = False
+  , importPkg       = Nothing
+  , importAs        = Just $ ModuleName () $ Text.unpack modAs
+  , importSpecs     = Nothing
+  }
+genImportModule (SymImport modName symbols) = ImportDecl
+  { importAnn       = ()
+  , importModule    = ModuleName () $ Text.unpack modName
+  -- Symbols are not imported qualified because you can't define your own
+  -- operators in Thrift, therefore they are guaranteed not to collide
+  , importQualified = False
+  , importSrc       = False
+  , importSafe      = False
+  , importPkg       = Nothing
+  , importAs        = Nothing
+  , importSpecs     = Just $ ImportSpecList () False (map mkImport symbols)
+  }
+    where mkImport = IVar () . Symbol () . Text.unpack
+genImportModule (TypesImport modName) = ImportDecl
+  { importAnn       = ()
+  , importModule    = ModuleName () $ Text.unpack modName ++ ".Types"
+  , importQualified = False
+  , importSrc       = False
+  , importSafe      = False
+  , importPkg       = Nothing
+  , importAs        = Nothing
+  , importSpecs     = Nothing
+  }
+
+importFromInclude :: Program Haskell a -> Import
+importFromInclude Program{..} =
+  QImport (progHSName <> ".Types") progHSName
+
+typeToImport :: HSType t -> Set.Set Import
+typeToImport = typeToImportRec True
+
+typeToImportRec :: Bool -> HSType t -> Set.Set Import
+typeToImportRec _ I8  = Set.singleton (QImport "Data.Int" "Int")
+typeToImportRec _ I16 = Set.singleton (QImport "Data.Int" "Int")
+typeToImportRec _ I32 = Set.singleton (QImport "Data.Int" "Int")
+typeToImportRec _ I64 = Set.singleton (QImport "Data.Int" "Int")
+typeToImportRec _ (TSpecial HsInt) = Set.empty
+typeToImportRec _ TFloat = Set.empty
+typeToImportRec _ TDouble = Set.empty
+typeToImportRec _ TText = Set.fromList
+  [ QImport "Data.Text" "Text"
+  , QImport "Data.Text.Encoding" "Text"
+  ]
+typeToImportRec r (TSpecial HsString) = typeToImportRec r TText
+typeToImportRec _ (TSpecial HsByteString) = Set.fromList
+  [ QImport "Data.ByteString" "ByteString"
+  , QImport "Data.Text" "Text"
+  , QImport "Data.Text.Encoding" "Text"
+  ]
+typeToImportRec _ TBytes = Set.fromList
+  [ QImport "Data.ByteString" "ByteString"
+  ]
+typeToImportRec _ TBool = Set.empty
+typeToImportRec r (TSet t) =
+  Set.singleton (QImport "Data.Set" "Set") `union`
+  typeToImportRec r t
+typeToImportRec r (THashSet t) =
+  Set.singleton (QImport "Data.HashSet" "HashSet") `union`
+  typeToImportRec r t
+typeToImportRec r (TList t) = typeToImportRec r t
+typeToImportRec r (TSpecial (HsVector vec t)) =
+  Set.singleton (QImport (hsVectorImport vec) (hsVectorQual vec)) `union`
+  typeToImportRec r t
+typeToImportRec r (TMap k v) =
+  Set.singleton (QImport "Data.Map.Strict" "Map") `union`
+  typeToImportRec r k `union`
+  typeToImportRec r v
+typeToImportRec r (THashMap k v) =
+  Set.singleton (QImport "Data.HashMap.Strict" "HashMap") `union`
+  typeToImportRec r k `union`
+  typeToImportRec r v
+typeToImportRec r (TStruct name _loc) = nameToImport r name
+typeToImportRec r (TException name _loc) = nameToImport r name
+typeToImportRec r (TUnion name _loc) = nameToImport r name
+typeToImportRec r (TEnum name _loc _) = nameToImport r name
+typeToImportRec r (TTypedef name ty _loc) =
+  nameToImport r name `union` typeToImportRec False ty
+typeToImportRec r (TNewtype name ty _loc) =
+  nameToImport r name `union` typeToImportRec False ty
+
+nameToImport :: Bool -> Name -> Set.Set Import
+nameToImport cond Name{..} = case resolvedName of
+  QName q _ | cond-> Set.singleton $ QImport (q <> ".Types") q
+  _ -> Set.empty
+
+unqualSym :: Text -> QName ()
+unqualSym = UnQual () . textToName
+
+qualSym :: Text -> Text -> QName ()
+qualSym m sym = Qual () (ModuleName () $ Text.unpack m) (textToName sym)
+
+nameToQName :: Name -> QName ()
+nameToQName Name{..} = case resolvedName of
+  UName n -> unqualSym n
+  QName m n -> qualSym m n
+
+qualType :: Text -> Text -> HS.Type ()
+qualType mname tname = TyCon () $ qualSym mname tname
+
+simpleType :: Text -> HS.Type ()
+simpleType tname = TyCon () $ unqualSym tname
+
+app :: Exp () -> Exp () -> Exp ()
+app = App ()
+infixl `app`
+
+appT :: HS.Type () -> HS.Type () -> HS.Type ()
+appT = TyApp ()
+infixl `appT`
+
+infixApp :: Text -> Exp () -> Exp () -> Exp ()
+infixApp sym e1 e2 =
+  InfixApp () e1 (QVarOp () $ UnQual () $ Symbol () $ Text.unpack sym) e2
+
+compose :: Exp () -> Exp () -> Exp ()
+compose = infixApp "."
+
+stringLit :: Text -> Exp ()
+stringLit text = Lit () $ String () s s
+  where s = Text.unpack text
+
+listE :: [Exp ()] -> Exp ()
+listE = HS.List ()
+
+intLit :: (Integral a, Show a) => a -> Exp ()
+intLit x = wrapNegativeLit x $ Lit () $ Int () (fromIntegral x) (show x)
+
+floatLit :: (Real a, Show a) => a -> Exp ()
+floatLit x = wrapNegativeLit x $ Lit () $ Frac () (toRational x) (show x)
+
+wrapNegativeLit :: Show a => a -> Exp () -> Exp ()
+wrapNegativeLit x = case show x of
+  '-':_ -> Paren ()
+  _ -> id
+  -- NB: we check the result of show directly to handle negative zeros
+  --
+  -- >>> let x = -0.0 in (show x, signum x, x < 0)
+  -- ("-0.0", -0.0, False)
+
+intP :: (Integral a, Show a) => a -> Pat ()
+intP x = PLit () (sign ()) $ Int () (fromIntegral $ abs x) (show x)
+  where sign | x < 0 = Negative
+             | otherwise = Signless
+
+stringP :: Text -> Pat ()
+stringP text = PLit () (Signless ()) $ String () s s
+  where s = Text.unpack text
+
+var :: Text -> Exp ()
+var = Var () . unqualSym
+
+qvar :: Text -> Text -> Exp ()
+qvar m n = Var () $ qualSym m n
+
+pvar :: Text -> Pat ()
+pvar name = PVar () $ textToName name
+
+con :: Text -> Exp ()
+con = Con () . unqualSym
+
+qcon :: Text -> Text -> Exp ()
+qcon m n = Con () $ qualSym m n
+
+tvar :: Text -> HS.Type ()
+tvar = TyVar () . textToName
+
+deriving_ :: [InstRule ()] -> Deriving ()
+deriving_ = Deriving () Nothing
+
+genType :: HSType t -> HS.Type ()
+genType I8      = qualType "Int" "Int8"
+genType I16     = qualType "Int" "Int16"
+genType I32     = qualType "Int" "Int32"
+genType I64     = qualType "Int" "Int64"
+genType (TSpecial HsInt) = qualType "Prelude" "Int"
+genType TFloat  = qualType "Prelude" "Float"
+genType TDouble = qualType "Prelude" "Double"
+genType TBool   = qualType "Prelude" "Bool"
+genType TText   = qualType "Text" "Text"
+genType (TSpecial HsString) = qualType "Prelude" "String"
+genType (TSpecial HsByteString) = qualType "ByteString" "ByteString"
+genType TBytes  = qualType "ByteString" "ByteString"
+genType (TList ty) = TyList () (genType ty)
+genType (TSpecial (HsVector vec ty)) =
+  qualType (hsVectorQual vec) "Vector" `appT` genType ty
+genType (TSet ty)  = qualType "Set" "Set" `appT` genType ty
+genType (THashSet ty) = qualType "HashSet" "HashSet" `appT` genType ty
+genType (TMap k v) = qualType "Map" "Map" `appT` genType k `appT` genType v
+genType (THashMap k v) =
+  qualType "HashMap" "HashMap" `appT` genType k `appT` genType v
+genType (TStruct name _loc)    = TyCon () $ nameToQName name
+genType (TException name _loc) = TyCon () $ nameToQName name
+genType (TUnion name _loc)     = TyCon () $ nameToQName name
+genType (TEnum name _loc _)      = TyCon () $ nameToQName name
+genType (TTypedef name _ _loc) = TyCon () $ nameToQName name
+genType (TNewtype name _ _loc) = TyCon () $ nameToQName name
+
+genConst :: HSType t -> TypedConst Haskell t -> Exp ()
+-- Base Type Literals
+genConst I8  (Literal x) = intLit x
+genConst I16 (Literal x) = intLit x
+genConst I32 (Literal x) = intLit x
+genConst I64 (Literal x) = intLit x
+genConst (TSpecial HsInt) (Literal x) = intLit x
+genConst TFloat  (Literal x) = floatLit x
+genConst TDouble (Literal x) = floatLit x
+genConst TBool   (Literal x) = qvar "Prelude" $ if x then "True" else "False"
+genConst TText   (Literal s) = stringLit s
+genConst (TSpecial HsString) (Literal s) = Lit () $ String () s s
+genConst (TSpecial HsByteString) (Literal s) = stringLit $ decodeUtf8 s
+genConst TBytes (Literal s) = stringLit $ decodeUtf8 s
+-- Collection Literals
+genConst (TList ty)   (Literal (List l)) = HS.List () $ map (genConst ty) l
+genConst (TSpecial (HsVector vec ty)) (Literal (List l)) =
+  qvar (hsVectorQual vec) "fromList" `app` HS.List () (map (genConst ty) l)
+genConst (TSet ty) (Literal (Set l)) =
+  qvar "Set" "fromList" `app` HS.List () (map (genConst ty) l)
+genConst (THashSet ty) (Literal (HashSet l)) =
+  qvar "HashSet" "fromList" `app` HS.List () (map (genConst ty) l)
+genConst (TMap kt vt) (Literal (Map m)) =
+  qvar "Map" "fromList" `app`
+  HS.List () (map (\(k, v) -> Tuple () Boxed [genConst kt k, genConst vt v]) m)
+genConst (THashMap kt vt) (Literal (HashMap m)) =
+  qvar "HashMap" "fromList" `app`
+  HS.List () (map (\(k, v) -> Tuple () Boxed [genConst kt k, genConst vt v]) m)
+-- Names Type Constants
+genConst (TTypedef _ ty _loc) lit@Literal{} = genConst ty lit
+genConst (TNewtype name ty _loc) (Literal (New lit)) =
+  Con () (nameToQName name) `app` genConst ty (Literal lit)
+genConst (TStruct name _loc) (Literal (Some s)) = genStructConst name s
+genConst (TException name _loc) (Literal (Some (EV s))) = genStructConst name s
+genConst (TUnion name _loc) (Literal (Some (UnionVal proxy ty val _))) =
+  Con () (nameToQName cname) `app` genConst ty val
+  where
+    conName = Text.pack $ symbolVal proxy
+    cname = name { resolvedName = mapName (const conName) $ resolvedName name }
+genConst (TEnum _ _loc _) (Literal (EnumVal name _)) = Con () $ nameToQName name
+-- Identifiers
+genConst _ (Identifier name _ _loc) = Var () $ nameToQName name
+-- TODO: WeirdEnumToInt needs some kind of explicit conversion, this should fail
+genConst _ (WeirdEnumToInt _ name _ _loc) = Var () $ nameToQName name
+
+genStructConst :: Name -> StructVal Haskell s -> Exp ()
+genStructConst name struct =
+  case fields struct of
+    [] -> def
+    flds -> RecUpdate () (Paren () def) flds
+  where
+    def = ExpTypeSig () (qvar "Default" "def") (TyCon () $ nameToQName name)
+    fields :: StructVal Haskell s -> [FieldUpdate ()]
+    fields Empty = []
+    fields (ConsVal proxy ty val s) =
+      FieldUpdate () (getName proxy) (genConst ty val) : fields s
+    fields (ConsDefault _ _ s) = fields s
+    fields (ConsJust proxy ty val s) =
+      FieldUpdate () (getName proxy)
+        (qcon "Prelude" "Just" `app` genConst ty val) : fields s
+    fields (ConsNothing _ s) = fields s
+    getName :: KnownSymbol s => Proxy s -> QName ()
+    getName proxy =
+      nameToQName name { resolvedName = mapName (const n) $ resolvedName name }
+      where n = Text.pack $ symbolVal proxy
+
+typeToDefault :: HSType t -> Exp ()
+typeToDefault TBool = qcon "Prelude" "False"
+typeToDefault TText = stringLit ""
+typeToDefault TBytes = stringLit ""
+typeToDefault THashMap{} = qvar "HashMap" "empty"
+typeToDefault THashSet{} = qvar "HashSet" "empty"
+typeToDefault (TSpecial (HsVector vec _)) = qvar (hsVectorQual vec) "empty"
+typeToDefault (TTypedef _ ty _loc) = typeToDefault ty
+typeToDefault (TNewtype name ty _loc) =
+  Con () (nameToQName name) `app` typeToDefault ty
+-- Everything else has default instances
+typeToDefault _ = qvar "Default" "def"
+
+isBaseType :: HSType t -> Bool
+isBaseType I8 = True
+isBaseType I16 = True
+isBaseType I32 = True
+isBaseType I64 = True
+isBaseType (TSpecial HsInt) = True
+isBaseType TFloat = True
+isBaseType TDouble = True
+isBaseType TBool = True
+isBaseType TText = True
+isBaseType (TSpecial HsString) = True
+isBaseType (TSpecial HsByteString) = True
+isBaseType TBytes = True
+isBaseType (TTypedef _ t _loc) = isBaseType t
+isBaseType (TNewtype _ t _loc) = isBaseType t
+isBaseType _ = False
+
+genThriftType :: HSType t -> Exp ()
+genThriftType I8      = protocolFun "getByteType"
+genThriftType I16     = protocolFun "getI16Type"
+genThriftType I32     = protocolFun "getI32Type"
+genThriftType I64     = protocolFun "getI64Type"
+genThriftType (TSpecial HsInt) = protocolFun "getI64Type"
+genThriftType TFloat  = protocolFun "getFloatType"
+genThriftType TDouble = protocolFun "getDoubleType"
+genThriftType TBool   = protocolFun "getBoolType"
+genThriftType TText   = protocolFun "getStringType"
+genThriftType (TSpecial HsString) = protocolFun "getStringType"
+genThriftType (TSpecial HsByteString) = protocolFun "getStringType"
+genThriftType TBytes  = protocolFun "getStringType"
+genThriftType TList{}    = protocolFun "getListType"
+genThriftType (TSpecial HsVector{}) = protocolFun "getListType"
+genThriftType TSet{}     = protocolFun "getSetType"
+genThriftType THashSet{} = protocolFun "getSetType"
+genThriftType TMap{}     = protocolFun "getMapType"
+genThriftType THashMap{} = protocolFun "getMapType"
+genThriftType TStruct{}  = protocolFun "getStructType"
+genThriftType TException{} = protocolFun "getStructType"
+genThriftType TUnion{} = protocolFun "getStructType"
+genThriftType TEnum{}    = protocolFun "getI32Type"
+genThriftType (TTypedef _ ty _loc) = genThriftType ty
+genThriftType (TNewtype _ ty _loc) = genThriftType ty
+
+protocolFun :: Text -> Exp ()
+protocolFun fun = qvar "Thrift" fun `app` var "_proxy"
+
+genCALL, genREPLY, genEXCEPTION, genONEWAY :: Int
+genCALL      = 1
+genREPLY     = 2
+genEXCEPTION = 3
+genONEWAY    = 4
+
+data PrimType = P_I8 | P_I16 | P_I32 | P_I64 | P_Bool
+
+getPrim :: HSType t -> Maybe PrimType
+getPrim I8    = Just P_I8
+getPrim I16   = Just P_I16
+getPrim I32   = Just P_I32
+getPrim I64   = Just P_I64
+getPrim TBool = Just P_Bool
+getPrim _ = Nothing
+
+qualifyType :: Text -> HSType t -> HSType t
+qualifyType _ I8      = I8
+qualifyType _ I16     = I16
+qualifyType _ I32     = I32
+qualifyType _ I64     = I64
+qualifyType _ (TSpecial HsInt) = TSpecial HsInt
+qualifyType _ TFloat  = TFloat
+qualifyType _ TDouble = TDouble
+qualifyType _ TBool   = TBool
+qualifyType _ TText   = TText
+qualifyType _ (TSpecial HsString) = TSpecial HsString
+qualifyType _ (TSpecial HsByteString) = TSpecial HsByteString
+qualifyType _ TBytes  = TBytes
+qualifyType q (TList u) = TList $ qualifyType q u
+qualifyType q (TSpecial (HsVector vec u)) =
+  TSpecial $ HsVector vec $ qualifyType q u
+qualifyType q (TSet u) = TSet $ qualifyType q u
+qualifyType q (THashSet u) = THashSet $ qualifyType q u
+qualifyType q (TMap k v) = TMap (qualifyType q k) (qualifyType q v)
+qualifyType q (THashMap k v) = THashMap (qualifyType q k) (qualifyType q v)
+qualifyType q (TStruct name loc) = TStruct (qualifyName q name) loc
+qualifyType q (TException name loc) = TException (qualifyName q name) loc
+qualifyType q (TEnum name loc nounknown) =
+  TEnum (qualifyName q name) loc nounknown
+qualifyType q (TUnion name loc) = TUnion (qualifyName q name) loc
+qualifyType q (TTypedef name ty loc) =
+  TTypedef (qualifyName q name) (qualifyType q ty) loc
+qualifyType q (TNewtype name ty loc) =
+  TNewtype (qualifyName q name) (qualifyType q ty) loc
+
+qualifySomeType :: Text -> Some HSType -> Some HSType
+qualifySomeType q ty = mapSome (qualifyType q) ty
+
+qualifyResolvedType :: Text -> Maybe (Some HSType) -> Maybe (Some HSType)
+qualifyResolvedType q ty = fmap (qualifySomeType q) ty
+
+qualifyField
+  :: Text -> Field u 'Resolved Haskell a -> Field u 'Resolved Haskell a
+qualifyField q Field{..} = Field
+  { fieldResolvedType = qualifyType q fieldResolvedType
+  , fieldResolvedVal  = qualifyConst q fieldResolvedType <$> fieldResolvedVal
+  , ..
+  }
+
+qualifyConst :: Text -> HSType t -> TypedConst Haskell t -> TypedConst Haskell t
+qualifyConst q _ (Identifier name ty loc) =
+  Identifier (qualifyName q name) (qualifyType q ty) loc
+qualifyConst q _ (WeirdEnumToInt ty name tEnum loc) =
+  WeirdEnumToInt (qualifyType q ty)
+    (qualifyName q name) (qualifyType q tEnum) loc
+qualifyConst q ty (Literal lit) = Literal $ qualifyLit q ty lit
+
+qualifyLit :: Text -> HSType t -> t -> t
+-- Base types don't need to be qualified
+qualifyLit _ I8  x = x
+qualifyLit _ I16 x = x
+qualifyLit _ I32 x = x
+qualifyLit _ I64 x = x
+qualifyLit _ (TSpecial HsInt) x = x
+qualifyLit _ TFloat f = f
+qualifyLit _ TDouble d = d
+qualifyLit _ TBool b = b
+qualifyLit _ TText t = t
+qualifyLit _ TBytes t = t
+qualifyLit _ (TSpecial HsString) s = s
+qualifyLit _ (TSpecial HsByteString) s = s
+-- Collections
+qualifyLit q (TList u) (List l) = List $ map (qualifyConst q u) l
+qualifyLit q (TSpecial (HsVector _ u)) (List l) =
+  List $ map (qualifyConst q u) l
+qualifyLit q (TSet u) (Set s) = Set $ map (qualifyConst q u) s
+qualifyLit q (THashSet u) (HashSet s) = HashSet $ map (qualifyConst q u) s
+qualifyLit q (TMap kt vt) (Map m) =
+  Map [ (qualifyConst q kt k, qualifyConst q vt v) | (k, v) <- m ]
+qualifyLit q (THashMap kt vt) (HashMap m) =
+  HashMap [ (qualifyConst q kt k, qualifyConst q vt v) | (k, v) <- m ]
+-- Named Types
+qualifyLit q TStruct{} (Some s) = Some $ qualifyStruct q s
+qualifyLit q TException{} (Some (EV s)) = Some $ EV $ qualifyStruct q s
+qualifyLit q TEnum{} (EnumVal name loc) = EnumVal (qualifyName q name) loc
+qualifyLit q TUnion{} (Some u) = Some $ qualifyUnion q u
+qualifyLit q (TTypedef _ ty _loc) lit = qualifyLit q ty lit
+qualifyLit q (TNewtype _ ty _loc) (New lit) = New $ qualifyLit q ty lit
+
+qualifyStruct :: Text -> StructVal Haskell s -> StructVal Haskell s
+qualifyStruct _ Empty = Empty
+qualifyStruct q (ConsVal pr ty val s) =
+  ConsVal pr (qualifyType q ty) (qualifyConst q ty val) $ qualifyStruct q s
+qualifyStruct q (ConsDefault pr ty s) =
+  ConsDefault pr (qualifyType q ty) $ qualifyStruct q s
+qualifyStruct q (ConsJust pr ty val s) =
+  ConsJust pr (qualifyType q ty) (qualifyConst q ty val) $
+  qualifyStruct q s
+qualifyStruct q (ConsNothing pr s) = ConsNothing pr $ qualifyStruct q s
+
+qualifyUnion :: Text -> UnionVal Haskell s -> UnionVal Haskell s
+qualifyUnion q (UnionVal pr ty val proof) =
+  UnionVal pr (qualifyType q ty) (qualifyConst q ty val) proof
+
+-- Note: we only care about qualifying the resolved name because the source name
+-- is not used anymore after typechecking
+qualifyName :: Text -> Name -> Name
+qualifyName q name@Name{..} = name
+  { resolvedName = case resolvedName of
+      UName n -> QName q n
+      n@QName{} -> n
+  }
+
+genConstructor
+  :: Maybe Text -> HSType (Some (ExceptionVal Haskell)) -> QName ()
+genConstructor qual (TException name _loc)
+  | Just uname <- getUName name = case qual of
+      Nothing -> unqualSym uname
+      Just q  -> qualSym q uname
+genConstructor _ (TException name _loc) = nameToQName name
+genConstructor qual (TTypedef _ ty _loc) = genConstructor qual ty
+-- This case is impossible since there is no possible value for
+-- SpecialType Haskell (Some (ExceptionVal Haskell))
+-- , which is obvious from looking at the data family instance.
+-- However, the pattern match completeness checker for HSType
+-- doesn't seem to be able to eliminate this case.
+genConstructor _ (TSpecial _) = error "This is provably unreachable"
+
+getUName :: Name -> Maybe Text
+getUName Name{..} = case resolvedName of
+  UName n -> Just n
+  QName{} -> Nothing
diff --git a/Thrift/Compiler/Lexer.x b/Thrift/Compiler/Lexer.x
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Lexer.x
@@ -0,0 +1,274 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+{
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+module Thrift.Compiler.Lexer
+  ( lexThrift
+  , Token(..), TokenType(..)
+  , AlexPosn(..), Alex(..)
+  , setFilename, getComments
+  , alexMonadScan, alexGetInput, runAlex, alexError
+  ) where
+
+import Control.Monad
+import Control.Monad.Trans.State
+import Data.List.Extra
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Text.Read (readEither)
+
+import Thrift.Compiler.Types
+}
+
+%wrapper "monadUserState"
+
+$all        = [.\n]
+
+$digit      = [0-9]
+@decimal    = [\+\-]?$digit+
+@floating   = [\+\-]?$digit* "." $digit+
+@sciSuffix  = [eE][\+\-]?$digit+
+@scientific = (@floating@sciSuffix | @decimal@sciSuffix)
+@hex        = 0x[0-9a-fA-F]+
+
+-- Note: Thrift strings don't support escaped characters :(
+@string     = \' ($all # \')* \'
+@dstring    = \" ($all # \")* \"
+
+@notEnd     = ($all # [\*\/]) | ($all # \*)"/" | "*"($all # \/)
+@comment    = "/*" @notEnd*"*"* "*/"
+
+tokens :-
+  $white+              ;
+  -- Comments
+  "#"[^\n]*            { addComment }
+  "//"[^\n]*           { addComment }
+  @comment             { addComment }
+
+  -- Keywords
+  "struct"             { basicToken STRUCT }
+  "enum"               { basicToken ENUM }
+  "typedef"            { basicToken TYPEDEF }
+  "const"              { basicToken CONST }
+  "required"           { basicToken REQUIRED }
+  "optional"           { basicToken OPTIONAL }
+  "map"                { basicToken MAP }
+  "list"               { basicToken LIST }
+  "set"                { basicToken SET }
+  "byte"               { basicToken INT8 }
+  "i16"                { basicToken INT16 }
+  "i32"                { basicToken INT32 }
+  "i64"                { basicToken INT64 }
+  "double"             { basicToken DOUBLE }
+  "float"              { basicToken FLOAT }
+  "bool"               { basicToken BOOL }
+  "string"             { basicToken STRING }
+  "void"               { basicToken VOID }
+  "true"               { basicToken TRUE }
+  "false"              { basicToken FALSE }
+  "package"            { basicToken PACKAGE }
+  "namespace"          { basicToken NAMESPACE }
+  "include"            { basicToken INCLUDE }
+  "hs_include"         { basicToken HS_INCLUDE }
+  "hash_map"           { basicToken HASH_MAP }
+  "hash_set"           { basicToken HASH_SET }
+  "binary"             { basicToken BINARY }
+  "senum"              { basicToken SENUM }
+  "stream"             { basicToken STREAM }
+  "void"               { basicToken VOID }
+  "union"              { basicToken UNION }
+  "view"               { basicToken VIEW }
+  "exception"          { basicToken EXCEPTION }
+  "service"            { basicToken SERVICE }
+  "oneway"             { basicToken ONEWAY }
+  "extends"            { basicToken EXTENDS }
+  "throws"             { basicToken THROWS }
+  "async"              { basicToken ASYNC }
+  "cpp_include"        { basicToken CPP_INCLUDE }
+  "safe"               { basicToken SAFE }
+  "transient"          { basicToken TRANSIENT }
+  "stateful"           { basicToken STATEFUL }
+  "permanent"          { basicToken PERMANENT }
+  "server"             { basicToken SERVER }
+  "client"             { basicToken CLIENT }
+  "readonly"           { basicToken READONLY }
+  "idempotent"         { basicToken IDEMPOTENT }
+  "interaction"        { basicToken INTERACTION }
+  "performs"           { basicToken PERFORMS }
+
+
+  -- Literals
+  @scientific          { numToken FLOATING }
+  @floating            { numToken FLOATING }
+  @decimal             { numToken INTEGRAL }
+  @hex                 { numToken INTEGRAL }
+  @string|@dstring     { strToken }
+
+  -- Identifiers
+ [a-zA-Z_] [a-zA-Z0-9_\.]*  { symbolToken }
+
+  -- Symbols
+  "{"                  { basicToken L_CURLY_BRACE }
+  "}"                  { basicToken R_CURLY_BRACE }
+  "["                  { basicToken L_SQUARE_BRACE }
+  "]"                  { basicToken R_SQUARE_BRACE }
+  "<"                  { basicToken L_ANGLE_BRACE }
+  ">"                  { basicToken R_ANGLE_BRACE }
+  "("                  { basicToken L_PAREN }
+  ")"                  { basicToken R_PAREN }
+  ","                  { basicToken COMMA }
+  ":"                  { basicToken COLON }
+  ";"                  { basicToken SEMICOLON }
+  "="                  { basicToken EQUALS }
+  "@"                  { basicToken AT }
+
+{
+
+data Token
+  = Tok TokenType (Located Loc)
+  | EOF
+  deriving (Show, Eq)
+
+data TokenType
+  -- Braces
+  = L_CURLY_BRACE  | R_CURLY_BRACE
+  | L_ANGLE_BRACE  | R_ANGLE_BRACE
+  | L_SQUARE_BRACE | R_SQUARE_BRACE
+  | L_PAREN        | R_PAREN
+  -- Puntuation
+  | COMMA | SEMICOLON | COLON | EQUALS | AT
+  -- Headers
+  | NAMESPACE | INCLUDE | HS_INCLUDE
+  -- Other Keywords
+  | STRUCT | ENUM | TYPEDEF | CONST
+  | REQUIRED | OPTIONAL
+  -- Types
+  | MAP | LIST | SET
+  | HASH_MAP | HASH_SET
+  | INT8 | INT16 | INT32 | INT64
+  | DOUBLE | FLOAT
+  | BOOL | STRING
+  -- Literals
+  | INTEGRAL Int Text
+  | FLOATING Double Text
+  | STRING_LIT String QuoteType
+  | SYMBOL String
+  | TRUE | FALSE
+  -- Stuff we don't use (yet)
+  | SENUM | STREAM | VOID | BINARY | INTERACTION
+  | UNION | VIEW | EXCEPTION | SERVICE
+  | ONEWAY | EXTENDS | THROWS | ASYNC | PERFORMS
+  | SAFE | TRANSIENT | STATEFUL | PERMANENT | SERVER | CLIENT
+  | READONLY | IDEMPOTENT
+  | PACKAGE
+  -- Stuff we won't use ever
+  | CPP_INCLUDE
+  deriving (Show, Eq)
+
+-- Note: the following tokens exist, but as far as I can tell aren't ever used
+-- We exclude them for brevity:
+--
+-- java_package, cocoa_prefix, csharp_namespace, php_namespace, ruby_namespace,
+-- py_module, perl_package, smalltalk_category, smalltalk_prefix, xsd_all,
+-- xsd_optional, xsd_nillable, xsd_namespace, xsd_attrs, slist
+
+data AlexUserState = AlexUserState
+  { ust_filename :: FilePath
+  , ust_comments :: [Comment Loc] -> [Comment Loc]
+  }
+
+alexInitUserState :: AlexUserState
+alexInitUserState = AlexUserState "" id
+
+getFilename :: Alex FilePath
+getFilename = Alex $ \s@AlexState{alex_ust=AlexUserState{..}} ->
+  Right (s, ust_filename)
+
+setFilename :: FilePath -> Alex ()
+setFilename f = Alex $ \s@AlexState{..} ->
+  Right (s {alex_ust = alex_ust { ust_filename = f } }, ())
+
+getComments :: Alex [Comment Loc]
+getComments = Alex $ \s@AlexState{alex_ust=ust@AlexUserState{..}} ->
+  Right (s { alex_ust = ust { ust_comments = id } }, ust_comments [])
+
+addComment :: AlexInput -> Int -> Alex Token
+addComment i@(_,_,_,input) len = do
+  loc <- getLoc i len
+  let c = Comment loc $ Text.pack $ take len input
+  Alex $ \s@AlexState{alex_ust=ust@AlexUserState{..}} ->
+    Right (s{alex_ust = ust{ust_comments = ust_comments . (c:)}}, ())
+  alexMonadScan
+
+getLoc :: AlexInput -> Int -> Alex Loc
+getLoc (AlexPn _ l c,_,_,input) len = do
+  file <- getFilename
+  let
+    chunk = take len input
+    newlines = length $ filter (== '\n') chunk
+    endcol | newlines == 0 = c + len
+           | otherwise = length $ takeWhileEnd (/= '\n') chunk
+  return $ Loc file l c (l + newlines) endcol
+
+basicToken :: TokenType -> AlexInput -> Int -> Alex Token
+basicToken tok i@(AlexPn _ l c,_,_,_) len = do
+  loc <- getLoc i len
+  cs <- getComments
+  pure $ Tok tok $ Located cs loc
+
+strToken :: AlexInput -> Int -> Alex Token
+strToken i@(_, _, _, input) len = basicToken (mkString str qtype) i len
+  where
+    str = take len input
+    mkString s = STRING_LIT $ drop 1 $ take (n - 1) s
+      where n = length s
+    qtype = case str of
+      '"':_ -> DoubleQuote
+      _     -> SingleQuote
+
+symbolToken :: AlexInput -> Int -> Alex Token
+symbolToken i@(p, _, _, input) len = basicToken (SYMBOL (take len input)) i len
+
+numToken
+  :: (Read a, Num a)
+  => (a -> Text -> TokenType)
+  -> AlexInput
+  -> Int
+  -> Alex Token
+numToken mkTok i@(AlexPn _ l c, _, _, input) len =
+  case parseNumWithSign rawInput of
+    Left err -> do
+      file <- getFilename
+      alexError $ concat
+        [file, ":", show l, ":", show c, ": ", err]
+    Right num -> basicToken (mkTok num $ Text.pack rawInput) i len
+  where
+    rawInput = take len input
+
+    parseNumWithSign ('+' : num) = parseNum num
+    parseNumWithSign ('-' : num) = negate <$> parseNum num
+    parseNumWithSign num = parseNum num
+
+    -- Read doesn't like numbers starting with decimal points, so concat a `0`
+    -- to the front if it isn't there.
+    parseNum num@('.':_) = readEither $ '0':num
+    parseNum num = readEither num
+
+alexEOF :: Alex Token
+alexEOF = pure EOF
+
+lexThrift :: String -> Either String [Token]
+lexThrift input = runAlex input go
+  where
+    go = do
+      tok <- alexMonadScan
+      case tok of
+        EOF -> return []
+        _ -> (tok :) <$> go
+
+}
diff --git a/Thrift/Compiler/OptParse.hs b/Thrift/Compiler/OptParse.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/OptParse.hs
@@ -0,0 +1,188 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE MonadComprehensions #-}
+{-# LANGUAGE CPP #-}
+module Thrift.Compiler.OptParse
+  ( optionsParser
+  , ThriftLanguage
+  , SomeOptions(..), SomeLangOpts(..)
+  ) where
+
+#if __GLASGOW_HASKELL__ <= 804
+import Data.Monoid ( (<>) )
+#endif
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Data.Typeable
+import Options.Applicative
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Plugin
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Plugins.Linter
+
+-- Types -----------------------------------------------------------------------
+
+type ThriftLanguage l =
+  ( Typecheckable l
+  , Typeable l
+  )
+
+data SomeOptions = forall l. ThriftLanguage l => TheseOptions (Options l)
+
+-- Hack because data families must be saturated
+data SomeLangOpts = forall l. ThriftLanguage l => TheseLangOpts (LangOpts l)
+
+-- Parsers ---------------------------------------------------------------------
+
+optionsParser :: Parser SomeOptions
+optionsParser = do
+  optsPath <- strArgument $ mconcat
+    [ metavar "INPUT"
+    , help "Generate code for thrift file INPUT"
+    ]
+  optsOutPath <- strOption $ mconcat
+    [ long "output-dir"
+    , short 'o'
+    , metavar "DIR"
+    , help "Output generated files in DIR"
+    , value "."
+    ]
+  optsIncludePath <- strOption $ mconcat
+    [ long "include-dir"
+    , short 'I'
+    , metavar "DIR"
+    , help "Base directory for includes DIR"
+    , value "."
+    ]
+  optsThriftMade <- maybeStr
+    [ long "record-genfiles"
+    , metavar "GENFILES"
+    , help "Output generated file to GENFILES"
+    ]
+  optsGenMode <- modeParser
+  lo <- langOptsParser
+  optsReqSymbols <- maybeList
+    [ long "required-symbols"
+    , help "List of symbols that should be generated"
+    ]
+  optsRecursive <- switch $ mconcat
+    [ long "recursive"
+    , short 'r'
+    , help "Recursively generate dependencies"
+    ]
+  optsSingleOutput <- switch $ mconcat
+    [ long "single-output"
+    , help "When emitting JSON in recursive mode, dump output to a single file"
+    ]
+  optsLenient <- switch $ mconcat
+    [ long "lenient"
+    , help "Parse & Typecheck weird old thrift files, disables code generation"
+    ]
+  optsLenientStillGenCode <- switch $ mconcat
+    [ long "lenient-still-gencode"
+    , help "Do code generation for lenient runs"
+    ]
+  -- We can support parsing these options for compatibility, but they don't do
+  -- anything
+  _ <- switch (long "allow-64bit-consts")
+  _ <- switch (long "allow-neg-keys")
+  _ <- switch (long "allow-neg-enum-vals")
+  _ <- maybeStr [long "templates"]
+  pure $ case lo of
+    TheseLangOpts optsLangSpecific -> TheseOptions Options{..}
+
+modeParser :: Parser Mode
+modeParser =
+  flag' Lint
+  (mconcat
+   [ long "lint"
+   , help "Only invoke the typechecker, do not emit any code"
+   ]) <|>
+  flag' (EmitJSON WithoutLoc)
+  (mconcat
+   [ long "emit-json"
+   , help "Dump the typechecked thrift AST as JSON in the output directory"
+   ]) <|>
+  flag' (EmitJSON WithLoc)
+  (mconcat
+   [ long "emit-json-loc"
+   , help $ "Dump the typechecked thrift AST as JSON"
+            <> " with Locations in the output directory"
+   ]) <|>
+  -- Default Mode is code generation
+  pure EmitCode
+
+langOptsParser :: Parser SomeLangOpts
+langOptsParser =
+  (TheseLangOpts <$> hsOptsParser) <|>
+  pure (TheseLangOpts NoOpts)
+
+hsOptsParser :: Parser (LangOpts Haskell)
+hsOptsParser = do
+  _ <- flag' () $ mconcat
+    [ long "hs"
+    , help "Target Haskell"
+    ]
+  hsoptsEnableHaddock <- switch $ mconcat
+    [ long "enable-haddock"
+    , help "Enable generating and building haddock"
+    ]
+  hsoptsUseInt <- switch $ mconcat
+    [ long "use-int"
+    , help $ "Use the Haskell type Int for the thrift type i64 " ++
+             "(not recommended for 32-bit systems)"
+    ]
+  hsoptsUseHashMap <- switch $ mconcat
+    [ long "use-hash-map"
+    , help "Use the Haskell type HashMap for the thrift type map"
+    ]
+  hsoptsUseHashSet <- switch $ mconcat
+    [ long "use-hash-set"
+    , help "Use the Haskell type HashSet for the thrift type set"
+    ]
+  hsoptsDupNames <- switch $ mconcat
+    [ long "duplicate-names"
+    , help "Do not de-dup struct field names"
+    ]
+  hsoptsExtensions <- listOption
+    [ long "extensions"
+    , help "List of language extensions to turn on"
+    , value []
+    ]
+  hsoptsGenPrefix <- strOption $ mconcat
+    [ long "gen-prefix"
+    , short 'g'
+    , metavar "DIR"
+    , help "Prefix for generated file paths, default 'gen-hs2'"
+    , value "gen-hs2"
+    ]
+  hsoptsExtraHasFields <- switch $ mconcat
+    [ long "extra-hasfields"
+    , help "Generate HasField instances for unqualified struct names"
+    ]
+
+  return HsOpts{..}
+
+-- Helpers ---------------------------------------------------------------------
+
+maybeStr :: [Mod OptionFields FilePath] -> Parser (Maybe FilePath)
+maybeStr = optional . strOption . mconcat
+
+strToList :: String -> [Text]
+strToList s | null s    = []
+            | otherwise = Text.splitOn "," $ Text.pack s
+
+listOption :: [Mod OptionFields String] -> Parser [Text]
+listOption = fmap strToList . strOption . mconcat
+
+maybeList :: [Mod OptionFields String] -> Parser (Maybe [Text])
+maybeList = optional . listOption
diff --git a/Thrift/Compiler/Options.hs b/Thrift/Compiler/Options.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Options.hs
@@ -0,0 +1,50 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.Options
+  ( Options(..), defaultOptions
+  , Mode(..), LangOpts
+  , OptLoc(..)
+  ) where
+
+import Data.Text (Text)
+
+data Options l = Options
+  { optsPath          :: FilePath
+  , optsOutPath       :: FilePath
+  , optsIncludePath   :: FilePath
+  , optsThriftMade    :: Maybe FilePath
+  , optsGenMode       :: Mode
+  , optsLangSpecific  :: LangOpts l
+  , optsRecursive     :: Bool
+  , optsReqSymbols    :: Maybe [Text]
+  , optsSingleOutput  :: Bool
+  , optsLenient       :: Bool -- ^ whether to accept older weirder thrift files
+  , optsLenientStillGenCode :: Bool -- ^ whether to still generate code under lenient
+  }
+
+defaultOptions :: LangOpts l -> Options l
+defaultOptions opts = Options
+  { optsPath          = ""
+  , optsOutPath       = "."
+  , optsIncludePath   = "."
+  , optsThriftMade    = Nothing
+  , optsGenMode       = Lint
+  , optsLangSpecific  = opts
+  , optsRecursive     = False
+  , optsReqSymbols    = Nothing
+  , optsSingleOutput  = False
+  , optsLenient       = False
+  , optsLenientStillGenCode = False
+  }
+
+data OptLoc = WithoutLoc | WithLoc
+
+data Mode = Lint | EmitJSON OptLoc | EmitCode
+
+data family LangOpts l
diff --git a/Thrift/Compiler/Parser.y b/Thrift/Compiler/Parser.y
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Parser.y
@@ -0,0 +1,889 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+{
+
+module Thrift.Compiler.Parser
+  ( parseThrift, runParser
+  , parse, parseString
+  , ThriftFile(..), Header(..), Decl(..), getModuleName
+  ) where
+
+import Prelude hiding (Enum)
+import Data.Bifunctor
+import Data.Maybe
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import System.FilePath
+
+import Thrift.Compiler.Lexer
+import Thrift.Compiler.Options
+import Thrift.Compiler.Types
+
+}
+
+%name parseStatements
+%tokentype { Token }
+%lexer { lexWrap } { EOF }
+%monad { Parser } { bind } { return }
+
+%error { parseError }
+
+%token struct      { Tok STRUCT _ }
+       typedef     { Tok TYPEDEF _ }
+       enum        { Tok ENUM _ }
+       const       { Tok CONST _ }
+       required    { Tok REQUIRED _ }
+       optional    { Tok OPTIONAL _ }
+       map         { Tok MAP _ }
+       list        { Tok LIST _ }
+       set         { Tok SET _ }
+       byte        { Tok INT8 _ }
+       i16         { Tok INT16 _ }
+       i32         { Tok INT32 _ }
+       i64         { Tok INT64 _ }
+       double      { Tok DOUBLE _ }
+       float       { Tok FLOAT _ }
+       bool        { Tok BOOL _ }
+       true        { Tok TRUE _ }
+       false       { Tok FALSE _ }
+       string      { Tok STRING _ }
+       namespace   { Tok NAMESPACE _ }
+       include     { Tok INCLUDE _ }
+       hs_include  { Tok HS_INCLUDE _ }
+       cpp_include { Tok CPP_INCLUDE _ }
+       hash_map    { Tok HASH_MAP _ }
+       hash_set    { Tok HASH_SET _ }
+       intTok      { Tok INTEGRAL{} _ }
+       doubleTok   { Tok FLOATING{} _ }
+       stringTok   { Tok STRING_LIT{} _ }
+       symTok      { Tok SYMBOL{} _ }
+       '{'         { Tok L_CURLY_BRACE _ }
+       '}'         { Tok R_CURLY_BRACE _ }
+       '['         { Tok L_SQUARE_BRACE _ }
+       ']'         { Tok R_SQUARE_BRACE _ }
+       '<'         { Tok L_ANGLE_BRACE _ }
+       '>'         { Tok R_ANGLE_BRACE _ }
+       '('         { Tok L_PAREN _ }
+       ')'         { Tok R_PAREN _ }
+       ','         { Tok COMMA _ }
+       ';'         { Tok SEMICOLON _ }
+       ':'         { Tok COLON _ }
+       '='         { Tok EQUALS _ }
+       '@'         { Tok AT _ }
+       -- Tokens for unused syntax
+       package     { Tok PACKAGE _ }
+       binary      { Tok BINARY _ }
+       senum       { Tok SENUM _ }
+       stream      { Tok STREAM _ }
+       interaction { Tok INTERACTION _ }
+       void        { Tok VOID _ }
+       union       { Tok UNION _ }
+       view        { Tok VIEW _ }
+       exception   { Tok EXCEPTION _ }
+       service     { Tok SERVICE _ }
+       oneway      { Tok ONEWAY _ }
+       extends     { Tok EXTENDS _ }
+       performs    { Tok PERFORMS _ }
+       throws      { Tok THROWS _ }
+       safe        { Tok SAFE _ }
+       transient   { Tok TRANSIENT _ }
+       stateful    { Tok STATEFUL _ }
+       permanent   { Tok PERMANENT _ }
+       server      { Tok SERVER _ }
+       client      { Tok CLIENT _ }
+       readonly    { Tok READONLY _ }
+       idempotent { Tok IDEMPOTENT _ }
+
+-- Shift/reduce conflicts
+-- - UntypedConst needs to parse both an identifier and a struct which begins with an identifier
+%expect 1
+-- - "oneway" can be both a function qualifier and an identifier, so "oneway fn_return_type"
+--   is ambiguous - we want to always treat it as a qualifier if possible though. Ditto the
+--   idempotency keywords.
+%right SKIP_ONEWAY oneway
+%right SKIP_IDEMPOTENCY readonly idempotent
+
+%%
+Thrift :: { [ParsedStatement] }
+Thrift : list(Statement) { catMaybes $1 }
+
+Statement :: { Maybe ParsedStatement }
+  : Header { fmap StatementHeader $1 }
+  | Decl { fmap StatementDecl $1 }
+
+Header :: { Maybe (Parsed Header) }
+  : Include stringLit
+    { Just HInclude
+      { incPath = Text.unpack (lParsed $2)
+      , incType = lVal $1
+      , incKeywordLoc = lLoc $1
+      , incPathLoc    = lLoc $2
+      , incQuoteType  = lRep $2
+      }
+    }
+  | namespace Symbol SymbolOrString
+    { Just HNamespace
+      { nmLang = lVal $2
+      , nmName = lParsed $3
+      , nmKeywordLoc = getLoc $1
+      , nmLangLoc    = lLoc $2
+      , nmNameLoc    = lLoc $3
+      , nmQuoteType  = lRep $3
+      }
+    }
+  | StructuredAnnotations package stringLit
+    { Just HPackage
+      { pkgUri = lParsed $3
+      , pkgKeywordLoc = getLoc $2
+      , pkgUriLoc     = lLoc $3
+      , pkgQuoteType  = lRep $3
+      , pkgSAnns      = $1
+      }
+    }
+
+Include
+  : include     { L (getLoc $1) Include }
+  | hs_include  { L (getLoc $1) HsInclude }
+  | cpp_include { L (getLoc $1) CppInclude }
+
+SymbolOrString
+  : stringLit { fmap (second Just) $1 }
+  | Symbol    { fmap (,Nothing) $1 }
+
+Decl :: { Maybe (Parsed Decl) }
+  : Struct  { Just $ D_Struct $1 }
+  | Union   { Just $ D_Union $1 }
+  | Typedef { Just $ D_Typedef $1 }
+  | Enum    { Just $ D_Enum $1 }
+  | Const   { Just $ D_Const $1 }
+  | Service { Just $ D_Service $1 }
+  | Interaction { Just $ D_Interaction $1 }
+  | UnusedDecl { Nothing }
+
+-- Structs ---------------------------------------------------------------------
+
+Struct :: { Parsed Struct }
+Struct
+  : StructuredAnnotations ErrorClassifications StructType Symbol '{' list(Field) '}' Annotations
+    { Struct
+      { structName         = lVal $4
+      , structResolvedName = ()
+      , structType         = lVal $3
+      , structMembers      = filterHiddenFields $6
+      , structLoc          = StructLoc
+        { slKeyword    = lLoc $3
+        , slName       = lLoc $4
+        , slOpenBrace  = getLoc $5
+        , slCloseBrace = getLoc $7
+        }
+      , structAnns           = $8
+      , structSAnns          = $1
+      , errorClassifications = $2
+      }
+    }
+
+StructType
+  : struct    { L (getLoc $1) StructTy }
+  | exception { L (getLoc $1) ExceptionTy }
+
+Field :: { Parsed (Field 'StructField) }
+Field : StructuredAnnotations intLit ':' Req AnnotatedType Symbol MaybeConst Annotations Separator
+        { case $5 of
+            Some t -> Field
+              { fieldId           = fromIntegral $ lParsed $2
+              , fieldName         = lVal $6
+              , fieldResolvedName = ()
+              , fieldType         = t
+              , fieldResolvedType = ()
+              , fieldVal          = fmap lVal $7
+              , fieldResolvedVal  = ()
+              , fieldRequiredness = $4
+              , fieldLaziness     = Lazy
+              , fieldTag          = STRUCT_FIELD
+              , fieldLoc          = FieldLoc
+                { flId        = lLoc $2
+                , flIdRep     = lRep $2
+                , flColon     = getLoc $3
+                , flName      = lLoc $6
+                , flEqual     = fmap lLoc $7
+                , flSeparator = $9
+                }
+              , fieldAnns         = $8
+              , fieldSAnns        = $1
+              }
+        }
+
+Req :: { Requiredness 'StructField Loc }
+Req : {- empty -}    { Default }
+    | optional       { Optional $ getLoc $1 }
+    | required       { Required $ getLoc $1 }
+
+MaybeConst : {- empty -}      { Nothing }
+           | '=' UntypedConst { Just $ L (getLoc $1) $2 }
+
+ErrorClassifications : list(ErrorClassification) { $1 }
+
+ErrorClassification
+  : ErrorClassificationKeyword
+    { ErrorClassification
+      { ecType = lVal $1
+      , ecKeywordLoc = lLoc $1
+      }
+    }
+
+ErrorClassificationKeyword
+  : safe       { L (getLoc $1) EcSafe }
+  | transient  { L (getLoc $1) EcTransient }
+  | stateful   { L (getLoc $1) EcStateful }
+  | permanent  { L (getLoc $1) EcPermanent }
+  | server     { L (getLoc $1) EcServer }
+  | client     { L (getLoc $1) EcClient }
+
+-- Unions ----------------------------------------------------------------------
+
+Union :: { Parsed Union }
+Union
+  : StructuredAnnotations union Symbol '{' list(UnionAlt) '}' Annotations
+    { Union
+      { unionName         = lVal $3
+      , unionResolvedName = ()
+      , unionAlts         = $5
+      , unionEmptyName    = ()
+      , unionHasEmpty     = HasEmpty
+      , unionLoc          = StructLoc
+        { slKeyword    = getLoc $2
+        , slName       = lLoc $3
+        , slOpenBrace  = getLoc $4
+        , slCloseBrace = getLoc $6
+        }
+      , unionAnns         = $7
+      , unionSAnns        = $1
+      }
+    }
+
+UnionAlt :: { Parsed UnionAlt }
+UnionAlt
+  : StructuredAnnotations intLit ':' AnnotatedType Symbol MaybeConst Annotations Separator
+    { case $4 of
+        Some t -> UnionAlt
+          { altId           = fromIntegral $ lParsed $2
+          , altName         = lVal $5
+          , altResolvedName = ()
+          , altType         = t
+          , altResolvedType = ()
+          , altLoc          = FieldLoc
+            { flId        = lLoc $2
+            , flIdRep     = lRep $2
+            , flColon     = getLoc $3
+            , flName      = lLoc $5
+            , flEqual     = fmap lLoc $6
+            , flSeparator = $8
+            }
+          , altAnns         = $7
+          , altSAnns        = $1
+          }
+    }
+
+-- Typedefs --------------------------------------------------------------------
+
+Typedef :: { Parsed Typedef }
+Typedef : StructuredAnnotations typedef AnnotatedType Symbol Annotations
+          { case $3 of
+              Some t -> Typedef
+                { tdName         = lVal $4
+                , tdResolvedName = ()
+                , tdTag          = IsTypedef
+                , tdType         = t
+                , tdResolvedType = ()
+                , tdLoc          = TypedefLoc
+                  { tdlKeyword = getLoc $2
+                  , tdlName    = lLoc $4
+                  }
+                , tdAnns         = $5
+                , tdSAnns        = $1
+                }
+          }
+
+-- Annotations -----------------------------------------------------------------
+
+Annotations :: { Maybe (Annotations Loc) }
+Annotations
+  : '(' list(Annotation) ')'
+     { Just Annotations
+       { annList = $2
+       , annOpenParen  = getLoc $1
+       , annCloseParen = getLoc $3
+       }
+     }
+  | {- empty -} { Nothing }
+
+Annotation :: { Annotation Loc }
+Annotation
+  : Symbol Separator
+    { SimpleAnn
+      { saTag = lVal $1
+      , saLoc = lLoc $1
+      , saSep = $2
+      }
+    }
+  | Symbol '=' AnnValue Separator
+    { ValueAnn
+      { vaTag = lVal $1
+      , vaVal = lVal $3
+      , vaTagLoc = lLoc $1
+      , vaEqual  = getLoc $2
+      , vaValLoc = lLoc $3
+      , vaSep    = $4
+      }
+    }
+
+AnnValue
+  : intLit    { fmap (uncurry IntAnn) $1 }
+  | stringLit { fmap (uncurry TextAnn) $1 }
+
+StructuredAnnotations : list(StructuredAnnotation) { $1 }
+
+StructuredAnnotation
+  : '@' Symbol
+    { StructuredAnn
+      { saAt = getLoc $1
+      , saType = lVal $2
+      , saTypeLoc = Arity0Loc $ lLoc $2
+      , saMaybeElems = Nothing
+      }
+    }
+  | '@' Symbol '{' list(StructElem) '}'
+    { StructuredAnn
+      { saAt = getLoc $1
+      , saType = lVal $2
+      , saTypeLoc = Arity0Loc $ lLoc $2
+      , saMaybeElems = Just $ StructuredAnnElems
+        { saOpenBrace = getLoc $3
+        , saElems = $4
+        , saCloseBrace = getLoc $5
+        }
+      }
+    }
+
+-- Constants -------------------------------------------------------------------
+
+Const :: { Parsed Const }
+Const : StructuredAnnotations const AnnotatedType Symbol '=' UntypedConst Separator
+        { case $3 of
+            Some ty -> Const
+              { constName         = lVal $4
+              , constResolvedName = ()
+              , constType         = ty
+              , constResolvedType = ()
+              , constVal          = $6
+              , constResolvedVal  = ()
+              , constLoc          = ConstLoc
+                { clKeyword   = getLoc $2
+                , clName      = lLoc $4
+                , clEqual     = getLoc $5
+                , clSeparator = $7
+                }
+              , constSAnns = $1
+              }
+        }
+
+UntypedConst :: { UntypedConst Loc }
+UntypedConst
+  : intLit     { UntypedConst (lLoc $1) (uncurry IntConst $ lVal $1) }
+  | doubleLit  { UntypedConst (lLoc $1) (uncurry DoubleConst $ lVal $1) }
+  | stringLit  { UntypedConst (lLoc $1) (uncurry StringConst $ lVal $1) }
+  | true       { UntypedConst (getLoc $1) (BoolConst True) }
+  | false      { UntypedConst (getLoc $1) (BoolConst False) }
+  | Symbol     { UntypedConst (lLoc $1) (IdConst $ lVal $1) }
+  | '[' list(ListElem) ']'
+    { UntypedConst
+      { ucLoc   = getLoc $1
+      , ucConst = ListConst
+        { lvElems = $2
+        , lvCloseBrace = getLoc $3
+        }
+      }
+    }
+  | '{' list(MapElem) '}'
+    { UntypedConst
+      { ucLoc   = getLoc $1
+      , ucConst = MapConst
+        { mvElems = $2
+        , mvCloseBrace = getLoc $3
+        }
+      }
+    }
+  | Symbol '{' list(StructElem) '}'
+    { UntypedConst
+      { ucLoc   = lLoc $1
+      , ucConst = StructConst
+        { svType = lVal $1
+        , svOpenBrace = getLoc $2
+        , svElems = $3
+        , svCloseBrace = getLoc $4
+        }
+      }
+    }
+ListElem : UntypedConst Separator { ListElem $1 $2 }
+
+MapElem : UntypedConst ':' UntypedConst Separator
+          { ListElem (MapPair $1 (getLoc $2) $3) $4 }
+
+StructElem : Symbol '=' UntypedConst Separator
+             { ListElem (StructPair (lVal $1) (lLoc $1) (getLoc $2) $3) $4 }
+
+-- Enum Values -----------------------------------------------------------------
+
+Enum :: { Parsed Enum }
+Enum : StructuredAnnotations enum Symbol '{' list(EnumVal) '}' Annotations
+       { Enum
+         { enumName         = lVal $3
+         , enumResolvedName = ()
+         , enumFlavour      = ()
+         , enumConstants    = $5
+         , enumLoc          = StructLoc
+           { slKeyword    = getLoc $2
+           , slName       = lLoc $3
+           , slOpenBrace  = getLoc $4
+           , slCloseBrace = getLoc $6
+           }
+         , enumAnns = $7
+         , enumSAnns = $1
+         }
+       }
+
+EnumVal :: { Parsed EnumValue }
+EnumVal : StructuredAnnotations Symbol '=' intLit Annotations Separator
+          { EnumValue
+            { evName         = lVal $2
+            , evResolvedName = ()
+            , evValue        = fromIntegral $ lParsed $4
+            , evLoc          = EnumValLoc
+              { evlName      = lLoc $2
+              , evlEqual     = getLoc $3
+              , evlValue     = lLoc $4
+              , evlRep       = lRep $4
+              , evlSeparator = $6
+              }
+            , evAnns = $5
+            , evSAnns = $1
+            }
+          }
+
+-- Services --------------------------------------------------------------------
+
+Service :: { Parsed Service }
+Service
+  : StructuredAnnotations service Symbol Extends '{' list(ServiceStmt) '}' Annotations
+     { Service
+       { serviceName         = lVal $3
+       , serviceResolvedName = ()
+       , serviceSuper        = $4
+       , serviceStmts        = $6
+       , serviceLoc          = StructLoc
+         { slKeyword    = getLoc $2
+         , slName       = lLoc $3
+         , slOpenBrace  = getLoc $5
+         , slCloseBrace = getLoc $7
+         }
+       , serviceAnns         = $8
+       , serviceSAnns        = $1
+       }
+     }
+
+ServiceStmt :: { Parsed ServiceStmt }
+  : Function
+    { FunctionStmt $1
+    }
+  | performs Symbol Separator
+    { PerformsStmt
+      ( Performs
+        { performsName = lVal $2
+        }
+      )
+    }
+
+Function :: { Parsed Function }
+  : StructuredAnnotations IsOneway RpcIdempotency FunType Symbol '(' list(Argument) ')' Throws Annotations Separator
+    { Function
+      { funName          = lVal $5
+      , funResolvedName  = ()
+      , funType          = $4
+      , funResolvedType  = ()
+      , funArgs          = $7
+      , funExceptions    = maybe [] throwsFields $9
+      , funIsOneWay      = isJust $2
+      , funIdempotency   = fmap lVal $3
+      , funPriority      = NormalPriority
+      , funLoc           = FunLoc
+        { fnlOneway      = $2
+        , fnlIdempotency = fmap lLoc $3
+        , fnlName        = lLoc $5
+        , fnlOpenParen   = getLoc $6
+        , fnlCloseParen  = getLoc $8
+        , fnlThrows      = fmap throwsLoc $9
+        , fnlSeparator   = $11
+        }
+      , funAnns         = $10
+      , funSAnns        = $1
+      }
+    }
+
+Argument :: { Parsed (Field 'Argument) }
+Argument : StructuredAnnotations intLit ':' AnnotatedType Symbol MaybeConst Annotations Separator
+  { case $4 of
+     Some t -> Field
+       { fieldId           = fromIntegral $ lParsed $2
+       , fieldName         = lVal $5
+       , fieldResolvedName = ()
+       , fieldType         = t
+       , fieldResolvedType = ()
+       , fieldVal          = fmap lVal $6
+       , fieldResolvedVal  = ()
+       , fieldRequiredness = Default
+       , fieldLaziness     = Lazy
+       , fieldTag          = ARGUMENT
+       , fieldLoc          = FieldLoc
+         { flId        = lLoc $2
+         , flIdRep     = lRep $2
+         , flColon     = getLoc $3
+         , flName      = lLoc $5
+         , flEqual     = fmap lLoc $6
+         , flSeparator = $8
+         }
+       , fieldAnns         = $7
+       , fieldSAnns        = $1
+       }
+  }
+
+Extends
+  : extends Symbol
+    { Just Super
+        { supName         = lVal $2
+        , supResolvedName = ()
+        , supExtends      = getLoc $1
+        , supLoc          = lLoc $2
+        }
+    }
+  | {- nothing -}  { Nothing }
+
+IsOneway
+  : oneway      { Just $ getLoc $1  }
+  | {- empty -} %prec SKIP_ONEWAY { Nothing }
+
+RpcIdempotency
+  : RpcIdempotencyKeyword { Just $ L (lLoc $1) (RpcIdempotency (lVal $1)) }
+  | {- empty -} %prec SKIP_IDEMPOTENCY { Nothing }
+
+RpcIdempotencyKeyword
+  : readonly   { L (getLoc $1) RiReadonly }
+  | idempotent { L (getLoc $1) RiIdempotent }
+
+Throws :: { Maybe (Parsed Throws) }
+Throws
+  : throws '(' list(Throw) ')'
+    { Just $ Throws
+      { throwsLoc = ThrowsLoc
+          { tlThrows     = getLoc $1
+          , tlOpenParen  = getLoc $2
+          , tlCloseParen = getLoc $4
+          }
+      , throwsFields = $3
+      }
+    }
+  | {- empty -} { Nothing }
+
+FunType
+  : AnnotatedType { FunType $1 }
+  | void { FunTypeVoid $ getLoc $1 }
+  | ResponseAndStreamReturnType { FunTypeResponseAndStreamReturn $1 }
+
+ResponseAndStreamReturnType
+  : stream '<' AnnotatedType Throws '>'
+    { case $3 of
+        Some t -> ResponseAndStreamReturn
+          { rsReturn = Nothing
+          , rsComma = Nothing
+          , rsStream = (Stream t $4 (annTy1 $1 $2 $5))
+          }
+    }
+  | AnnotatedType ',' stream '<' AnnotatedType Throws '>'
+    { case ($1, $5) of
+        (Some tRet, Some tStream) -> ResponseAndStreamReturn
+          { rsReturn = Just tRet
+          , rsComma = Just $ getLoc $2
+          , rsStream = (Stream tStream $6 (annTy1 $3 $4 $7))
+          }
+    }
+
+Throw :: { Parsed (Field 'ThrowsField) }
+Throw : StructuredAnnotations intLit ':' AnnotatedType Symbol MaybeConst Annotations Separator
+        { case $4 of
+            Some t -> Field
+              { fieldId           = fromIntegral $ lParsed $2
+              , fieldName         = lVal $5
+              , fieldResolvedName = ()
+              , fieldType         = t
+              , fieldResolvedType = ()
+              , fieldVal          = fmap lVal $6
+              , fieldResolvedVal  = ()
+              , fieldRequiredness = Default
+              , fieldLaziness     = Lazy
+              , fieldTag          = THROWS_UNRESOLVED
+              , fieldLoc          = FieldLoc
+                { flId        = lLoc $2
+                , flIdRep     = lRep $2
+                , flColon     = getLoc $3
+                , flName      = lLoc $5
+                , flEqual     = fmap lLoc $6
+                , flSeparator = $8
+                }
+              , fieldAnns         = $7
+              , fieldSAnns        = $1
+              }
+        }
+
+
+-- Unused Stuff ----------------------------------------------------------------
+
+-- We don't use any of this syntax at the moment, but we need to be aware of it
+-- for compatibility
+
+UnusedDecl
+  : view Symbol ':' Symbol '{' list(ViewField) '}' Annotations  {}
+  | senum Symbol '{' list(stringLit) '}'                        {}
+
+ViewField
+  : Symbol Annotations                              {}
+  | intLit ':' Req AnnotatedType Symbol Annotations {}
+
+-- Interactions --------------------------------------------------------------------
+
+Interaction :: { Parsed Interaction }
+Interaction
+  : StructuredAnnotations interaction Symbol Extends '{' list(Function) '}' Annotations
+     { Interaction
+       { interactionName         = lVal $3
+       , interactionResolvedName = ()
+       , interactionSuper        = $4
+       , interactionFunctions    = $6
+       , interactionLoc          = StructLoc
+         { slKeyword    = getLoc $2
+         , slName       = lLoc $3
+         , slOpenBrace  = getLoc $5
+         , slCloseBrace = getLoc $7
+         }
+       , interactionAnns         = $8
+       , interactionSAnns        = $1
+       }
+     }
+
+
+-- Other------------------------------------------------------------------------
+
+list(p) : revlist(p) { reverse $1 }
+
+revlist(p) : revlist(p) p { $2 : $1 }
+           | {- empty -}  { [] }
+
+Symbol :: { L Text }
+  : symTok
+    {% case $1 of
+        Tok (SYMBOL s) loc -> return $ L loc $ Text.pack s
+        _ -> parseError $1
+    }
+  -- view isn't actually a keyword according to the fbthrift lexer
+  -- even though it probably should be
+  | view { L (getLoc $1) "view" }
+  -- other "keywords" allowed in identifiers:
+  | oneway      { L (getLoc $1) "oneway" }
+  | safe        { L (getLoc $1) "safe" }
+  | transient   { L (getLoc $1) "transient" }
+  | stateful    { L (getLoc $1) "stateful" }
+  | permanent   { L (getLoc $1) "permanent" }
+  | server      { L (getLoc $1) "server" }
+  | client      { L (getLoc $1) "client" }
+  | readonly    { L (getLoc $1) "readonly" }
+  | idempotent  { L (getLoc $1) "idempotent" }
+  | package     { L (getLoc $1) "package" }
+
+stringLit : stringTok
+  {% case $1 of
+       Tok (STRING_LIT s qt) loc -> return $ L loc (Text.pack s, qt)
+       _ -> parseError $1
+  }
+
+intLit : intTok
+  {% case $1 of
+       Tok (INTEGRAL x s) loc -> return $ L loc (x, s)
+       _ -> parseError $1
+  }
+
+doubleLit : doubleTok
+  {% case $1 of
+       Tok (FLOATING x s) loc -> return $ L loc (x, s)
+       _ -> parseError $1
+  }
+
+Separator :: { Separator Loc }
+  : ',' { Comma     $ getLoc $1 }
+  | ';' { Semicolon $ getLoc $1 }
+  |     { NoSep }
+
+AnnotatedType :: { Some (AnnotatedType Loc) }
+AnnotatedType : Type Annotations
+                { case $1 of
+                    ThisAnnTy ty loc -> Some $ AnnotatedType ty $2 loc
+                }
+
+Type :: { SomeAnnTy 'Unresolved () }
+Type : byte   { ThisAnnTy I8 (annTy0 $1) }
+     | i16    { ThisAnnTy I16 (annTy0 $1) }
+     | i32    { ThisAnnTy I32 (annTy0 $1) }
+     | i64    { ThisAnnTy I64 (annTy0 $1) }
+     | double { ThisAnnTy TDouble (annTy0 $1) }
+     | float  { ThisAnnTy TFloat (annTy0 $1) }
+     | string { ThisAnnTy TText (annTy0 $1) }
+     | binary { ThisAnnTy TBytes (annTy0 $1) }
+     | bool   { ThisAnnTy TBool (annTy0 $1) }
+     | Symbol { ThisAnnTy (TNamed (lVal $1)) (Arity0Loc (lLoc $1)) }
+     | map '<' AnnotatedType ',' AnnotatedType '>'
+       { case ($3, $5) of
+           (Some k, Some v) -> ThisAnnTy (TMap k v) (annTy2 $1 $2 $4 $6)
+       }
+     | hash_map '<' AnnotatedType ',' AnnotatedType '>'
+       { case ($3, $5) of
+           (Some k, Some v) -> ThisAnnTy (THashMap k v) (annTy2 $1 $2 $4 $6)
+       }
+     | set '<' AnnotatedType '>'
+       { case $3 of
+           Some t -> ThisAnnTy (TSet t) (annTy1 $1 $2 $4)
+       }
+     | hash_set '<' AnnotatedType '>'
+       { case $3 of
+           Some t -> ThisAnnTy (THashSet t) (annTy1 $1 $2 $4)
+       }
+     | list '<' AnnotatedType '>'
+       { case $3 of
+           Some t -> ThisAnnTy (TList t) (annTy1 $1 $2 $4) }
+
+{
+
+-- Result Types ----------------------------------------------------------------
+
+data ThriftFile a l = ThriftFile
+  { thriftName    :: Text
+  , thriftPath    :: FilePath
+  , thriftHeaders :: [Header 'Unresolved () l]
+  , thriftDecls   :: [Decl 'Unresolved () l]
+  , thriftSplice  :: a
+  , thriftComments :: [Comment l]
+  }
+
+-- Parser Monad ----------------------------------------------------------------
+
+type Parser = Alex
+
+data L a = L { lLoc :: Located Loc, lVal :: a }
+
+instance Functor L where
+  fmap f (L loc val) = L loc $ f val
+
+lParsed :: L (a, b) -> a
+lParsed = fst . lVal
+
+lRep :: L (a, b) -> b
+lRep = snd . lVal
+
+getLoc :: Token -> Located Loc
+getLoc (Tok _ loc) = loc
+
+runParser :: Parser a -> FilePath -> String -> Either String a
+runParser parser file input = fst <$> runFullParser parser file input
+
+runFullParser
+  :: Parser a -> FilePath -> String -> Either String (a, [Comment Loc])
+runFullParser parser file input =
+  runAlex input $ setFilename file >> (,) <$> parser <*> getComments
+
+parseError :: Token -> Parser a
+parseError (Tok _ Located{lLocation=Loc{..}}) =
+  alexError $ concat
+    [locFile, ":", show locStartLine, ":", show locStartCol, ": parse error"]
+
+bind :: Parser a -> (a -> Parser b) -> Parser b
+bind = (>>=)
+
+lexWrap :: (Token -> Parser a) -> Parser a
+lexWrap k = alexMonadScan >>= k
+
+parseThrift :: Parser ([Parsed Header], [Parsed Decl])
+parseThrift = do
+  statements <- parseStatements
+  splitStatements [] [] statements
+  where
+    splitStatements
+      :: [Parsed Header]
+      -> [Parsed Decl]
+      -> [ParsedStatement]
+      -> Parser ([Parsed Header], [Parsed Decl])
+    splitStatements headers [] (StatementHeader header : statements) =
+      splitStatements (header:headers) [] statements
+    splitStatements _ decl (StatementHeader header : _) =
+      alexError $ concat
+        [locFile, ":", show locStartLine, ":", show locStartCol, ": unexpected header"]
+      where
+        Located{lLocation=Loc{..}} = case header of
+          HInclude{incKeywordLoc=incKeywordLoc} -> incKeywordLoc
+          HNamespace{nmKeywordLoc=nmKeywordLoc} -> nmKeywordLoc
+          HPackage{pkgKeywordLoc=pkgKeywordLoc} -> pkgKeywordLoc
+    splitStatements headers decls (StatementDecl decl : statements) =
+      splitStatements headers (decl:decls) statements
+    splitStatements headers decls [] =
+      pure ((reverse headers), (reverse decls))
+
+
+parseString :: FilePath -> String -> Either String (ThriftFile () Loc)
+parseString file string = do
+  ((headers, decls), comments) <- runFullParser parseThrift file string
+  pure $ mkThriftFile (headers, decls, comments)
+
+  where
+    mkThriftFile (headers, decls, comments) =
+      ThriftFile
+      { thriftName    = getModuleName file
+      , thriftPath    = file
+      , thriftHeaders = headers
+      , thriftDecls   = decls
+      , thriftSplice  = ()
+      , thriftComments = comments
+      }
+
+parse :: FilePath -> FilePath -> IO (Either String (ThriftFile () Loc))
+parse baseDir file = parseString file <$> readFile (baseDir </> file)
+
+getModuleName :: FilePath -> Text
+getModuleName file =
+  fst . Text.breakOn "." .
+  snd . Text.breakOnEnd "/" .
+  Text.pack $ file
+
+annTy0 :: Token -> TypeLoc 0 Loc
+annTy0 tok = Arity0Loc $ getLoc tok
+
+annTy1 :: Token -> Token -> Token -> TypeLoc 1 Loc
+annTy1 tok open close = Arity1Loc
+  { a1Ty         = getLoc tok
+  , a1OpenBrace  = getLoc open
+  , a1CloseBrace = getLoc close
+  }
+
+annTy2 :: Token -> Token -> Token -> Token -> TypeLoc 2 Loc
+annTy2 tok open comma close = Arity2Loc
+  { a2Ty         = getLoc tok
+  , a2OpenBrace  = getLoc open
+  , a2Comma      = getLoc comma
+  , a2CloseBrace = getLoc close
+  }
+}
diff --git a/Thrift/Compiler/Plugin.hs b/Thrift/Compiler/Plugin.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Plugin.hs
@@ -0,0 +1,294 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE TypeOperators #-}
+module Thrift.Compiler.Plugin
+  ( Typecheckable(..), SomeLit(..)
+  , qualify, qualifyType
+  , getPrefix
+  , lowercase, uppercase, toCamel
+  , fixLeadingUnderscore
+  , toConstructorName
+  , getNamespace
+  , isNewtype
+  , filterHsAnns, getTypeAnns
+  ) where
+
+import Data.Bifunctor
+import Data.List
+import qualified Data.Map.Strict as Map
+import Data.Maybe
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Data.Type.Equality
+import Prelude hiding (Enum)
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Typechecker.Monad
+import Thrift.Compiler.Types
+
+data SomeLit l = forall t. ThisLit (Type l t) t
+
+-- | Typeclass to define Thrift typecheckable Languages. There are several
+-- sections of functions to define here, although many have default
+-- implementations
+class Monoid (Interface l) => Typecheckable l  where
+  -- | Interface that gets generated by the Thrift compiler. This includes all
+  -- the symbols exported by the generated code in the target language. It is
+  -- used in order to add additional required symbols that get referenced in
+  -- splice (hs_include) files. If your language does not support splice files,
+  -- then set Interface l = ()
+  type Interface l
+
+  -- * Annotation Processing
+
+  -- | Given a resolved Thrift type and a list of annotations, produce some new
+  -- transformed type. This is how TSpecial types get generated
+  resolveTypeAnnotations
+    :: Type l t
+    -> [Annotation Loc]
+    -> TC l (Some (Type l))
+  resolveTypeAnnotations ty _ = pure $ Some ty
+
+  -- | Recursively qualify all of the named types in a SpecialType so that they
+  -- can be properly identified in imports
+  qualifySpecialType :: (Text, Text) -> SpecialType l t -> SpecialType l t
+
+  -- * Typechecking
+
+  -- | Typecheck literals of special, language specific types
+  -- Note: this is *only* for literals, named constants are typechecked by the
+  -- main typecheckConst function (even for special types)
+  typecheckSpecialConst
+    :: SpecialType l t
+    -> UntypedConst Loc
+    -> TC l (TypedConst l t)
+
+  -- | Type equality for special types
+  eqSpecial :: SpecialType l u -> SpecialType l v -> Maybe (u :~: v)
+
+  -- | Generate an interface. See the Interface type family for more info on how
+  -- this is used.
+  getInterface :: Options l -> ThriftFile a Loc -> Interface l
+  getInterface _ _ = mempty
+
+  -- | Get extra Thrift symbols that are referenced in splice files
+  getExtraSymbols ::
+    Options l -> Interface l -> ThriftFile SpliceFile b -> [Text]
+  getExtraSymbols _ _ _ = []
+
+  -- * Renamers
+
+  -- | Rename the thrift module, probably taking namespace into account
+  renameModule :: Options l -> ThriftFile a b -> Text
+  renameModule _ ThriftFile{..} = thriftName
+
+  renameStruct :: Options l -> Struct s u a -> Text
+  renameStruct _ Struct{..} = structName
+
+  renameField
+    :: Options l
+    -> [Annotation a]
+    -> Text
+    -> Field u s m a
+    -> Text
+  renameField _ _ _ Field{..} = fieldName
+
+  renameConst :: Options l -> Text -> Text
+  renameConst _ = id
+
+  renameService :: Options l -> Service s u a -> Text
+  renameService _ Service{..} = serviceName
+
+  renameFunction :: Options l -> Function s u a -> Text
+  renameFunction _ Function{..} = funName
+
+  renameTypedef :: Options l -> Typedef s u a -> Text
+  renameTypedef _ Typedef{..} = tdName
+
+  renameEnum :: Options l -> Enum s u a -> Text
+  renameEnum _ Enum{..} = enumName
+
+  renameEnumAlt :: Options l -> Enum s u a -> Text -> Text
+  renameEnumAlt _ _ name = name
+
+  renameUnion :: Options l -> Union s u a -> Text
+  renameUnion _ Union{..} = unionName
+
+  renameUnionAlt :: Options l -> Union s u a -> UnionAlt s u a -> Text
+  renameUnionAlt _ _ UnionAlt{..} = altName
+
+  getUnionEmptyName :: Options l -> Union s u a -> Text
+  getUnionEmptyName _ Union{..} = unionName <> "_EMPTY"
+
+  -- * Uniqueness options specify whether various renamed symbols need to be
+  -- globally unique to the entire Thrift (if False, they are still unique
+  -- within their structure)
+
+  -- | Are field names globally unique? If yes, then we will report renamed
+  -- field name collisions across structs
+  fieldsAreUnique :: Options l -> Bool
+  fieldsAreUnique _ = False
+
+  -- | Are union alternatives unique?
+  unionAltsAreUnique :: Options l -> Bool
+  unionAltsAreUnique _ = False
+
+  -- | Are enum values unique?
+  enumAltsAreUnique :: Options l -> Bool
+  enumAltsAreUnique _ = False
+
+  -- | Get enum flavour from annotation tags
+  enumFlavourTag :: Options l -> Enum s u a -> EnumFlavour
+  enumFlavourTag _ _ = SumTypeEnum False
+
+  -- * Back translators
+  -- Translate Stuff Back to regular thrift for pretty printing and JSON output
+
+  -- | Translate a special type back to its underlying Thrift type, and its
+  -- special name in the target language.
+  -- Note that this should be a shallow conversion. Do not backtranslate
+  -- recursively
+  backTranslateType :: SpecialType l t -> (Some (Type l), Text)
+
+  -- | Translate a literal to its underlying thrift type and representation.
+  -- Like @backTranslateType@, the conversion should be shallow
+  backTranslateLiteral :: SpecialType l t -> t -> SomeLit l
+
+-- Env Qualifier ---------------------------------------------------------------
+
+-- | Qualify all the named types in an Env
+qualify :: Typecheckable l => (Text, Text) -> Env l -> Env l
+qualify m env = env
+  { typeMap  = qualCtx qualST (typeMap env)
+  , schemaMap = qualSchemas (schemaMap env)
+  , unionMap = qualSchemas (unionMap env)
+  , constMap = qualCtx qualC (constMap env)
+  , enumMap  = qualEnums (enumMap env)
+  , serviceMap = qualServices (serviceMap env)
+  }
+  where
+    qualCtx
+      :: (a -> a)
+      -> Context a
+      -> Context a
+    qualCtx f ctx@Context{..} = ctx { cMap = Map.map f cMap }
+    qualST :: Typecheckable l => Some (Type l) -> Some (Type l)
+    qualST (Some ty) = Some $ qualifyType m ty
+    qualC :: Typecheckable l => (Some (Type l), Name, Loc)
+                             -> (Some (Type l), Name, Loc)
+    qualC (st, n, loc) = (qualST st, qualName m n, loc)
+    qualSchemas
+      :: Typecheckable l
+      => Map.Map Text (Some (SCHEMA l t)) -> Map.Map Text (Some (SCHEMA l t))
+    qualSchemas = Map.map $ \(Some schema) -> Some (qualifySchema m schema)
+    qualEnums = Map.map $ \(vs, ns) ->
+      (Map.map (first (qualName m)) vs, Map.map (first (qualName m)) ns)
+    qualServices = Map.map $ \(a, b, c) -> (qualName m a, b, c)
+
+qualifyType :: Typecheckable l => (Text, Text) -> Type l t -> Type l t
+qualifyType _ I8 = I8
+qualifyType _ I16 = I16
+qualifyType _ I32 = I32
+qualifyType _ I64 = I64
+qualifyType _ TFloat = TFloat
+qualifyType _ TDouble = TDouble
+qualifyType _ TBool = TBool
+qualifyType _ TBytes = TBytes
+qualifyType _ TText = TText
+qualifyType m (TSet u)       = TSet $ qualifyType m u
+qualifyType m (THashSet u)   = THashSet $ qualifyType m u
+qualifyType m (TList u)      = TList $ qualifyType m u
+qualifyType m (TMap k v)     = TMap (qualifyType m k) (qualifyType m v)
+qualifyType m (THashMap k v) = THashMap (qualifyType m k) (qualifyType m v)
+qualifyType m (TTypedef name t loc) =
+  TTypedef (qualName m name) (qualifyType m t) loc
+qualifyType m (TStruct name loc)    = TStruct (qualName m name) loc
+qualifyType m (TException name loc) = TException (qualName m name) loc
+qualifyType m (TUnion name loc)     = TUnion (qualName m name) loc
+qualifyType m (TEnum name loc nounknown) =
+  TEnum (qualName m name) loc nounknown
+qualifyType m (TNewtype name t loc) =
+  TNewtype (qualName m name) (qualifyType m t) loc
+qualifyType m (TSpecial ty) = TSpecial $ qualifySpecialType m ty
+
+qualifySchema :: Typecheckable l => (Text, Text) -> SCHEMA l t s -> SCHEMA l t s
+qualifySchema _ SEmpty = SEmpty
+qualifySchema m (SField p n t s) =
+  SField p n (qualifyType m t) (qualifySchema m s)
+qualifySchema m (SReqField p n t s) =
+  SReqField p n (qualifyType m t) (qualifySchema m s)
+qualifySchema m (SOptField p n t s) =
+  SOptField p n (qualifyType m t) (qualifySchema m s)
+
+qualName :: (Text, Text) -> Name -> Name
+qualName (tm, rm) Name{..} = Name
+  { sourceName = qualName_ tm sourceName
+  , resolvedName = qualName_ rm resolvedName
+  }
+
+qualName_ :: Text -> Name_ s -> Name_ s
+qualName_ m (UName n) = QName m n
+qualName_ _ n@QName{} = n
+
+-- Renamer Helpers -------------------------------------------------------------
+
+getPrefix :: [Annotation a] -> Maybe Text
+getPrefix anns = listToMaybe
+  [ pre
+  | ValueAnn{vaVal=TextAnn pre _,..} <- anns
+  , vaTag == "hs.prefix"
+  ]
+
+lowercase :: Text -> Text
+lowercase = uncurry (<>) . first Text.toLower . Text.splitAt 1
+
+uppercase :: Text -> Text
+uppercase = uncurry (<>) . first Text.toUpper . Text.splitAt 1
+
+toCamel :: Text -> Text
+toCamel = Text.concat . map capitalize . Text.splitOn "_"
+  where capitalize = uncurry (<>) . first Text.toUpper . Text.splitAt 1
+
+-- Prepend "TU" for "ThriftUnderscore"
+fixLeadingUnderscore :: Text -> Text
+fixLeadingUnderscore = uncurry (<>) . first fixUnderscore . Text.splitAt 1
+  where
+    fixUnderscore s = if s == "_" then "TU__" else s
+
+toConstructorName :: Text -> Text
+toConstructorName = fixLeadingUnderscore . uppercase
+
+-- | Select the last namespace header
+getNamespace :: Text -> [Header s l a] -> Maybe Text
+getNamespace l = foldl' getNS Nothing
+  where
+    getNS ns HInclude{} = ns
+    getNS ns HPackage{} = ns
+    getNS ns HNamespace{..}
+      | nmLang == l = Just nmName
+      | otherwise   = ns
+
+isNewtype :: [Annotation a] -> Bool
+isNewtype = any isNewtypeAnn
+  where
+    isNewtypeAnn SimpleAnn{..} = saTag == "hs.newtype"
+    isNewtypeAnn _ = False
+
+filterHsAnns :: [Annotation a] -> [Annotation a]
+filterHsAnns = filter $ Text.isPrefixOf "hs." . \case
+  SimpleAnn{..} -> saTag
+  ValueAnn{..}  -> vaTag
+
+getTypeAnns :: Text -> [Annotation a] -> [(Text, Annotation a)]
+getTypeAnns lang anns =
+  [ (ty, a) | a@ValueAnn{vaVal=TextAnn ty _,..} <- anns, vaTag == typeTag ]
+  where
+    typeTag = lang <> ".type"
diff --git a/Thrift/Compiler/Pretty.hs b/Thrift/Compiler/Pretty.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Pretty.hs
@@ -0,0 +1,207 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.Pretty
+  ( renderTypeError
+  , renderTypeErrorPlain
+  , renderType
+  , ppHeader, ppName, ppType, ppText
+  ) where
+
+import Text.PrettyPrint hiding ((<>))
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Plugin
+import Thrift.Compiler.Typechecker.Monad
+import Thrift.Compiler.Types
+
+renderType :: Typecheckable l => Type l t -> String
+renderType = render . ppType
+
+renderTypeError :: Typecheckable l => TypeError l -> String
+renderTypeError = render . ppTypeError
+
+renderTypeErrorPlain :: Typecheckable l => TypeError l -> String
+renderTypeErrorPlain = render . ppTypeErrorPlain
+
+ppTypeError :: Typecheckable l => TypeError l -> Doc
+ppTypeError (TypeError loc msg) = "" $$ hang (ppHeader loc) 1 (ppErrorMsg msg)
+ppTypeError EmptyInput = "" $$ red "Error: no input files specified"
+ppTypeError (CyclicModules ms) =
+  "" $$ hang (red "Error: cycle in modules:") 1
+    (sep (punctuate "," (map (text . thriftPath) ms)))
+
+ppTypeErrorPlain :: Typecheckable l => TypeError l -> Doc
+ppTypeErrorPlain (TypeError loc msg) =
+  ppHeaderPlain loc <+> ppErrorMsg msg
+ppTypeErrorPlain EmptyInput = "Error: no input files specified"
+ppTypeErrorPlain (CyclicModules ms) =
+  "Error: cycle in modules:" <+>
+    sep (punctuate "," (map (text . thriftPath) ms))
+
+ppHeader :: Loc -> Doc
+ppHeader loc = red (ppHeaderPlain loc)
+
+ppHeaderPlain :: Loc -> Doc
+ppHeaderPlain Loc{..} =
+  hcat $ map (<> ":") [ text locFile, int locStartLine, int locStartCol ]
+
+ppErrorMsg :: Typecheckable l => ErrorMsg l -> Doc
+ppErrorMsg (CyclicTypes decls) =
+ "cycle in types:" <+> sep (punctuate "," (foldr getName [] decls))
+    where
+      getName (D_Typedef Typedef{..}) ns = ppText tdName : ns
+      getName (D_Struct Struct{..} )  ns = ppText structName : ns
+      getName (D_Union Union{..})     ns = ppText unionName : ns
+      getName (D_Enum Enum{..})       ns = ppText enumName : ns
+      getName D_Const{}               ns = ns
+      getName D_Service{}             ns = ns
+      getName D_Interaction{}             ns = ns
+ppErrorMsg (CyclicServices ss) =
+  "cycle in service hierarchy:" <+> sep (punctuate "," (map getName ss))
+    where
+      getName Service{..} = quotes $ ppText serviceName
+ppErrorMsg (UnknownType name)  = "unknown type" <+> quotes (ppName_ name)
+ppErrorMsg (UnknownConst name) = "unknown constant" <+> quotes (ppName_ name)
+ppErrorMsg (UnknownService name) = "unknown service" <+> quotes (ppName_ name)
+ppErrorMsg (UnknownField name) = "unknown field" <+> quotes (ppText name)
+ppErrorMsg (MissingField name) = "missing field" <+> quotes (ppText name)
+ppErrorMsg (InvalidFieldId name fid) =
+  hang "invalid field id:" 1 $
+    "field" <+> quotes (ppText name) <+> "has id" <+> quotes (int fid) $$
+    "field ids must be unique and non-zero"
+ppErrorMsg (InvalidField val)  =
+  hang "invalid field name:" 1 $
+    "struct fields must be string literals" $$
+    "got" <+> quotes (ppConst val)
+ppErrorMsg (InvalidUnion name n) =
+  hang ("invalid union literal for type" <+> (quotes (ppName name) <> ":")) 1 $
+    "unions must contain exactly 1 field" $$
+    "got" <+> int n <+> "fields"
+ppErrorMsg (EmptyUnion name) =
+  hang ("invalid union declaration" <+> (quotes (ppText name) <> ":")) 1 $
+    "unions must contain at least one alternative" $$
+    "try using an empty enum"
+ppErrorMsg (InvalidThrows ty name) =
+  hang ("invalid throws declaration" <+> (quotes (ppText name) <> ":")) 1 $
+    "all fields in a throws clause must be exceptions" $$
+    "but got type" <+> quotes (ppType ty)
+ppErrorMsg (LiteralMismatch ty val) =
+  hang "type mismatch:" 1 $
+    "expected value of type" <+> quotes (ppType ty) $$
+    "but got" <+> quotes (ppConst val)
+ppErrorMsg (IdentMismatch expect actual name) =
+  hang "type mismatch:" 1 $
+    "expected value of type" <+> quotes (ppType expect) $$
+    "but got identifier" <+> quotes (ppName_ name) <+>
+      "of type" <+> quotes (ppType actual)
+ppErrorMsg (AnnotationMismatch place ann) =
+  hang "annotation mismatch:" 1 $
+    "cannot use annotation" <+> quotes (ppAnnotation ann) $$
+    "in" <+> ppPlacement place
+ppErrorMsg (DuplicateName name) =
+  "multiple definitions of" <+> quotes (ppText name)
+ppErrorMsg (DuplicateEnumVal enum names val) =
+  hang "duplicate enum value" 1 $
+    "enum" <+> quotes (ppText enum) <+>
+      "has multiple constructors with value" <+> quotes (int val) $$
+    "constructors are" <+> hcat (map (quotes . ppText) names)
+ppErrorMsg (TypeMismatch ty1 ty2) =
+    hang "type mismatch:" 1 $
+    "expected type" <+> quotes (ppType ty1) $$
+    "but got type" <+> quotes (ppType ty2)
+ppErrorMsg (NotDefinedBeforeUsed ty) =
+    "type" <+> quotes (ppType ty) <+> "must be defined before it is used"
+ppErrorMsg (UnknownEnumValue name) =
+    "no value found for enum" <+> quotes (ppName_ name)
+ppErrorMsg (MultipleEnumValues name) =
+    "ambiguous values found for enum" <+> quotes (ppName_ name)
+
+red :: Doc -> Doc
+red doc = zeroWidthText "\ESC[31;1m" <> doc <> zeroWidthText "\ESC[0m"
+
+ppPlacement :: Typecheckable l => AnnotationPlacement l -> Doc
+ppPlacement (AnnType ty) = "type" <+> ppType ty
+ppPlacement AnnField = "field"
+ppPlacement AnnStruct = "struct"
+ppPlacement AnnUnion = "union"
+ppPlacement AnnTypedef = "typedef"
+ppPlacement AnnEnum = "enum"
+ppPlacement AnnPriority = "priority"
+
+ppType :: Typecheckable l => Type l t -> Doc
+ppType I8   = "byte"
+ppType I16  = "i16"
+ppType I32  = "i32"
+ppType I64  = "i64"
+ppType TDouble = "double"
+ppType TFloat  = "float"
+ppType TBool   = "bool"
+ppType TText   = "string"
+ppType TBytes  = "binary"
+ppType (TSet u)     = hcat [ "set<", ppType u, ">" ]
+ppType (THashSet u) = hcat [ "hash_set<", ppType u, ">" ]
+ppType (TList u)    = hcat [ "list<", ppType u, ">" ]
+ppType (TMap k v) = hcat [ "map<", ppType k, ", ", ppType v, ">" ]
+ppType (THashMap k v) = hcat [ "hash_map<", ppType k, ", ", ppType v, ">" ]
+ppType (TTypedef name _ _loc) = ppName name
+ppType (TNewtype name _ _loc) = ppName name
+ppType (TStruct name _loc)    = ppName name
+ppType (TException name _loc) = ppName name
+ppType (TUnion name _loc)     = ppName name
+ppType (TEnum name _loc _)      = ppName name
+ppType (TSpecial ty) = case backTranslateType ty of
+  (Some u, name) -> ppType u <+> parens (ppText name)
+
+ppName :: Name -> Doc
+ppName Name{..} = ppName_ sourceName
+
+ppName_ :: Name_ s -> Doc
+ppName_ (UName name) = text $ Text.unpack name
+ppName_ (QName m name) =
+    hcat [ ppText m, ".", ppText name ]
+
+ppText :: Text -> Doc
+ppText = text . Text.unpack
+
+ppConst :: UntypedConst a -> Doc
+ppConst (UntypedConst _ c) = ppConstVal c
+
+ppConstVal :: ConstVal a -> Doc
+ppConstVal (IntConst _ i)    = ppText i
+ppConstVal (DoubleConst _ d) = ppText d
+ppConstVal (StringConst s qt) = addQuotes $ text $ Text.unpack s
+  where
+    addQuotes = case qt of
+      DoubleQuote -> doubleQuotes
+      SingleQuote -> quotes
+ppConstVal (IdConst x)     = text $ Text.unpack x
+ppConstVal ListConst{..} =
+  brackets $ sep $ punctuate "," $ map (ppConst . leElem) lvElems
+ppConstVal MapConst{..} = braces $ sep $ punctuate "," $ map pp mvElems
+  where
+    pp ListElem{ leElem = MapPair{..} } =
+      hsep [ ppConst mpKey, ":", ppConst mpVal ]
+ppConstVal StructConst{..} = braces $ sep $ punctuate "," $ map pp svElems
+  where
+    pp ListElem{ leElem = StructPair{..} } =
+      hsep [ ppText spKey, "=", ppConst spVal ]
+ppConstVal (BoolConst b)
+  | b         = text "true"
+  | otherwise = text "false"
+
+ppAnnotation :: Annotation a -> Doc
+ppAnnotation SimpleAnn{..} = parens $ ppText saTag
+ppAnnotation ValueAnn{..} = parens $
+  ppText vaTag <+> "=" <+>
+  case vaVal of
+    TextAnn txt _ -> doubleQuotes (ppText txt)
+    IntAnn x _ -> int x
diff --git a/Thrift/Compiler/Typechecker.hs b/Thrift/Compiler/Typechecker.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Typechecker.hs
@@ -0,0 +1,1838 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE TypeOperators, NamedFieldPuns, ApplicativeDo #-}
+module Thrift.Compiler.Typechecker
+  ( typecheck
+  , typecheckConst, eqOrAlias
+  , PartitionedDecls(..), partitionDecls
+  , ModuleMap, sortModules
+  ) where
+
+import Prelude hiding (Enum)
+import Data.List hiding (uncons)
+import Data.Maybe
+import Data.Some
+import Data.Text.Encoding hiding (Some)
+import Data.Type.Equality
+import Control.Monad
+import Data.Graph
+import Data.Text (Text)
+import GHC.TypeLits hiding (TypeError)
+import GHC.Float
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Plugin
+import Thrift.Compiler.Typechecker.Monad
+import Thrift.Compiler.Types
+
+data PartitionedDecls s l a = Decls
+  { dTdefs   :: [Typedef s l a]
+  , dStructs :: [Struct s l a]
+  , dUnions  :: [Union s l a]
+  , dEnums   :: [Enum s l a]
+  , dConsts  :: [Const s l a]
+  , dServs   :: [Service s l a]
+  , dInteractions   :: [Interaction s l a]
+  }
+
+partitionDecls :: [Decl s l a] -> PartitionedDecls s l a
+partitionDecls = foldr addDecl emptyDecls
+  where
+    addDecl (D_Typedef t)  decls@Decls{..} = decls { dTdefs   = t : dTdefs   }
+    addDecl (D_Struct s)   decls@Decls{..} = decls { dStructs = s : dStructs }
+    addDecl (D_Union u)    decls@Decls{..} = decls { dUnions  = u : dUnions  }
+    addDecl (D_Enum e)     decls@Decls{..} = decls { dEnums   = e : dEnums   }
+    addDecl (D_Const c)    decls@Decls{..} = decls { dConsts  = c : dConsts  }
+    addDecl (D_Service s)  decls@Decls{..} = decls { dServs   = s : dServs   }
+    addDecl (D_Interaction s) decls@Decls{..} = decls { dInteractions = s : dInteractions }
+
+emptyDecls :: PartitionedDecls s l a
+emptyDecls = Decls
+  { dTdefs   = []
+  , dStructs = []
+  , dUnions  = []
+  , dEnums   = []
+  , dConsts  = []
+  , dServs   = []
+  , dInteractions = []
+  }
+
+getLoc :: Parsed Decl -> Loc
+getLoc (D_Typedef Typedef{..}) = lLocation $ tdlName tdLoc
+getLoc (D_Struct Struct{..}) = lLocation $ slName structLoc
+getLoc (D_Union Union{..}) = lLocation $ slName unionLoc
+getLoc (D_Enum Enum{..}) = lLocation $ slName enumLoc
+getLoc (D_Const Const{..}) = lLocation $ clName constLoc
+getLoc (D_Service Service{..}) = lLocation $ slName serviceLoc
+getLoc (D_Interaction Interaction{..}) = lLocation $ slName interactionLoc
+
+-- Main Typechecking Function --------------------------------------------------
+
+-- Given a map containing the tree of modules, typecheck all the things
+-- We do a left fold over the modules, so in the end they are reverse
+-- topologically sorted; the original module is the head of the list
+typecheck
+  :: Typecheckable l
+  => Options l
+  -> ModuleMap
+  -> Either [TypeError l] (Program l Loc, [Program l Loc])
+typecheck opts =
+  uncons <=< foldM (typecheckModule opts) [] <=< sortAndPrune
+    where
+      sortAndPrune = fmap (pruneModules opts) . sortModules
+      uncons (p : ps) = pure (p, ps)
+      uncons []       = Left [EmptyInput]
+
+typecheckModule
+   :: Typecheckable l
+   => Options l
+   -> [Program l Loc]
+   -> ThriftFile SpliceFile Loc
+   -> Either [TypeError l] [Program l Loc]
+typecheckModule opts@Options{..} progs tf@ThriftFile{..} = do
+  -- Make Imports Map
+  let
+    imports   = [ incPath | HInclude{incType=Include,..} <- thriftHeaders ]
+    includes  = [ prog | prog@Program{..} <- progs
+                , optsLenient || progPath `elem` imports ]
+    importMap = mkImportMap opts progs imports
+    renamedModule = renameModule opts tf
+    thriftDeclsNew
+      | optsLenient && Map.notMember thriftName importMap =
+          unSelfQualDecls thriftName thriftDecls
+      | otherwise = thriftDecls
+  -- Make Type Map
+  tmap <- mkTypemap (thriftName, opts) importMap thriftDeclsNew
+  -- Make Schema, Constants, and Services Maps
+  let
+    Decls{..} = partitionDecls thriftDeclsNew
+    emap = mkEnumMap opts dEnums
+    imap = mkEnumInt opts dEnums
+  (smap, umap, cmap, servMap)
+     <- (,,,) <$> mkSchemaMap (thriftName, opts) importMap tmap dStructs
+         <*> mkUnionMap (thriftName, opts) importMap tmap dUnions
+         <*> mkConstMap (thriftName, opts) importMap tmap thriftDeclsNew
+         <*> mkServiceMap (thriftName, opts) importMap dServs
+
+  -- Build the Env
+  let env = Env { typeMap    = tmap
+                , schemaMap  = smap
+                , unionMap   = umap
+                , enumMap    = emap
+                , enumInt    = imap
+                , constMap   = cmap
+                , serviceMap = servMap
+                , importMap  = importMap
+                , options    = opts
+                , envName    = thriftName -- for weird 'mkThriftName' case
+                }
+  -- Typecheck the rest of the things
+  headers <- runTypechecker env $ traverse typecheckHeader thriftHeaders
+  decls <- runTypechecker env $ traverse resolveDecl thriftDeclsNew
+  let prog = Program
+             { progName      = thriftName
+             , progHSName    = renamedModule
+             , progPath      = thriftPath
+             , progOutPath   = optsOutPath
+             , progInstances = thriftSplice
+             , progIncludes  = includes
+             , progHeaders   = headers
+             , progDecls     = decls
+             , progComments  = thriftComments
+             , progEnv       = qualify (thriftName, renamedModule) env
+             }
+  return $ prog : progs
+
+typecheckHeader
+  :: Typecheckable l
+  => Header 'Unresolved () Loc
+  -> TC l (Header 'Resolved  l Loc)
+typecheckHeader HInclude{..} = pure $ HInclude{..}
+typecheckHeader HNamespace{..} = pure $ HNamespace{..}
+typecheckHeader HPackage{..} = do
+  sAnns <- resolveStructuredAnns pkgSAnns
+  pure $ HPackage{pkgSAnns = sAnns, ..}
+
+-- Self qualified --------------------------------------------------------------
+
+-- | Takes the current thriftName (envName, progName) and removes this
+-- from any 'TNamed' type that uses this thriftName a qualifier, i.e.
+-- removes the qualifier if it is for the current thrift module.
+--
+-- We need to do this early, otherwise building the type map fails.
+--
+-- This is only used in @--lenient@ mode.
+unSelfQualDecls :: Text -> [Parsed Decl] -> [Parsed Decl]
+unSelfQualDecls thriftName xs = map unSelfQual xs
+  where
+    self = thriftName <> "."
+
+    unSelfQual :: Parsed Decl -> Parsed Decl
+    unSelfQual p = case p of
+      D_Struct Struct{..}
+        -> D_Struct Struct{structMembers = map usqField structMembers, ..}
+      D_Union Union{..} -> D_Union Union{unionAlts = map usqAlt unionAlts, ..}
+      D_Const Const{..}
+        | Just x <- usqAnnType constType -> D_Const Const{constType=x, ..}
+      D_Typedef Typedef{..}
+        | Just x <- usqAnnType tdType -> D_Typedef Typedef{tdType=x, ..}
+      D_Service Service{..}
+        -> D_Service Service{serviceStmts = map usqStmt serviceStmts, ..}
+      _ -> p
+
+    usqField f@Field{..}
+      | Just x <- usqAnnType fieldType = Field{fieldType=x, ..}
+      | otherwise = f
+
+    usqAlt :: UnionAlt 'Unresolved () Loc -> UnionAlt 'Unresolved () Loc
+    usqAlt a@UnionAlt{..}
+      | Just x <- usqAnnType altType = UnionAlt{altType=x, ..}
+      | otherwise = a
+
+    usqStmt :: ServiceStmt 'Unresolved () Loc -> ServiceStmt 'Unresolved () Loc
+    usqStmt (FunctionStmt Function{..}) = FunctionStmt $ Function
+      { funType = case funType of
+          FunType (Some at) | Just x <- usqAnnType at -> FunType (Some x)
+          FunTypeResponseAndStreamReturn ResponseAndStreamReturn{..}
+            | Stream{..} <- rsStream
+            , Just x <- usqAnnType streamType ->
+                FunTypeResponseAndStreamReturn $ ResponseAndStreamReturn
+                  { rsStream = Stream{streamType=x, ..}
+                  , ..
+                  }
+          _ -> funType
+      , funArgs = map usqField funArgs
+      , funExceptions = map usqField funExceptions
+      , .. }
+    usqStmt (PerformsStmt p) = PerformsStmt p
+
+    usqAnnType :: forall v. AnnotatedType Loc v -> Maybe (AnnotatedType Loc v)
+    usqAnnType t@AnnotatedType{..} = (\x -> t{atType=x}) <$> usqType atType
+
+    usqType
+      :: forall v. TType 'Unresolved () Loc v
+      -> Maybe (TType 'Unresolved () Loc v)
+    usqType (TSet t) | Just x <- usqAnnType t = Just $ TSet x
+    usqType (THashSet t) | Just x <- usqAnnType t = Just $ THashSet x
+    usqType (TList t) | Just x <- usqAnnType t = Just $ TList x
+    usqType (TMap k v) = case (usqAnnType k, usqAnnType v) of
+      (Just x, Just y) -> Just $ TMap x y
+      (Just x, _) -> Just $ TMap x v
+      (_, Just y) -> Just $ TMap k y
+      _ -> Nothing
+    usqType (THashMap k v) = case (usqAnnType k, usqAnnType v) of
+      (Just x, Just y) -> Just $ THashMap x y
+      (Just x, _) -> Just $ THashMap x v
+      (_, Just y) -> Just $ THashMap k y
+      _ -> Nothing
+    usqType (TNamed input) | Just x <- Text.stripPrefix self input =
+      Just (TNamed x) -- Here is the point of unSelfQualDecls
+    usqType _ = Nothing
+
+-- Map Builders ----------------------------------------------------------------
+
+-- | When using @--lenient@ mode, this includes not only the direct import but
+-- also all others.  If there is a naming collision then direct wins over
+-- indirect, but naming collisions between indirect ones is resolved in an
+-- unspecified way. See T43181464 for weird examples of transitive imports.
+mkImportMap :: Options l -> [Program l a] -> [FilePath] -> ImportMap l
+mkImportMap options progs imports =
+  if not (optsLenient options) then Map.fromList
+    [ (progName, progEnv) | Program{..} <- progs, progPath `elem` imports ]
+  else
+    let (direct, indirect) = partition (\ p -> progPath p `elem` imports) progs
+    in Map.fromList $
+        (++) [ (progName, progEnv) | Program{..} <- indirect ]
+             [ (progName, progEnv) | Program{..} <- direct ]
+
+-- Recursively Typecheck all the Modules ---------------------------------------
+
+type ModuleMap = Map.Map FilePath (ThriftFile SpliceFile Loc)
+
+-- Topologically sort the modules so that we can typecheck them. We will start
+-- at the leaves and work our way up to the original module
+sortModules :: ModuleMap -> Either [TypeError l] [ThriftFile SpliceFile Loc]
+sortModules moduleMap = traverse getVertex sccs
+  where
+    sccs  = stronglyConnComp graph
+    graph = map mkVertex (Map.toList moduleMap)
+    -- Create a vertex from a map entry
+    mkVertex (filepath, file) = (file, filepath, getIncludes file)
+    getIncludes ThriftFile{..} = foldr getInc [] thriftHeaders
+    getInc HInclude{incType=Include,..} ps = incPath : ps
+    getInc _ ps = ps
+    -- get a ThriftFile from an SCC
+    getVertex (AcyclicSCC f) = pure f
+    getVertex (CyclicSCC fs) = Left [CyclicModules fs]
+
+-- Prune the modules to only include the required symbols. This avoids
+-- generating extra code
+-- Note: assumes modules are topologically sorted with head module at the tail
+pruneModules
+  :: Typecheckable l
+  => Options l
+  -> [ThriftFile SpliceFile Loc]
+  -> [ThriftFile SpliceFile Loc]
+pruneModules Options { optsReqSymbols = Nothing } files = files
+pruneModules opts@Options { optsReqSymbols = Just syms } files =
+  prunesFiles
+    where
+      (prunesFiles, _, _) =
+        foldr (pruneModule opts) ([], symbolMap, mempty) files
+      symbolMap = mkSymbolMap opts syms
+
+type SymbolMap = Map.Map Text Symbols
+type Symbols   = Set.Set Text
+
+mkSymbolMap :: Options l -> [Text] -> SymbolMap
+mkSymbolMap Options{..} qsyms = Map.fromListWith Set.union
+  [ (mname, Set.singleton symbol)
+  | s <- qsyms
+  , let
+      (pre, symbol) = Text.breakOnEnd "." s
+      mname | Text.null pre = topModule
+            | otherwise = Text.dropEnd 1 pre
+  ]
+  where
+    topModule = getModuleName optsPath
+
+pruneModule
+  :: Typecheckable l
+  => Options l
+  -> ThriftFile SpliceFile Loc
+  -> ([ThriftFile SpliceFile Loc], SymbolMap, Interface l)
+  -> ([ThriftFile SpliceFile Loc], SymbolMap, Interface l)
+pruneModule opts file@ThriftFile{..} (fs, symbolMap, iface) =
+  (prunedFile : fs, newMap, iface')
+  where
+    prunedFile = file { thriftDecls = prunedDecls }
+    (prunedDecls, _, newMap) =
+      filterDecls requiredSymbols symbolMap' thriftDecls
+    requiredSymbols = fromMaybe Set.empty $ Map.lookup thriftName symbolMap'
+
+    symbolMap' =
+      Map.unionWith Set.union symbolMap $ mkSymbolMap opts extraSymbols
+    extraSymbols = getExtraSymbols opts iface' file
+    iface' = iface <> getInterface opts file
+
+filterDecls
+  :: Symbols
+  -> SymbolMap
+  -> [Parsed Decl]
+  -> ([Parsed Decl], Symbols, SymbolMap)
+filterDecls reqSymbols symbolMap =
+  foldr filterSCC ([], reqSymbols, symbolMap) . mkSortedGraph
+  where
+    -- If we get a singleton node and it's a member of the required symbols,
+    -- include it with all dependencies
+    filterSCC (AcyclicSCC node) ctx@(_, symbols, _)
+      | isRequired node symbols = addNode node ctx
+    -- If we get a strongly connected component and at least one of the decls
+    -- is required, we need to include all of them
+    filterSCC (CyclicSCC nodes) ctx@(_, symbols, _)
+      | any (\node -> isRequired node symbols) nodes =
+        foldr addNode ctx nodes
+    -- Otherwise we don't need it
+    filterSCC _ ctx = ctx
+
+    filterOutFns symbols (FunctionStmt Function{..}) = Set.member funName symbols
+    filterOutFns _ (PerformsStmt _) = False
+
+    isRequired (D_Service Service{..}, dname, _) symbols =
+      Set.member dname symbols ||
+      any (filterOutFns symbols) serviceStmts
+    isRequired (_, dname, _) symbols = Set.member dname symbols
+
+    addNode node (ds, syms, smap) = (decl : ds, newSyms, newMap)
+      where
+        (decl, _, rsyms) = filterDecl node syms
+        (newSyms, newMap) = foldr addSym (syms, smap) rsyms
+
+    -- If the Decl is a Service, then we only want to take the functions which
+    -- are required
+    filterDecl (D_Service s, _, _) symbols = mkVertex newDecl
+      where
+        newDecl = D_Service s {serviceStmts = filteredStmts, serviceSAnns=[]}
+
+        mapFunSAnns (FunctionStmt f) = FunctionStmt (f {funSAnns=[]})
+        mapFunSAnns p = p
+
+        filteredStmts =
+          map mapFunSAnns $
+          filter (filterOutFns symbols) $
+          serviceStmts s
+    filterDecl (D_Interaction s, _, _) symbols = mkVertex newDecl
+      where
+        newDecl = D_Interaction s {interactionFunctions = filteredFuns, interactionSAnns=[]}
+        filteredFuns =
+          map (\f -> f {funSAnns=[]}) $
+          filter (\Function{..} -> Set.member funName symbols) $
+          interactionFunctions s
+    filterDecl (D_Struct s, syms, smap) _ =
+      (D_Struct s
+        { structSAnns = []
+        , structMembers = map filterField $ structMembers s
+        }, syms, smap)
+    filterDecl (D_Union u, syms, smap) _ =
+      (D_Union u
+        { unionSAnns = []
+        , unionAlts = map filterAlt $ unionAlts u
+        }, syms, smap)
+    filterDecl (D_Typedef t, syms, smap) _ =
+      (D_Typedef t {tdSAnns=[]}, syms, smap)
+    filterDecl (D_Enum e, syms, smap) _ =
+        (D_Enum e
+          {enumSAnns=[]
+          , enumConstants = filterEnumConstants $ enumConstants e
+          }, syms, smap)
+      where
+        filterEnumConstants = map filterEnumValue
+        filterEnumValue ev = ev { evSAnns = []}
+    filterDecl (D_Const c, syms, smap) _ =
+      (D_Const c {constSAnns=[]}, syms, smap)
+
+    filterField field = field {fieldSAnns=[]}
+
+    filterAlt :: UnionAlt 'Unresolved l a -> UnionAlt 'Unresolved l a
+    filterAlt alt = alt {altSAnns=[]}
+
+    addSym symbol (syms, smap)
+      | Text.null name = (Set.insert symbol syms, smap)
+      | otherwise = (syms, Map.insertWith Set.union prefix nameSet smap)
+      where (prefix, name) = Text.breakOn "." symbol
+            nameSet = Set.singleton $ Text.drop 1 name
+
+    mkSortedGraph :: [Parsed Decl] -> [SCC (Parsed Decl, Text, [Text])]
+    mkSortedGraph = stronglyConnCompR . map mkVertex
+
+    mkVertex d@(D_Struct Struct{..}) =
+      (d, structName, concatMap fieldSymbols structMembers)
+    mkVertex d@(D_Union Union{..}) =
+      (d, unionName, concatMap altSymbols unionAlts)
+    mkVertex d@(D_Enum Enum{..}) =
+      (d, enumName, [])
+    mkVertex d@(D_Typedef Typedef{..}) =
+      (d, tdName, anTypeSymbols tdType)
+    mkVertex d@(D_Const Const{..}) =
+      (d, constName, anTypeSymbols constType ++ constSymbols constVal)
+    mkVertex d@(D_Service Service{..}) =
+      ( d
+      , serviceName
+      , maybeToList (supName <$> serviceSuper) ++
+        concatMap stmtSymbols serviceStmts
+      )
+    mkVertex d@(D_Interaction Interaction{..}) =
+      ( d
+      , interactionName
+      , maybeToList (supName <$> interactionSuper) ++
+        concatMap funSymbols interactionFunctions
+      )
+    fieldSymbols :: Parsed (Field u) -> [Text]
+    fieldSymbols Field{..} =
+      maybe [] constSymbols fieldVal ++ anTypeSymbols fieldType
+    altSymbols :: Parsed UnionAlt -> [Text]
+    altSymbols UnionAlt{..} = anTypeSymbols altType
+    constSymbols (UntypedConst _ val) = constValSymbols val
+    constValSymbols IntConst{} = []
+    constValSymbols DoubleConst{} = []
+    constValSymbols StringConst{} = []
+    constValSymbols BoolConst{} = []
+    constValSymbols (IdConst name) = [name]
+    constValSymbols ListConst{..} = concatMap (constSymbols . leElem) lvElems
+    constValSymbols MapConst{..} =
+      [ s | ListElem{leElem=MapPair{..}} <- mvElems
+          , s <- constSymbols mpKey ++ constSymbols mpVal ]
+    constValSymbols StructConst{..} =
+      [ s | ListElem{leElem=StructPair{..}} <- svElems
+          , s <- constSymbols spVal ]
+    stmtSymbols :: Parsed ServiceStmt -> [Text]
+    stmtSymbols (FunctionStmt f) = funSymbols f
+    stmtSymbols _ = []
+    funSymbols :: Parsed Function -> [Text]
+    funSymbols Function{..} =
+      funName :
+      funTypeSymbols funType ++
+      concatMap fieldSymbols funArgs ++
+      concatMap fieldSymbols funExceptions
+    funTypeSymbols :: Parsed FunctionType -> [Text]
+    funTypeSymbols (FunType (Some ty)) = anTypeSymbols ty
+    funTypeSymbols (FunTypeVoid _) = []
+    funTypeSymbols
+      (FunTypeResponseAndStreamReturn
+       ResponseAndStreamReturn{rsStream=Stream{..}}) =
+        anTypeSymbols streamType ++
+        maybe [] (concatMap fieldSymbols . throwsFields) streamThrows
+
+    anTypeSymbols :: AnnotatedType Loc t -> [Text]
+    anTypeSymbols AnnotatedType{..} = typeSymbols atType
+    typeSymbols :: TType 'Unresolved l Loc t -> [Text]
+    -- Base types have no dependencies
+    typeSymbols I8  = []
+    typeSymbols I16 = []
+    typeSymbols I32 = []
+    typeSymbols I64 = []
+    typeSymbols TFloat  = []
+    typeSymbols TDouble = []
+    typeSymbols TBool = []
+    typeSymbols TText = []
+    typeSymbols TBytes = []
+    -- Recursive types have recursive dependencies
+    typeSymbols (TSet ty)      = anTypeSymbols ty
+    typeSymbols (THashSet ty)  = anTypeSymbols ty
+    typeSymbols (TList ty)     = anTypeSymbols ty
+    typeSymbols (TMap k v)     = anTypeSymbols k ++ anTypeSymbols v
+    typeSymbols (THashMap k v) = anTypeSymbols k ++ anTypeSymbols v
+    -- Named types depend on the type they name
+    typeSymbols (TNamed name) = [name]
+
+-- Resolve the Decls -----------------------------------------------------------
+
+resolveDecl :: Typecheckable l => Parsed Decl -> Typechecked l Decl
+resolveDecl (D_Struct s)  = D_Struct  <$> resolveStruct s
+resolveDecl (D_Union u)   = D_Union   <$> resolveUnion u
+resolveDecl (D_Typedef t) = D_Typedef <$> resolveTypedef t
+resolveDecl (D_Enum e)    = D_Enum    <$> resolveEnum e
+resolveDecl (D_Const c)   = D_Const   <$> resolveConst c
+resolveDecl (D_Service s) = D_Service <$> resolveService s
+resolveDecl (D_Interaction s) = D_Interaction <$> resolveInteraction s
+
+resolveTypedef
+  :: forall l. Typecheckable l
+  => Parsed Typedef
+  -> Typechecked l Typedef
+resolveTypedef t@Typedef{..} = mkTypedef
+  where
+    mkTypedef :: Typechecked l Typedef
+    mkTypedef = do
+      Env{..} <- ask
+      thisty <- resolveAnnotatedType tdType
+      sAnns   <- resolveStructuredAnns tdSAnns
+      declIsNewtype <- or <$> mapM checkAnn (filterHsAnns $ getAnns tdAnns)
+      case thisty of
+        Some ty -> return $ Typedef
+          { tdResolvedName = renameTypedef options t
+          , tdResolvedType = ty
+          , tdTag = if declIsNewtype then IsNewtype else IsTypedef
+          , tdSAnns = sAnns
+          , ..
+          }
+
+    checkAnn SimpleAnn{..} | saTag == "hs.newtype" = return True
+    checkAnn ann = typeError (annLoc ann) $ AnnotationMismatch AnnTypedef ann
+
+resolveStruct
+  :: Typecheckable l
+  => Parsed Struct
+  -> Typechecked l Struct
+resolveStruct s@Struct{..} = do
+  Env{..} <- ask
+  fields <- resolveFields structName (getAnns structAnns) structMembers
+  sAnns   <- resolveStructuredAnns structSAnns
+  return Struct
+    { structResolvedName = renameStruct options s
+    , structMembers      = fields
+    , structSAnns        = sAnns
+    , ..
+    }
+
+resolveFields
+  :: Typecheckable l
+  => Text
+  -> [Annotation Loc]
+  -> [Parsed (Field u)]
+  -> TC l [Field u 'Resolved l Loc]
+resolveFields sname as fs =
+  (traverse (resolveField as sname) =<< fields) <*
+  -- Check for duplicate field ids
+  foldM checkId Set.empty fs
+  where
+    update lazy f = f { fieldLaziness = lazy }
+    fields = foldM checkAnn fs $ filterHsAnns as
+    checkAnn _ SimpleAnn{..}
+      | saTag == "hs.strict" = pure $ map (update Strict) fs
+      | saTag == "hs.lazy"   = pure $ map (update Lazy) fs
+    checkAnn fs' ValueAnn{..}
+      | vaTag == "hs.prefix"
+      , TextAnn{} <- vaVal = pure fs'
+    checkAnn _ ann = typeError (annLoc ann) $ AnnotationMismatch AnnStruct ann
+    checkId ids Field{..}
+      | Set.member fieldId ids =
+          typeError (lLocation $ flId fieldLoc) $
+          InvalidFieldId fieldName (fromIntegral fieldId)
+      | otherwise = pure $ Set.insert fieldId ids
+
+getPriority
+  :: [Annotation Loc]
+  -> Maybe ThriftPriority
+getPriority = listToMaybe . mapMaybe getP
+  where
+    getP ValueAnn{vaVal=TextAnn p _, vaTag = "priority"}
+      | p == "HIGH_IMPORTANT" = Just HighImportant
+      | p == "HIGH"           = Just High
+      | p == "IMPORTANT"      = Just Important
+      | p == "NORMAL"         = Just NormalPriority
+      | p == "BEST_EFFORT"    = Just BestEffort
+      | p == "N_PRIORITIES"   = Just NPriorities
+    getP _ = Nothing
+
+resolveField
+  :: Typecheckable l
+  => [Annotation Loc]
+  -> Text
+  -> Parsed (Field u)
+  -> Typechecked l (Field u)
+resolveField anns sname field@Field{..} = do
+  when (fieldId == 0) $
+    typeError (lLocation $ flId fieldLoc) $ InvalidFieldId fieldName 0
+  thisty <- resolveAnnotatedType fieldType
+  case thisty of
+    Some ty -> do
+      val  <- sequence (typecheckConst ty <$> fieldVal)
+      lazy <- case filterHsAnns $ getAnns fieldAnns of
+            [SimpleAnn{..}]
+              | saTag == "hs.strict" -> pure Strict
+              | saTag == "hs.lazy"   -> pure Lazy
+            [] -> pure fieldLaziness
+            ann : _ -> typeError (annLoc ann) $ AnnotationMismatch AnnField ann
+      sAnns <- resolveStructuredAnns fieldSAnns
+      Env{..} <- ask
+      case resolveTag fieldTag ty of
+        Nothing -> typeError (lLocation $ flName fieldLoc) $
+                   InvalidThrows ty fieldName
+        Just tag ->
+          return Field
+          { fieldResolvedName = renameField options anns sname field
+          , fieldResolvedType = ty
+          , fieldResolvedVal  = val
+          , fieldLaziness = lazy
+          , fieldTag = tag
+          , fieldSAnns = sAnns
+          , ..
+          }
+
+resolveTag
+  :: FieldTag u 'Unresolved () a
+  -> Type l t
+  -> Maybe (FieldTag u 'Resolved l t)
+resolveTag STRUCT_FIELD _ = Just STRUCT_FIELD
+resolveTag ARGUMENT     _ = Just ARGUMENT
+resolveTag THROWS_UNRESOLVED ty =
+  case getAliasedType ty of
+    TException{} -> Just THROWS_RESOLVED
+    _ -> Nothing
+
+resolveUnion :: forall l. Typecheckable l => Parsed Union -> Typechecked l Union
+resolveUnion u@Union{..} = do
+  Options{optsLenient} <- asks options
+  alts <- resolveAlts optsLenient unionAlts
+  thishasEmpty <-
+    fromMaybe (Some HasEmpty) . listToMaybe . catMaybes <$>
+    mapM resolveAnn (filterHsAnns $ getAnns unionAnns)
+  sAnns <- resolveStructuredAnns unionSAnns
+
+  Env{..} <- ask
+  case thishasEmpty of
+    Some hasEmpty -> return Union
+      { unionResolvedName = renameUnion options u
+      , unionAlts = alts
+      , unionEmptyName = getEmptyName options hasEmpty
+      , unionHasEmpty  = hasEmpty
+      , unionSAnns = sAnns
+      , ..
+      }
+  where
+    resolveAlts :: Bool -> [Parsed UnionAlt] -> TC l [UnionAlt 'Resolved l Loc]
+    resolveAlts optsLenient alts =
+      traverse resolveAlt alts
+      -- Check for duplicate field ids
+      <* foldM checkId Set.empty alts
+      <* checkEmpty
+      where
+        checkId ids UnionAlt{..}
+          | Set.member altId ids =
+              typeError (lLocation $ flId altLoc) $
+              InvalidFieldId altName (fromIntegral altId)
+          | otherwise = pure $ Set.insert altId ids
+        checkEmpty = when (null alts && not optsLenient) $
+          typeError (lLocation $ slKeyword unionLoc) $ EmptyUnion unionName
+
+    resolveAlt :: Parsed UnionAlt -> Typechecked l UnionAlt
+    resolveAlt alt@UnionAlt{..} = do
+      thisty <- resolveAnnotatedType altType
+      sAnns   <- resolveStructuredAnns altSAnns
+      Env{..} <- ask
+      case thisty of
+        Some ty -> return UnionAlt
+          { altResolvedName = renameUnionAlt options u alt
+          , altResolvedType = ty
+          , altSAnns = sAnns
+          , ..
+          }
+
+    resolveAnn :: Annotation Loc -> TC l (Maybe (Some PossiblyEmpty))
+    resolveAnn SimpleAnn{..}
+      | saTag == "hs.nonempty" = pure $ Just $ Some NonEmpty
+    resolveAnn ValueAnn{..}
+      | vaTag == "hs.prefix"
+      , TextAnn{} <- vaVal = pure Nothing
+    resolveAnn a = typeError (annLoc a) $ AnnotationMismatch AnnUnion a
+
+    getEmptyName :: Options l -> PossiblyEmpty e -> EmptyName 'Resolved e
+    getEmptyName opts HasEmpty = getUnionEmptyName opts u
+    getEmptyName _ NonEmpty = ()
+
+resolveEnum :: forall l. Typecheckable l => Parsed Enum -> Typechecked l Enum
+resolveEnum enum@Enum{..} = do
+  consts <- mapM mkAlt enumConstants
+  sAnns   <- resolveStructuredAnns enumSAnns
+  Env{..} <- ask
+  forM_ getDups $
+    typeError $ lLocation $ slName enumLoc
+  return Enum
+    { enumResolvedName = renameEnum options enum
+    , enumConstants = consts
+    , enumFlavour = enumFlavourTag options enum
+    , enumSAnns = sAnns
+    , ..
+    }
+  where
+    mkAlt :: Parsed EnumValue -> Typechecked l EnumValue
+    mkAlt EnumValue{..} = do
+      sAnns   <- resolveStructuredAnns evSAnns
+      Env{..} <- ask
+      return EnumValue
+        { evResolvedName = renameEnumAlt options enum evName
+        , evSAnns = sAnns
+        , ..
+        }
+
+    getDups :: Maybe (ErrorMsg l)
+    getDups =
+      (\(v, ns) -> DuplicateEnumVal enumName ns v) <$>
+      find ((>1) . length . snd)
+      (Map.toList $
+       Map.fromListWith (++)
+       [ (fromIntegral evValue, [evName]) | EnumValue{..} <- enumConstants ])
+
+resolveConst :: Typecheckable l => Parsed Const -> Typechecked l Const
+resolveConst Const{..} = do
+  thisty <- resolveAnnotatedType constType
+  case thisty of
+    Some ty -> do
+      Env{..} <- ask
+      val   <- typecheckConst ty constVal
+      sAnns <- resolveStructuredAnns constSAnns
+      return Const
+        { constResolvedName = renameConst options constName
+        , constResolvedType = ty
+        , constResolvedVal  = val
+        , constSAnns        = sAnns
+        , ..
+        }
+
+resolveService :: Typecheckable l => Parsed Service -> Typechecked l Service
+resolveService s@Service{..} = do
+  (super, stmts, sAnns)
+    <- (,,) <$> mapM resolveSuper serviceSuper
+            <*> traverse resolveStmt serviceStmts
+            <*> resolveStructuredAnns serviceSAnns
+  Env{..} <- ask
+  pure Service
+    { serviceResolvedName = renameService options s
+    , serviceSuper        = super
+    , serviceStmts        = stmts
+    , serviceSAnns        = sAnns
+    , ..
+    }
+  where
+    resolveSuper Super{..} = do
+      name <- mkThriftName supName
+      (rname, _, rloc) <- lookupService name $ lLocation $ slName serviceLoc
+      pure Super { supResolvedName = (rname, rloc), .. }
+
+resolveStmt :: Typecheckable l => Parsed ServiceStmt -> Typechecked l ServiceStmt
+resolveStmt (FunctionStmt f) = do
+  r <- resolveFunction f
+  pure $ FunctionStmt r
+resolveStmt (PerformsStmt Performs{..}) = do
+  pure $ PerformsStmt $ Performs {..}
+
+resolveInteraction :: Typecheckable l => Parsed Interaction -> Typechecked l Interaction
+resolveInteraction Interaction{..} = do
+  (super, funs, sAnns)
+    <- (,,) <$> mapM resolveSuper interactionSuper
+            <*> traverse resolveFunction interactionFunctions
+            <*> resolveStructuredAnns interactionSAnns
+  pure Interaction
+    { interactionResolvedName = interactionName
+    , interactionSuper        = super
+    , interactionFunctions    = funs
+    , interactionSAnns        = sAnns
+    , ..
+    }
+  where
+    resolveSuper Super{..} = do
+      name <- mkThriftName supName
+      (rname, _, rloc) <- lookupService name $ lLocation $ slName interactionLoc
+      pure Super { supResolvedName = (rname, rloc), .. }
+
+resolveFunction :: Typecheckable l => Parsed Function -> Typechecked l Function
+resolveFunction f@Function{..} = do
+  (rtype, ftype, args, excepts, sAnns)
+    <- (,,,,) <$>
+        sequence (resolveFunctionTypeTy funType)
+          <*> resolveFunctionType funName annNoPriorities funType
+          <*> resolveFields funName annNoPriorities funArgs
+          <*> resolveFields funName annNoPriorities funExceptions
+          <*> resolveStructuredAnns funSAnns
+  Env{..} <- ask
+  pure $ Function
+    { funResolvedName = renameFunction options f
+    , funType         = ftype
+    , funResolvedType = rtype
+    , funArgs         = args
+    , funExceptions   = excepts
+    , funPriority = fromMaybe funPriority $ getPriority annPriorities
+    , funSAnns = sAnns
+    , ..
+    }
+  where
+    (annPriorities, annNoPriorities) = partition isPriority $ getAnns funAnns
+    isPriority ValueAnn{..}
+      | TextAnn{} <- vaVal = vaTag == "priority"
+    isPriority _ = False
+
+resolveFunctionTypeTy
+  :: Typecheckable l
+  => FunctionType s () Loc
+  -> Maybe (TC l (Some (Type l)))
+resolveFunctionTypeTy (FunType (Some ty)) =
+  Just $ resolveAnnotatedType ty
+resolveFunctionTypeTy (FunTypeVoid _) =
+  Nothing
+resolveFunctionTypeTy (FunTypeResponseAndStreamReturn _) =
+  Nothing -- This doesn't support stream yet
+
+resolveFunctionType
+  :: Typecheckable l
+  => Text
+  -> [Annotation Loc]
+  -> Parsed FunctionType
+  -> Typechecked l FunctionType
+resolveFunctionType _ _ (FunType (Some ty)) = pure $ FunType (Some ty)
+resolveFunctionType _ _ (FunTypeVoid ann) = pure $ FunTypeVoid ann
+resolveFunctionType
+  structName
+  ann
+  (FunTypeResponseAndStreamReturn ResponseAndStreamReturn{..}) = do
+    stream <- resolveStream rsStream
+    pure $ FunTypeResponseAndStreamReturn $ ResponseAndStreamReturn
+      { rsStream = stream
+      , ..
+      }
+    where
+      resolveStream Stream{..} = do
+        throws <- mapM resolveThrows streamThrows
+        pure $ Stream
+          { streamThrows = throws
+          , ..
+          }
+      resolveThrows Throws{..} = do
+        fields <- resolveFields structName ann throwsFields
+        pure $ Throws
+          { throwsFields = fields
+          , ..
+          }
+
+-- Resolve Structured Annotations ----------------------------------------------
+
+resolveStructuredAnns
+  :: Typecheckable l
+  => [StructuredAnnotation 'Unresolved () Loc]
+  -> TC l [StructuredAnnotation 'Resolved  l Loc]
+resolveStructuredAnns = mapM resolveStructuredAnn
+
+resolveStructuredAnn
+  :: Typecheckable l
+  => Parsed StructuredAnnotation
+  -> Typechecked l StructuredAnnotation
+resolveStructuredAnn StructuredAnn{..} = do
+  thisty <- resolveType (TNamed saType) saTypeLoc Nothing
+  saTypeName <- mkThriftName saType
+  thisschema <- lookupSchemaRec saTypeName lLocation
+  case (thisty, thisschema) of
+    (Some ty, Some schema) -> do
+      val <- typecheckStruct lLocation schema =<<
+             mkStructFieldMap (maybe [] saElems saMaybeElems)
+      case ty of
+        TStruct _ loc | not $ loc `isDefinedAt` lLocation ->
+            typeError lLocation (NotDefinedBeforeUsed ty)
+        _ ->
+            pure StructuredAnn
+            { saResolvedType = ty
+            , saResolvedVal = Some val
+            , ..
+            }
+  where
+    Located{..} = a0Ty saTypeLoc
+    isDefinedAt :: Loc -> Loc -> Bool
+    isDefinedAt defLoc loc
+      | locFile defLoc /= locFile loc = True
+      | locEndLine defLoc < locStartLine loc = True
+      | locEndLine defLoc > locStartLine loc = False
+      -- locEndLine defLoc == locStartLine loc
+      | locEndCol defLoc <= locStartCol loc = True
+      | otherwise = False
+
+-- Build the Constant Map ------------------------------------------------------
+
+mkConstMap
+  :: forall l. Typecheckable l
+  => (Text, Options l)
+  -> ImportMap l
+  -> TypeMap l
+  -> [Parsed Decl]
+  -> Either [TypeError l] (ConstMap l)
+mkConstMap (thriftName, opts) imap tmap = foldM insertC emptyContext
+  where
+    -- Structs don't define constants, but they have symbols in scope
+    insertC m (D_Struct s@Struct{..}) = do
+      -- add data constructor name to scope
+      scope <- addToScope (lLocation $ slName structLoc) (renameStruct opts s) m
+      -- add field names to scope unless Duplicate Names is turned on
+      if fieldsAreUnique opts
+        then foldM (insFieldName opts) scope structMembers
+        else return scope
+      where
+        insFieldName
+          :: Options l
+          -> ConstMap l
+          -> Parsed (Field u)
+          -> Either [TypeError l] (ConstMap l)
+        insFieldName opts' scope field@Field{..} =
+          addToScope (lLocation $ flName fieldLoc)
+          (renameField opts' (getAnns structAnns) structName field)
+          scope
+
+    -- Unions define data constructors
+    insertC m (D_Union u@Union{..})
+      | unionAltsAreUnique opts =
+          (if any isETag $ getAnns unionAnns
+           then pure
+           else addToScope (lLocation $ slName unionLoc)
+                (getUnionEmptyName opts u))
+          =<< foldM (addAlt opts) m unionAlts
+      | otherwise = pure m
+      where
+        addAlt
+          :: Options l
+          -> ConstMap l
+          -> Parsed UnionAlt
+          -> Either [TypeError l] (ConstMap l)
+        addAlt opts' scope alt@UnionAlt{..} =
+          addToScope (lLocation $ flName altLoc) (renameUnionAlt opts' u alt)
+            scope
+        isETag SimpleAnn{..} = saTag == "hs.nonempty"
+        isETag ValueAnn{} = False
+
+    -- If a typedef is s newtype, we have to add the data constructor to the
+    -- scope
+    insertC m (D_Typedef t@Typedef{..})
+      | isNewtype (getAnns tdAnns) =
+          let
+            name = renameTypedef opts t
+            loc  = lLocation $ tdlName tdLoc
+          in addToScope loc name =<< addToScope loc ("un" <> name) m
+      | otherwise = pure m
+
+    -- All the enum constants have the type of the enum
+    insertC m (D_Enum enum@Enum{..})
+      | enumAltsAreUnique opts = foldM insE m enumConstants
+      | otherwise = pure m
+      where
+        insE acc EnumValue{..} = addToScope loc renamed acc
+          where
+            renamed = renameEnumAlt opts enum evName
+            loc = lLocation $ evlName evLoc
+    insertC m (D_Const Const{..}) = do
+      ty <- runTypechecker env $ resolveAnnotatedType constType
+      let renamed = renameConst opts constName
+      insertContext loc constName renamed (ty, mkName constName renamed, loc) m
+      where
+        env = (emptyEnv (thriftName, opts))
+          { typeMap   = tmap
+          , constMap  = m
+          , importMap = imap
+          }
+        loc = lLocation $ clName constLoc
+    insertC m D_Service{} = pure m
+    insertC m D_Interaction{} = pure m
+
+getEnumType :: Typecheckable l => Options l -> Parsed Enum -> Some (Type l)
+getEnumType opts enum@Enum{..} = case enumFlavourTag opts enum of
+  PseudoEnum{} -> Some $ TNewtype name enumValueType loc
+  SumTypeEnum noUnknown -> Some $ TEnum name loc noUnknown
+  where
+    name = mkName enumName $ renameEnum opts enum
+    loc = lLocation (slName enumLoc)
+
+-- Typecheck Constants ---------------------------------------------------------
+
+typecheckConst
+   :: Typecheckable l
+   => Type l t
+   -> UntypedConst Loc
+   -> TC l (TypedConst l t)
+
+-- Integral Types
+-- Maybe we should do overflow checking here?
+typecheckConst I8  (UntypedConst _ (IntConst i _)) = literal $ fromIntegral i
+typecheckConst I16 (UntypedConst _ (IntConst i _)) = literal $ fromIntegral i
+typecheckConst I32 (UntypedConst _ (IntConst i _)) = literal $ fromIntegral i
+typecheckConst I64 (UntypedConst _ (IntConst i _)) = literal $ fromIntegral i
+
+-- Floating Point Types
+typecheckConst TDouble (UntypedConst _ (IntConst i _)) =
+  literal $ fromIntegral i
+typecheckConst TDouble (UntypedConst _ (DoubleConst d _)) = literal d
+typecheckConst TFloat (UntypedConst _ (IntConst i _)) = literal $ fromIntegral i
+typecheckConst TFloat (UntypedConst _ (DoubleConst d _)) =
+  literal $ double2Float d
+
+-- Other Base Types
+typecheckConst TBool (UntypedConst _ (IntConst i _))
+  | i == 0 = literal False
+  | i == 1 = literal True
+typecheckConst TBool (UntypedConst _ (BoolConst b)) = literal b
+typecheckConst TText (UntypedConst _ (StringConst s _)) = literal s
+typecheckConst TBytes (UntypedConst _ (StringConst s _)) =
+  literal $ encodeUtf8 s
+
+-- Recursive Types
+typecheckConst (TList u) (UntypedConst _ ListConst{..}) =
+  Literal . List <$> traverse (typecheckConst u . leElem) lvElems
+typecheckConst ty@(TList _) c@(UntypedConst l MapConst{mvElems=[]})  = do
+  Options{optsLenient} <- asks options
+  if optsLenient then
+    return $ Literal $ List [] -- weird files use the wrong empty brackets, sigh
+  else
+    typeError (lLocation l) (LiteralMismatch ty c)
+typecheckConst (TSet u) (UntypedConst _ ListConst{..}) =
+  Literal . Set <$> traverse (typecheckConst u . leElem) lvElems
+typecheckConst ty@(TSet _) c@(UntypedConst l MapConst{mvElems=[]}) = do
+  Options{optsLenient} <- asks options
+  if optsLenient then
+    return $ Literal $ Set [] -- weird files use the wrong empty brackets, sigh
+  else
+    typeError (lLocation l) (LiteralMismatch ty c)
+typecheckConst (THashSet u) (UntypedConst _ ListConst{..}) =
+  Literal . HashSet <$> traverse (typecheckConst u . leElem) lvElems
+typecheckConst ty@(THashSet _) c@(UntypedConst l MapConst{mvElems=[]}) = do
+  Options{optsLenient} <- asks options
+  if optsLenient then
+    return $ Literal $ HashSet [] -- weird files use the wrong empty brackets
+  else
+    typeError (lLocation l) (LiteralMismatch ty c)
+typecheckConst (TMap kt vt) (UntypedConst _ MapConst{..}) = do
+  Options{optsLenient} <- asks options
+  Literal . Map <$> traverseWeird optsLenient tcConsts mvElems
+    where
+      tcConsts ListElem{leElem=MapPair{..}} = (,)
+        <$> typecheckConst kt mpKey
+        <*> typecheckConst vt mpVal
+typecheckConst ty@(TMap _ _) c@(UntypedConst l ListConst{lvElems=[]}) = do
+  Options{optsLenient} <- asks options
+  if optsLenient then
+    return $ Literal $ Map [] -- weird files use the wrong empty brackets, sigh
+  else
+    typeError (lLocation l) (LiteralMismatch ty c)
+typecheckConst (THashMap kt vt) (UntypedConst _ MapConst{..}) =
+  Literal . HashMap <$> traverse tcConsts mvElems
+    where
+      tcConsts ListElem{leElem=MapPair{..}} = (,)
+        <$> typecheckConst kt mpKey
+        <*> typecheckConst vt mpVal
+typecheckConst ty@(THashMap _ _) c@(UntypedConst l ListConst{lvElems=[]}) = do
+  Options{optsLenient} <- asks options
+  if optsLenient then
+    return $ Literal $ HashMap [] -- weird files use the wrong empty brackets
+  else
+    typeError (lLocation l) (LiteralMismatch ty c)
+
+-- Enums
+typecheckConst e@(TEnum Name{..} _loc _)
+               lit@(UntypedConst Located{..} (IntConst i _)) = do
+  (emap, _) <- lookupEnum sourceName lLocation
+  case Map.lookup (fromIntegral i) emap of
+    Nothing -> typeError lLocation $ LiteralMismatch e lit
+    Just (constName, constLoc) -> literal $ EnumVal constName constLoc
+typecheckConst enum@(TEnum name _loc _)
+               (UntypedConst Located{..} (IdConst ident)) =
+  typecheckEnum enum lLocation name ident <|>
+    typecheckIdent enum lLocation ident
+
+-- Typedefs
+typecheckConst (TTypedef _ ty _loc) val = typecheckConst ty val
+
+-- Newtypes
+-- This case is a bit complicated
+typecheckConst newt@(TNewtype name ty _loc) val@(UntypedConst Located{..} c) =
+   case c of
+     -- If it's an identifier, then it needs to be an exact type match,
+     -- however IdConsts can also be enums, so we have to check for this case
+     -- too
+     IdConst ident ->
+       typecheckPseudoEnum newt lLocation name ident <|>
+       typecheckIdent newt lLocation ident <|>
+       (liftNew =<< typecheckConst ty val)
+     _ -> liftNew =<< typecheckConst ty val
+  where
+    -- Lift literals into the newtype, but reject identifiers
+    liftNew (Literal lit) = literal $ New lit
+    liftNew (Identifier Name{..} u _loc) =
+      typeError lLocation $ IdentMismatch newt u sourceName
+    liftNew (WeirdEnumToInt u Name{..} _tyEnum _loc) =
+      typeError lLocation $ IdentMismatch newt u sourceName
+
+-- Structs
+typecheckConst (TStruct Name{..} _loc)
+               (UntypedConst Located{..} MapConst{..}) = do
+  tschema <- lookupSchema sourceName lLocation
+  case tschema of
+    Some schema -> Literal . Some
+               <$> (typecheckStruct lLocation schema =<< mkFieldMap mvElems)
+typecheckConst tyTop@(TStruct Name{} _loc)
+               (UntypedConst Located{..} StructConst{..}) = do
+  -- First typecheck the struct with the type annotated then check this matches
+  -- the type given at the top level
+  svTypeName <- mkThriftName svType
+  tschema <- lookupSchemaRec svTypeName lLocation
+  ttyAnn <- lookupType svTypeName lLocation
+  case (tschema, ttyAnn) of
+    (Some schema, Some tyAnn) -> do
+      let struct = typecheckStruct lLocation schema =<< mkStructFieldMap svElems
+      case eqOrAlias tyTop tyAnn of
+        Just _ -> Literal . Some <$> struct
+        Nothing -> typeError lLocation $ TypeMismatch tyTop tyAnn
+typecheckConst (TException Name{..} _loc)
+               (UntypedConst Located{..} MapConst{..}) = do
+  tschema <- lookupSchema sourceName lLocation
+  case tschema of
+    Some schema -> Literal . Some . EV <$>
+                   (typecheckStruct lLocation schema =<< mkFieldMap mvElems)
+typecheckConst (TUnion n@Name{..} _loc) (UntypedConst uloc MapConst{..}) = do
+  thisschema <- lookupUnion sourceName (lLocation uloc)
+  -- Unions can only have one field
+  (utname, val) <-
+    case mvElems of
+      [ListElem{leElem=MapPair{..}}] -> pure (mpKey, mpVal)
+      l -> typeError (lLocation uloc) $ InvalidUnion n (length l)
+  fname <-
+    case utname of
+      UntypedConst _ (StringConst s _) -> pure s
+      v@(UntypedConst utloc _) -> typeError (lLocation utloc) $ InvalidField v
+  case thisschema of
+    Some schema -> Literal . Some <$> typecheckUnion schema fname val
+typecheckConst
+  tyTop@(TUnion n@Name{} _loc)
+  (UntypedConst Located{..} StructConst {..}) = do
+    -- Constant structs can be used for unions as well
+    svTypeName <- mkThriftName svType
+    tschema <- lookupUnion svTypeName lLocation
+    ttyAnn <- lookupType svTypeName lLocation
+    case (tschema, ttyAnn) of
+      (Some schema, Some tyAnn) -> case svElems of
+        [ListElem{leElem = StructPair{..}}] -> do
+          case eqOrAlias tyTop tyAnn of
+            Just _ -> Literal . Some <$> typecheckUnion schema spKey spVal
+            Nothing -> typeError lLocation $ TypeMismatch tyTop tyAnn
+        _ -> typeError lLocation $ InvalidUnion n $ length svElems
+
+-- Identifiers (typecheckIdentNum is not first parameter to <|>)
+-- These identified are permitted to be enums in lenient mode
+typecheckConst ty (UntypedConst Located{..} (IdConst ident)) = do
+  Env{..} <- ask
+  typecheckIdent ty lLocation ident
+    <|> typecheckIdentNum ty lLocation ident
+    <|> case ty of
+      I8 | optsLenient options -> typecheckEnumAsInt lLocation ident
+      I16 | optsLenient options -> typecheckEnumAsInt lLocation ident
+      I32 | optsLenient options -> typecheckEnumAsInt lLocation ident
+      I64 | optsLenient options -> typecheckEnumAsInt lLocation ident
+      _ -> empty
+
+-- Special Types
+typecheckConst (TSpecial ty) val = typecheckSpecialConst ty val
+
+-- Type Error
+typecheckConst ty val@(UntypedConst Located{..} _) =
+  typeError lLocation $ LiteralMismatch ty val
+
+-- Lenient mode only. Implicit cast from a qualified enum to an int
+typecheckEnumAsInt
+  :: Integral t
+  => Loc
+  -> Text
+  -> TC l (TypedConst l t)
+typecheckEnumAsInt loc ident = do
+  name <- mkThriftName ident
+  let
+    enumValue = case name of
+      UName e -> UName <$> extractEnumValue e
+      QName q e -> QName q <$> extractEnumValue e
+    extractEnumValue text = if Text.null v
+      then Nothing
+      else Just $ Text.drop 1 v
+      where (_nm, v) = Text.breakOn "." text
+  case enumValue of
+    Nothing -> empty
+    Just k -> do
+      i <- lookupEnumInt k loc
+      literal $ fromIntegral i
+
+-- NOTE: This function only handles identifiers that end in an enum value,
+-- not identifiers that are other constants. Those are handled in a
+-- separate typecheckIdent call in typecheckConst.
+-- Also, enumTy and enumTyName need to match.
+typecheckEnum
+  :: Typecheckable l
+  => Type l t
+  -> Loc
+  -> Name
+  -> Text
+  -> TC l (TypedConst l EnumVal)
+typecheckEnum enumTy loc enumTyName ident = do
+  -- Parse the identifier and look up its type.
+  (identTyName, identValue) <- parseIdentifier
+  identEnumType <- lookupType identTyName loc
+  -- Check whether this is the same type as
+  -- the declaration.
+  -- Explicit () needed to avoid type error about GADTs and "untouchable"
+  -- types.
+  () <- case identEnumType of
+    Some identEnumType' ->
+      case enumTy `eqOrAlias` identEnumType' of
+          Just Refl -> return ()
+          Nothing -> typeError loc $ TypeMismatch enumTy identEnumType'
+  -- Look up the enum values and see if `identValue` is one of them
+  (_, nameMap) <- lookupEnum (sourceName enumTyName) loc
+  case Map.lookup identValue nameMap of
+    Nothing -> typeError loc $ UnknownEnumValue (sourceName enumTyName)
+    Just (targetName, targetLoc) ->
+      return $ Literal $ EnumVal targetName targetLoc
+  where
+    parseIdentifier = do
+      -- This strips off the filename, if present, leaving us with either
+      -- <enum>.<value> or just <value>. The latter case is technically
+      -- out of spec, but it's out there, so we deal with it by substituting
+      -- the expected enum typename in.
+      tName <- mkThriftName ident
+      -- We use the OnEnd methods so that if there is no dot, the content
+      -- ends up in the suffix.
+      let (pre, value) = Text.breakOnEnd "." (localName tName)
+          enumName = if Text.null pre
+            then localName $ sourceName enumTyName
+            else Text.dropEnd 1 pre
+          tyName = mapName (const enumName) tName
+      return (tyName, value)
+
+
+typecheckPseudoEnum
+  :: (Typecheckable l)
+  => Type l t
+  -> Loc
+  -> Name
+  -> Text
+  -> TC l (TypedConst l t)
+typecheckPseudoEnum ty loc name@Name{..} ident = do
+  result <- typecheckEnum ty loc name ident
+  case result of
+    Literal (EnumVal renamed locDefined) -> do
+      thistrueTy <- lookupType sourceName loc
+      case thistrueTy of
+        Some trueTy -> case trueTy `eqOrAlias` ty of
+          Just Refl -> pure $ Identifier renamed ty locDefined
+          Nothing -> empty
+    _ -> empty
+
+-- | Handle weird case of enum to int casting, dispatch when 'ty' is int like.
+--
+-- Do not use as first parameter to '<|>'
+typecheckIdentNum
+   :: (Typecheckable l)
+   => Type l t
+   -> Loc
+   -> Text
+   -> TC l (TypedConst l t)
+typecheckIdentNum ty loc ident = case ty of
+  I8  -> typecheckEnumInt loc ident
+  I16 -> typecheckEnumInt loc ident
+  I32 -> typecheckEnumInt loc ident
+  I64 -> typecheckEnumInt loc ident
+  _ -> empty
+
+-- | This is used for int-like constants that might, werdly, get their value
+-- from an enum value (implicit casting is somewhay popular).  Use the
+-- usual typecheckIdent before attempting the enum lookup (made up rule that
+-- seems to work).
+--
+-- Do not use as first parameter to '<|>'
+typecheckEnumInt
+   :: (Typecheckable l, Num t)
+   => Loc
+   -> Text
+   -> TC l (TypedConst l t)
+typecheckEnumInt loc ident = do
+  Env{..} <- ask
+  if not (optsLenient options) then empty else do
+    name <- mkThriftName ident
+    i <- lookupEnumInt name loc
+    literal $ fromIntegral i
+
+-- | There a weird casting from enum to int that happens in libadmarket.thrift
+--
+-- > typedef i16 TimeZoneId
+-- > const time_zone.TimeZoneType kReachBlockTimeZoneEST =
+-- >    time_zone.TZ_AMERICA_NEW_YORK
+-- > const TimeZoneId kDefaultReachBlockTimeZoneId = kReachBlockTimeZoneEST
+--
+-- To support this in the parser check 'useEnumAsInt'
+typecheckIdent
+  :: Typecheckable l
+  => Type l t
+  -> Loc
+  -> Text
+  -> TC l (TypedConst l t)
+typecheckIdent ty loc ident = do
+  name <- mkThriftName ident
+  (thistrueTy, renamed, locDefined) <- lookupConst name loc
+  Env{..} <- ask
+  case thistrueTy of
+    Some trueTy -> case trueTy `eqOrAlias` ty of
+      Just Refl -> pure $ Identifier renamed ty locDefined
+      Nothing   ->
+        if not (optsLenient options) then
+          typeError loc $ IdentMismatch ty trueTy name
+        else case useEnumAsInt trueTy ty of
+          Nothing -> typeError loc $ IdentMismatch ty trueTy name
+          Just trueTyEnum ->
+            -- This is the one place where WeirdEnumToInt is constructed
+            pure $ WeirdEnumToInt ty renamed trueTyEnum locDefined
+
+-- | helper for 'typecheckIdent' in weird case
+useEnumAsInt
+  :: Typecheckable l
+  => Type l u -- ^ @t1@ : Checked againt TEnum, type of default or const value
+  -> Type l v -- ^ @t2@ : Checked against int types, type of target
+  -> Maybe (Type l EnumVal) -- ^ When Just this is a type-refined @t1@
+useEnumAsInt t1 t2 = case t1 of
+  TEnum{} -> case t2 of
+    I8 -> Just t1
+    I16 -> Just t1
+    I32 -> Just t1
+    I64 -> Just t1
+    _ -> Nothing
+  _ -> Nothing
+
+-- This tells if the two types are compatible. This means that they are either
+-- structurally equal or aliases
+-- NOTE: using annotations, you can create code that won't typecheck in the
+-- haskell compiler, but will typecheck in fbthrift
+eqOrAlias :: Typecheckable l => Type l u -> Type l v -> Maybe (u :~: v)
+-- Typedefs are equal if they are aliases of the other type
+eqOrAlias (TTypedef _ u _loc) v = eqOrAlias u v
+eqOrAlias u (TTypedef _ v _loc) = eqOrAlias u v
+-- Newtypes may be lifted
+eqOrAlias (TNewtype n1 u _loc1) (TNewtype n2 v _loc2)
+  | n1 == n2  = apply Refl <$> eqOrAlias u v
+  | otherwise = Nothing
+eqOrAlias TNewtype{} _ = Nothing
+-- Base types only equal themselves
+eqOrAlias I8  I8  = Just Refl
+eqOrAlias I8  _   = Nothing
+eqOrAlias I16 I16 = Just Refl
+eqOrAlias I16 _   = Nothing
+eqOrAlias I32 I32 = Just Refl
+eqOrAlias I32 _   = Nothing
+eqOrAlias I64 I64 = Just Refl
+eqOrAlias I64 _   = Nothing
+eqOrAlias TFloat TFloat = Just Refl
+eqOrAlias TFloat _      = Nothing
+eqOrAlias TDouble TDouble = Just Refl
+eqOrAlias TDouble _       = Nothing
+eqOrAlias TBool TBool = Just Refl
+eqOrAlias TBool _     = Nothing
+eqOrAlias TText TText = Just Refl
+eqOrAlias TText _     = Nothing
+eqOrAlias TBytes TBytes = Just Refl
+eqOrAlias TBytes _      = Nothing
+-- Recursive types must be deeply equal
+eqOrAlias (TSet u) (TSet v) = apply Refl <$> eqOrAlias u v
+eqOrAlias TSet{} _ = Nothing
+eqOrAlias (THashSet u) (THashSet v) = apply Refl <$> eqOrAlias u v
+eqOrAlias THashSet{} _ = Nothing
+eqOrAlias (TList u) (TList v) = apply Refl <$> eqOrAlias u v
+eqOrAlias TList{} _ = Nothing
+eqOrAlias (TMap k1 v1) (TMap k2 v2) =
+  apply <$> (apply Refl <$> eqOrAlias k1 k2) <*> eqOrAlias v1 v2
+eqOrAlias TMap{} _ = Nothing
+eqOrAlias (THashMap k1 v1) (THashMap k2 v2) =
+  apply <$> (apply Refl <$> eqOrAlias k1 k2) <*> eqOrAlias v1 v2
+eqOrAlias THashMap{} _ = Nothing
+-- Named types must have the same name
+eqOrAlias (TStruct n1 _loc1) (TStruct n2 _loc2) | n1 == n2 = Just Refl
+eqOrAlias TStruct{} _ = Nothing
+eqOrAlias (TException n1 _loc1) (TException n2 _loc2) | n1 == n2 = Just Refl
+eqOrAlias TException{} _ = Nothing
+eqOrAlias (TUnion n1 _loc1) (TUnion n2 _loc2) | n1 == n2 = Just Refl
+eqOrAlias TUnion{} _ = Nothing
+eqOrAlias (TEnum n1 _loc1 _) (TEnum n2 _loc2 _) | n1 == n2 = Just Refl
+eqOrAlias TEnum{} _ = Nothing
+eqOrAlias (TSpecial u) (TSpecial v) = eqSpecial u v
+eqOrAlias TSpecial{} _ = Nothing
+
+-- Note that the type parameters are the same here. This is very important as
+-- the aliased type must be equal to the original type
+getAliasedType :: Type l t -> Type l t
+getAliasedType (TTypedef _ ty _loc) = getAliasedType ty
+getAliasedType ty = ty
+
+lookupSchemaRec :: ThriftName -> Loc -> TC l (Some (Schema l))
+lookupSchemaRec name loc = do
+  thisty <- lookupType name loc
+  case thisty of
+    Some ty -> do
+      let nm = case getAliasedType ty of
+            TStruct Name{..} _ -> sourceName
+            _ -> name
+      lookupSchema nm loc
+
+mkFieldMap
+  :: [ListElem MapPair Loc]
+  -> TC l (Map.Map Text (UntypedConst Loc))
+mkFieldMap = fmap Map.fromList . traverse getName
+  where
+    getName ListElem{ leElem = MapPair{..} } = case mpKey of
+      UntypedConst _ (StringConst s _) -> pure (s, mpVal)
+      val@UntypedConst{..} -> typeError (lLocation ucLoc) $ InvalidField val
+
+mkStructFieldMap
+  :: [ListElem StructPair Loc]
+  -> TC l (Map.Map Text (UntypedConst Loc))
+mkStructFieldMap = fmap Map.fromList . traverse getName
+  where
+    getName ListElem{ leElem = StructPair{..} } =
+      pure (spKey, spVal)
+
+-- Given a schema, this function proves that the resulting
+-- StructVal adheres to that schema
+typecheckStruct
+  :: Typecheckable l
+  => Loc
+  -> Schema l s
+  -> Map.Map Text (UntypedConst Loc)
+  -> TC l (StructVal l s)
+
+-- Empty schema only matches empty map
+typecheckStruct loc SEmpty fields =
+  case Map.keys fields of
+    [] -> pure Empty
+    k : _ -> typeError loc $ UnknownField k
+
+-- Default Field
+typecheckStruct loc (SField proxy fname ty schema) fields =
+  case Map.lookup fname fields of
+    Nothing ->
+      ConsDefault proxy ty <$> typecheckStruct loc schema fields
+    Just val -> ConsVal proxy ty
+                <$> typecheckConst ty val
+                <*> typecheckStruct loc schema (Map.delete fname fields)
+
+-- Required Field must be present
+typecheckStruct loc (SReqField proxy fname ty schema) fields =
+  case Map.lookup fname fields of
+    Nothing  -> typeError loc $ MissingField fname
+    Just val -> ConsVal proxy ty
+                <$> typecheckConst ty val
+                <*> typecheckStruct loc schema (Map.delete fname fields)
+
+-- Optional field may be missing
+typecheckStruct loc (SOptField proxy fname ty schema) fields =
+  mkCons
+  <$> sequence (typecheckConst ty <$> Map.lookup fname fields)
+  <*> typecheckStruct loc schema (Map.delete fname fields)
+  where
+    mkCons (Just val) struct = ConsJust proxy ty val struct
+    mkCons Nothing struct = ConsNothing proxy struct
+
+typecheckUnion
+  :: Typecheckable l
+  => USchema l s
+  -> Text
+  -> UntypedConst Loc
+  -> TC l (UnionVal l s)
+typecheckUnion SEmpty name UntypedConst{..} =
+  typeError (lLocation ucLoc) $ UnknownField name
+typecheckUnion (SReqField proxy fname ty schema) name val
+  | fname == name = do
+    tval <- typecheckConst ty val
+    pure $ UnionVal proxy ty tval PHere
+  | otherwise = do
+    UnionVal p t v proof <- typecheckUnion schema name val
+    pure $ UnionVal p t v (PThere proof)
+
+literal :: t -> TC l (TypedConst l t)
+literal = pure . Literal
+
+insertContext
+  :: Loc
+  -> Text -- ^ Thrift Name
+  -> Text -- ^ Renamed Name
+  -> a
+  -> Context a
+  -> Either [TypeError l] (Context a)
+insertContext loc tName lName v ctx@Context{..}
+  | Map.member tName cMap ||
+    Set.member lName cScope = Left [TypeError loc $ DuplicateName tName]
+  | otherwise = Right $ ctx { cMap   = Map.insert tName v cMap
+                            , cScope = Set.insert lName cScope
+                            }
+insertUnique
+  :: Loc -> Text -> a -> Map.Map Text a -> Either [TypeError l] (Map.Map Text a)
+insertUnique loc k v m
+  | Map.member k m = Left [TypeError loc $ DuplicateName k]
+  | otherwise      = Right $ Map.insert k v m
+
+addToScope :: Loc -> Text -> Context a -> Either [TypeError l] (Context a)
+addToScope loc x ctx@Context{..}
+  | Set.member x cScope = Left [TypeError loc $ DuplicateName x]
+  | otherwise = Right ctx { cScope = Set.insert x cScope }
+
+-- Resolve Named Types ---------------------------------------------------------
+
+-- Create a map from all named types to their resolved type
+
+mkTypemap
+  :: forall l. Typecheckable l
+  => (Text, Options l)
+  -> ImportMap l
+  -> [Parsed Decl]
+  -> Either [TypeError l] (TypeMap l)
+mkTypemap (thriftName, opts) imap =
+    foldM resolve emptyContext <=< sortDecls
+  where
+    resolve :: TypeMap l -> Parsed Decl -> Either [TypeError l] (TypeMap l)
+    resolve m (D_Typedef t@Typedef{..}) = do
+      tdef <- mkTypedef <$> runTypechecker env (resolveAnnotatedType tdType)
+      insertContext loc tdName hsname tdef m
+        where
+          loc = lLocation (tdlName tdLoc)
+          env = (emptyEnv (thriftName, opts))
+            { typeMap   = m
+            , importMap = imap
+            }
+          uname = mkName tdName hsname
+          hsname = renameTypedef opts t
+          mkTypedef :: Some (Type l) -> Some (Type l)
+          mkTypedef (Some u)
+            | isNewtype (getAnns tdAnns) = Some $ TNewtype uname u loc
+            -- Other annotations will be checked in resolveTypedef
+            | otherwise = Some $ TTypedef uname u loc
+    resolve m (D_Struct s@Struct{..}) =
+      insertContext (lLocation $ slName structLoc) structName hsname structTy m
+        where
+          loc = lLocation (slName structLoc)
+          uname = mkName structName hsname
+          hsname = renameStruct opts s
+          structTy =
+            case structType of
+              StructTy    -> Some $ TStruct uname loc
+              ExceptionTy -> Some $ TException uname loc
+    resolve m (D_Union u@Union{..}) =
+      insertContext (lLocation $ slName unionLoc) unionName hsname
+      (Some $ TUnion uname loc) m
+      where
+        loc = lLocation (slName unionLoc)
+        uname = mkName unionName hsname
+        hsname = renameUnion opts u
+    resolve m (D_Enum e@Enum{..}) =
+      insertContext (lLocation $ slName enumLoc) enumName (renameEnum opts e)
+      (getEnumType opts e) m
+    resolve m D_Const{} = pure m
+    resolve m D_Service{} = pure m
+    resolve m D_Interaction{} = pure m
+
+-- Topologically sort the Decls based on dependencies
+-- This function will fail if there is a cycle
+sortDecls :: [Parsed Decl] -> Either [TypeError l] [Parsed Decl]
+sortDecls decls = traverse getVertex sccs
+  where
+    sccs  = stronglyConnComp graph
+    graph = mapMaybe mkVertex decls
+    -- Convert a Decl into a vertex in the graph
+    mkVertex d@(D_Typedef Typedef{..}) = Just (d, tdName, getEdges tdType)
+    mkVertex d@(D_Struct Struct{..})   = Just (d, structName, [])
+    mkVertex d@(D_Union Union{..})     = Just (d, unionName, [])
+    mkVertex d@(D_Enum Enum{..})       = Just (d, enumName, [])
+    mkVertex D_Const{}   = Nothing
+    mkVertex D_Service{} = Nothing
+    mkVertex D_Interaction{} = Nothing
+    -- Find the dependencies of a type
+    getEdges :: AnnotatedType Loc t -> [Text]
+    getEdges AnnotatedType{..} =
+      case atType of
+        TNamed name -> [name]
+        TSet u      -> getEdges u
+        TList u     -> getEdges u
+        TMap k v    -> getEdges k ++ getEdges v
+        _           -> []
+    -- Get the vertex our of an SCC
+    getVertex (AcyclicSCC v) = Right v
+    getVertex (CyclicSCC vs@(d:_)) =
+      Left [TypeError (getLoc d) $ CyclicTypes vs]
+    -- This case should not be possible, but we are using an external library,
+    -- so there is no type-level way to enforce it
+    getVertex (CyclicSCC []) = Left []
+
+resolveAnnotatedType
+  :: forall l t. Typecheckable l
+  => AnnotatedType Loc t
+  -> TC l (Some (Type l))
+resolveAnnotatedType AnnotatedType{..} =
+  resolveType atType atLoc atAnnotations
+
+resolveType
+  :: forall l t n. Typecheckable l
+  => TType 'Unresolved () Loc t
+  -> TypeLoc n Loc
+  -> Maybe (Annotations Loc)
+  -> TC l (Some (Type l))
+resolveType atType atLoc atAnnotations =
+  case atType of
+    -- Resolving base types is trivial
+    I8      -> annotate I8
+    I16     -> annotate I16
+    I32     -> annotate I32
+    I64     -> annotate I64
+    TDouble -> annotate TDouble
+    TFloat  -> annotate TFloat
+    TText   -> annotate TText
+    TBytes  -> annotate TBytes
+    TBool   -> annotate TBool
+    -- Rescursive types must be resolved recursively
+    TSet u     -> resolve TSet u
+    THashSet u -> resolve THashSet u
+    TList u    -> resolve TList u
+    TMap k v -> do
+      thisrk <- resolveAnnotatedType k
+      thisrv <- resolveAnnotatedType v
+      case (thisrk, thisrv) of
+        (Some rk, Some rv) -> annotate $ TMap rk rv
+    THashMap k v -> do
+      thisrk <- resolveAnnotatedType k
+      thisrv <- resolveAnnotatedType v
+      case (thisrk, thisrv) of
+        (Some rk, Some rv) -> annotate $ THashMap rk rv
+    -- Named type may not be resolvable
+    TNamed name -> do
+      qname <- mkThriftName name
+      lookupType qname (getTypeLoc atLoc)
+  where
+    annotate :: Type l u -> TC l (Some (Type l))
+    annotate ty = resolveTypeAnnotations ty $ getAnns atAnnotations
+
+    resolve
+      :: (forall v. Type l v -> Type l (s v))
+      -> AnnotatedType Loc u
+      -> TC l (Some (Type l))
+    resolve mkType u = resolveAnnotatedType u >>=
+      \(Some v) -> annotate (mkType v)
+
+mkThriftName :: Text -> TC l ThriftName
+mkThriftName text
+  | Text.null suff = pure $ UName pre -- obviously undotted unqualified name
+  | otherwise = do
+      Env{..} <- ask
+      if
+        | Map.member pre importMap ->
+            pure $ QName pre (Text.drop 1 suff) -- directly included qname
+        | not (optsLenient options) ->
+            pure $ UName text -- pass through the dotted name, might be enum
+        | envName /= pre ->
+            pure $ UName text -- pass through the dotted name, might be enum
+        | otherwise ->
+            -- some weird code uses its own filename as qualifier
+            -- handle this by pretending the unwanted 'pre' is not there
+            pure $ UName (Text.drop 1 suff)
+  where (pre, suff) = Text.breakOn "." text
+
+
+-- Build Schemas ---------------------------------------------------------------
+
+mkSchemaMap
+  :: Typecheckable l
+  => (Text, Options l)
+  -> ImportMap l
+  -> TypeMap l
+  -> [Parsed Struct]
+  -> Either [TypeError l] (SchemaMap l)
+mkSchemaMap (thriftName, opts) imap tmap = foldM insertSchema Map.empty
+  where
+    insertSchema m s@Struct{..} = do
+      ty <- runTypechecker env (mkSchema s)
+      insertUnique (lLocation $ slName structLoc) structName ty m
+      where
+        env = (emptyEnv (thriftName, opts))
+                { typeMap   = tmap
+                , schemaMap = m
+                , importMap = imap
+                }
+
+mkSchema :: Typecheckable l => Parsed Struct -> TC l (Some (Schema l))
+mkSchema Struct{..} = buildSchema structMembers
+  where
+    buildSchema (field@Field{..} : fields) = do
+      (rty, tschema) <- (,)
+        <$> resolveAnnotatedType fieldType
+        <*> buildSchema fields
+      opts <- options <$> ask
+      let renamed =
+            Text.unpack $ renameField opts (getAnns structAnns) structName field
+      case (someSymbolVal renamed, rty, tschema) of
+       (SomeSymbol proxy, Some ty, Some schema) ->
+          case fieldRequiredness of
+            Default ->
+              pure . Some $
+              SField proxy fieldName ty schema
+            Optional{} -> pure . Some $ SOptField proxy fieldName ty schema
+            Required{} -> pure . Some $ SReqField proxy fieldName ty schema
+    buildSchema [] = pure $ Some SEmpty
+
+mkUnionMap
+  :: Typecheckable l
+  => (Text, Options l)
+  -> ImportMap l
+  -> TypeMap l
+  -> [Parsed Union]
+  -> Either [TypeError l] (UnionMap l)
+mkUnionMap (thriftName, opts) imap tmap  = foldM insertSchema Map.empty
+  where
+    insertSchema m u@Union{..} = do
+      schema <- runTypechecker env (mkUSchema u)
+      insertUnique (lLocation $ slName unionLoc) unionName schema m
+      where env = (emptyEnv (thriftName, opts))
+                  { typeMap   = tmap
+                  , unionMap  = m
+                  , importMap = imap
+                  }
+
+mkUSchema
+  :: Typecheckable l => Parsed Union -> TC l (Some (USchema l))
+mkUSchema u@Union{..} =
+  foldM buildSchema (Some SEmpty) unionAlts
+  where
+    buildSchema (Some schema) alt@UnionAlt{..} = do
+      rty <- resolveAnnotatedType altType
+      opts <- options <$> ask
+      let renamed = Text.unpack $ renameUnionAlt opts u alt
+      case (someSymbolVal renamed, rty) of
+        (SomeSymbol proxy, Some ty) ->
+          pure . Some $ SReqField proxy altName ty  schema
+
+-- We need the enums to be resolved in order to build the map because we need to
+-- know the numeric values for each field
+mkEnumMap :: Typecheckable l => Options l -> [Parsed Enum] -> EnumMap
+mkEnumMap opts = Map.fromList . map mkAssoc
+  where
+    mkAssoc :: Parsed Enum -> (Text, EnumValues)
+    mkAssoc e@Enum{..} = (enumName, enumValues)
+      where
+        enumValues =
+          ( Map.fromList
+            [(evValue, (rename evName, lLocation (evlName evLoc)))
+            | EnumValue{..} <- enumConstants]
+          , Map.fromList
+            [ (evName, (rename evName, lLocation (evlName evLoc)))
+            | EnumValue{..} <- enumConstants
+            ]
+          )
+        rename name = mkName name $ renameEnumAlt opts e name
+
+-- Build EnumInt Map -----------------------------------------------------------
+
+-- | When lenient mode is active (argument @--lenient@) then capture the enum
+-- values into 'imap' so they can be used as default integer values.
+mkEnumInt:: Typecheckable l => Options l -> [Parsed Enum] -> EnumInt
+mkEnumInt opts
+    | optsLenient opts = Map.unionsWith safe . map mkOne
+    | otherwise = mempty
+  where
+    mkOne :: Parsed Enum -> EnumInt
+    mkOne Enum{..} = Map.fromListWith safe
+      [ (evName, Just evValue)
+      | EnumValue{..} <- enumConstants
+      ]
+
+    safe (Just new) j@(Just old) | new == old = j -- collision but no ambiguity
+    safe _new _old = Nothing -- collision with ambiguity, set to Nothing
+
+-- Build Service Map -----------------------------------------------------------
+
+mkServiceMap
+  :: Typecheckable l
+  => (Text, Options l)
+  -> ImportMap l
+  -> [Parsed Service]
+  -> Either [TypeError l] ServiceMap
+mkServiceMap (thriftName, opts) imap =
+    foldM addToMap Map.empty <=< sortServices
+  where
+    addToMap ctx s@Service{..} = do
+      scope <- mkScope ctx s
+      let renamed = mkName serviceName $ renameService opts s
+          loc = sloc serviceLoc
+      insertUnique loc serviceName (renamed, scope, loc) ctx
+    addToSet loc x s
+      | Set.member x s = Left [TypeError loc (DuplicateName x)]
+      | otherwise      = pure $ Set.insert x s
+    mkScope ctx Service{..} = do
+      let env = (emptyEnv (thriftName, opts))
+                  { importMap = imap
+                  , serviceMap = ctx
+                  }
+      scope <-
+        case serviceSuper of
+          Nothing -> pure Set.empty
+          Just Super{..} -> runTypechecker env $ do
+            name <- mkThriftName supName
+            (\(_, setFuns, _) -> setFuns) <$>
+              lookupService name (sloc serviceLoc)
+      foldM insFunc scope serviceStmts
+    insFunc ctx (FunctionStmt f@Function{..}) =
+      addToSet (lLocation $ fnlName funLoc) renamed ctx
+      where renamed = renameFunction opts f
+    insFunc ctxt _ = Right ctxt
+    sloc = lLocation . slName
+
+sortServices
+  :: [Parsed Service] -> Either [TypeError l] [Parsed Service]
+sortServices services = traverse getVertex sccs
+  where
+    sccs  = stronglyConnComp graph
+    graph = map mkVertex services
+    mkVertex s@Service{..} =
+      (s, serviceName, maybeToList $ supName <$> serviceSuper)
+    getVertex (AcyclicSCC s) = pure s
+    getVertex (CyclicSCC ss@(Service{..}:_)) =
+      Left [TypeError (lLocation $ slName serviceLoc) (CyclicServices ss)]
+    getVertex (CyclicSCC []) = Left []
diff --git a/Thrift/Compiler/Typechecker/Monad.hs b/Thrift/Compiler/Typechecker/Monad.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Typechecker/Monad.hs
@@ -0,0 +1,200 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PolyKinds #-}
+{-# OPTIONS_GHC -Wno-star-is-type #-}
+module Thrift.Compiler.Typechecker.Monad
+  ( TC, Typechecked
+  , typeError, runTypechecker, ask, asks, traverseWeird
+  , Alternative(..)
+  , lookupType, lookupSchema, lookupUnion, lookupEnum, lookupConst
+  , lookupService, lookupEnumInt
+  , TypeError(..), ErrorMsg(..), AnnotationPlacement(..)
+  , orderError
+  ) where
+
+import Prelude hiding (Enum)
+import Control.Applicative
+import Data.Either ( rights )
+import Data.Int (Int32)
+import Data.Some
+import Data.Text (Text)
+import Control.Monad.Reader
+import qualified Data.Map.Strict as Map
+import qualified Data.Set as Set
+
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Types
+
+-- Typechecking Monad ----------------------------------------------------------
+
+-- The typechecking monad is a reader transformed either monad. This allows us
+-- to keep track of state and errors
+newtype TC l a = TC (ReaderT (Env l) (Either [TypeError l]) a)
+  deriving (Functor,Monad, MonadReader (Env l))
+
+instance Applicative (TC l) where
+  pure a = TC (pure a)
+  -- | Special Applicative instance which allows us to collect
+  -- type errors from *both* parts of the computation in the
+  -- event that they both fail.
+  TC (ReaderT rf) <*> TC (ReaderT rx) =
+    TC $ ReaderT $ \env -> rf env `collect` rx env
+    where
+        collect (Left e1) (Left e2) = Left $ e1 <> e2
+        collect (Left e)  (Right _) = Left e
+        collect (Right _) (Left e)  = Left e
+        collect (Right f) (Right x) = Right $ f x
+
+type Typechecked (l :: *) (t :: Status -> * -> * -> *) =
+  TC l (t 'Resolved l Loc)
+
+typeError :: Loc -> ErrorMsg l -> TC l a
+typeError loc msg = TC $ lift $ Left [TypeError loc msg]
+
+runTypechecker :: Env l -> TC l a -> Either [TypeError l] a
+runTypechecker env (TC t) = runReaderT t env
+
+instance Alternative (TC l) where
+  -- This produces an empty list of errors, so should never be used as the
+  -- first parater of '<|>'.
+  empty = TC $ lift (Left [])
+  t1 <|> t2 = TC $ do
+    env <- ask
+    lift $ case runTypechecker env t1 of
+      Left err1 -> case runTypechecker env t2 of
+        Left err2 -> Left (err1 <> err2)
+        x2@Right{} -> x2
+      x1@Right{} -> x1
+
+-- | See T45688659 for the weird tale of how badly-typed keys are getting
+-- ignored.  Try to be similar here, in weird mode, by dropping errors.
+traverseWeird :: Bool -> (a -> TC l b) -> [a] -> TC l [b]
+traverseWeird optsLenient f xs = do
+    if not optsLenient then
+      traverse f xs
+    else
+      TC $ ReaderT $ \env -> Right (mapEWeird (runTypechecker env . f) xs)
+  where
+    mapEWeird :: (a -> Either [e] b) -> [a] -> [b]
+    mapEWeird ff = rights . map ff
+
+-- Lookup Functions ------------------------------------------------------------
+
+lookupType :: ThriftName -> Loc -> TC l (Some (Type l))
+lookupType = envCtxLookup typeMap UnknownType
+
+lookupSchema :: ThriftName -> Loc -> TC l (Some (Schema l))
+lookupSchema = envLookup schemaMap UnknownType
+
+lookupUnion :: ThriftName -> Loc -> TC l (Some (USchema l))
+lookupUnion = envLookup unionMap UnknownType
+
+lookupEnum :: ThriftName -> Loc -> TC l EnumValues
+lookupEnum = envLookup enumMap UnknownType
+
+-- | Allow enum values as default values for int fields.
+-- This is a type violation.  This is added to allow parsing these old files
+-- when @--lenient@ mode is active (see 'Options.optsLenient').
+lookupEnumInt :: ThriftName -> Loc -> TC l Int32
+lookupEnumInt name loc = do
+  valueOrCollision <- envLookup enumInt UnknownEnumValue name loc
+  case valueOrCollision of
+    Just value -> pure value
+    Nothing -> typeError loc $ MultipleEnumValues name
+
+-- | Loc parameter of usage of ThriftName is for error messages.
+-- Loc in result is where ThriftName was defined.
+lookupConst :: ThriftName -> Loc -> TC l (Some (Type l), Name, Loc)
+lookupConst = envCtxLookup constMap UnknownConst
+
+-- | Loc parameter of usage of ThriftName is for error messages.
+-- Loc in result is where ThriftName was defined.
+lookupService :: ThriftName -> Loc -> TC l (Name, Set.Set Text, Loc)
+lookupService = envLookup serviceMap UnknownService
+
+envLookup
+  :: (Env l -> Map.Map Text u)
+  -> (ThriftName -> ErrorMsg l)
+  -> ThriftName
+  -> Loc
+  -> TC l u
+envLookup getMap mkError name loc = do
+  env <- TC ask
+  case doLookup env name of
+    Nothing -> typeError loc $ mkError name
+    Just u  -> pure u
+  where
+    doLookup env (UName n) = Map.lookup n (getMap env)
+    doLookup env (QName m n) =
+      Map.lookup n . getMap =<< Map.lookup m (importMap env)
+
+envCtxLookup
+  :: (Env l -> Context u)
+  -> (ThriftName -> ErrorMsg l)
+  -> ThriftName
+  -> Loc
+  -> TC l u
+envCtxLookup getMap mkError name loc = do
+  env <- TC ask
+  case doLookup env name of
+    Nothing -> typeError loc $ mkError name
+    Just u  -> pure u
+  where
+    doLookup env (UName n) = Map.lookup n (cMap $ getMap env)
+    doLookup env (QName m n) =
+      Map.lookup n . cMap . getMap =<< Map.lookup m (importMap env)
+
+-- Type Errors -----------------------------------------------------------------
+
+data TypeError l
+  -- Intra-Modular Type Errors
+  = TypeError Loc (ErrorMsg l)
+  -- Inter-Modular Errors
+  | EmptyInput
+  | CyclicModules [ThriftFile SpliceFile Loc]
+
+data ErrorMsg l
+  = CyclicTypes [Parsed Decl]
+  | CyclicServices [Parsed Service]
+  | UnknownType ThriftName
+  | UnknownConst ThriftName
+  | UnknownService ThriftName
+  | UnknownEnumValue ThriftName
+  | MultipleEnumValues ThriftName
+  | forall t. LiteralMismatch (Type l t) (UntypedConst Loc)
+  | forall u v. IdentMismatch (Type l u) (Type l v) ThriftName
+  | UnknownField Text
+  | MissingField Text
+  | InvalidFieldId Text Int
+  | InvalidField (UntypedConst Loc)
+  | InvalidUnion Name Int
+  | EmptyUnion Text
+  | forall t. InvalidThrows (Type l t) Text
+  | AnnotationMismatch (AnnotationPlacement l) (Annotation Loc)
+  | DuplicateName Text
+  | DuplicateEnumVal Text [Text] Int
+  | forall t1 t2. TypeMismatch (Type l t1) (Type l t2)
+  | forall t. NotDefinedBeforeUsed (Type l t)
+
+data AnnotationPlacement l
+  = forall t. AnnType (Type l t)
+  | AnnField | AnnStruct | AnnUnion | AnnTypedef | AnnEnum | AnnPriority
+
+orderError :: TypeError l -> TypeError l -> Ordering
+-- EmptyInput always comes first
+orderError EmptyInput EmptyInput = EQ
+orderError EmptyInput _ = LT
+orderError _ EmptyInput = GT
+-- CyclicModules comes next
+orderError CyclicModules{} CyclicModules{} = EQ
+orderError CyclicModules{} _ = LT
+orderError _ CyclicModules{} = GT
+-- Type Errors are ordered by Loc
+orderError (TypeError l1 _) (TypeError l2 _) = compare l1 l2
diff --git a/Thrift/Compiler/Types.hs b/Thrift/Compiler/Types.hs
new file mode 100644
--- /dev/null
+++ b/Thrift/Compiler/Types.hs
@@ -0,0 +1,893 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# OPTIONS_GHC -Wno-star-is-type #-}
+module Thrift.Compiler.Types
+  ( Status(..), IfResolved, Parsed
+  , Program(..), Header(..), ParsedStatement(..), IncludeType(..), Decl(..), SpliceFile
+  , Loc(..), noLoc, nlc, Comment(..), Located(..)
+  , Separator(..), getSepLoc
+  , Annotations(..), Annotation(..), AnnValue(..), getAnns, annLoc
+  , StructuredAnnotation(..), StructuredAnnotationElems(..)
+  , ThriftPriority(..)
+  , Env(..), emptyEnv, Context(..), emptyContext
+  , TypeMap, SchemaMap, UnionMap, EnumMap, ConstMap, ServiceMap, ImportMap
+  , EnumValues, EnumInt
+  , Typedef(..), TypedefTag(..), TypedefLoc(..)
+  , Const(..), ConstLoc(..)
+  , UntypedConst(..), ConstVal(..), ListElem(..), MapPair(..), QuoteType(..)
+  , StructPair (..)
+  , TypedConst(..)
+  , List(..), Set(..), HashSet(..), Map(..), HashMap(..), EnumVal(..), New(..)
+  , StructVal(..), ExceptionVal(..), UnionVal(..), MembershipProof(..)
+  , Struct(..), StructType(..), StructLoc(..), ErrorClassification(..)
+  , ErrorClassificationType(..)
+  , Field(..), FieldLoc(..), FieldType(..), FieldTag(..), FieldId
+  , Requiredness(..), Laziness(..)
+  , Union(..), UnionAlt(..), PossiblyEmpty(..), EmptyName
+  , Enum(..), EnumFlavour(..), EnumValue(..), EnumValLoc(..)
+  , EnumValueType, enumValueType
+  , Service(..), Super(..), Function(..), FunLoc(..), getServiceFunctions
+  , ServiceStmt(..), Performs(..)
+  , funThrows, ThrowsLoc(..), Throws(..), FunctionType(..)
+  , Interaction(..)
+  , RpcIdempotency(..), RpcIdempotencyType(..)
+  , Stream(..), ResponseAndStreamReturn(..), rsTypeLoc, rsLoc
+  , Type, AnnotatedType(..), TType(..), SomeAnnTy(..)
+  , TypeLoc(..), GetArity, getTypeLoc
+  , SCHEMA(..), Schema, USchema
+  , SpecialType
+  , Name(..), ThriftName, Name_(..), localName, mapName, mkName
+  , filterHiddenFields
+  ) where
+
+import Prelude hiding (Enum)
+import Data.ByteString (ByteString)
+import Data.Int
+import Data.Proxy
+import Data.Some
+import Data.Text (Text)
+import GHC.TypeLits
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+
+import Language.Haskell.Exts.SrcLoc (SrcSpanInfo)
+import Language.Haskell.Exts.Syntax (Module)
+
+import Thrift.Compiler.Options
+
+data Status = Resolved | Unresolved
+
+type Parsed t = t 'Unresolved () Loc
+
+type family IfResolved (s :: Status) (t :: *) :: * where
+  IfResolved 'Unresolved t = ()
+  IfResolved 'Resolved   t = t
+
+data ThriftPriority
+  = HighImportant
+  | High
+  | Important
+  | NormalPriority
+  | BestEffort
+  | NPriorities
+  deriving (Show, Eq)
+
+-- Thrift Program --------------------------------------------------------------
+
+data Program (l :: * {- Language -}) a = Program
+  { progName      :: Text           -- ^ Thrift name
+  , progHSName    :: Text           -- ^ Haskell module prefix (with namespace)
+  , progPath      :: FilePath
+  , progOutPath   :: FilePath
+  , progInstances :: SpliceFile
+  , progIncludes  :: [Program l a]
+  , progHeaders   :: [Header 'Resolved l a]
+  , progDecls     :: [Decl 'Resolved l a]
+  , progComments  :: [Comment a]
+  , progEnv       :: Env l
+  }
+
+data ParsedStatement
+  = StatementHeader (Parsed Header)
+  | StatementDecl (Parsed Decl)
+
+data Header s l a
+  = HInclude
+    { incPath       :: FilePath
+    , incType       :: IncludeType
+    , incKeywordLoc :: Located a
+    , incPathLoc    :: Located a
+    , incQuoteType  :: QuoteType
+    }
+  | HNamespace
+    { nmLang       :: Text
+    , nmName       :: Text
+    , nmKeywordLoc :: Located a
+    , nmLangLoc    :: Located a
+    , nmNameLoc    :: Located a
+    , nmQuoteType  :: Maybe QuoteType
+    }
+  | HPackage
+    { pkgUri         :: Text
+    , pkgKeywordLoc  :: Located a
+    , pkgUriLoc      :: Located a
+    , pkgQuoteType   :: QuoteType
+    , pkgSAnns       :: [StructuredAnnotation s l a]
+    }
+
+data IncludeType = Include | HsInclude | CppInclude
+
+data Decl s l a
+  = D_Struct (Struct s l a)
+  | D_Union (Union s l a)
+  | D_Enum (Enum s l a)
+  | D_Typedef (Typedef s l a)
+  | D_Const (Const s l a)
+  | D_Service (Service s l a)
+  | D_Interaction (Interaction s l a)
+
+type SpliceFile = Maybe (Module SrcSpanInfo)
+
+data Annotations a = Annotations
+  { annList :: [Annotation a]
+  , annOpenParen  :: Located a
+  , annCloseParen :: Located a
+  }
+
+data Annotation a
+  = SimpleAnn
+    { saTag :: Text
+    , saLoc :: Located a
+    , saSep :: Separator a
+    }
+  | ValueAnn
+    { vaTag :: Text
+    , vaVal :: AnnValue
+    , vaTagLoc :: Located a
+    , vaEqual  :: Located a
+    , vaValLoc :: Located a
+    , vaSep    :: Separator a
+    }
+
+data AnnValue = IntAnn Int Text | TextAnn Text QuoteType
+
+getAnns :: Maybe (Annotations a) -> [Annotation a]
+getAnns = maybe [] annList
+
+annLoc :: Annotation a -> a
+annLoc SimpleAnn{..} = lLocation saLoc
+annLoc ValueAnn{..} = lLocation vaTagLoc
+
+data StructuredAnnotation (s :: Status) (l :: *) a = forall t. StructuredAnn
+  { saAt :: Located a
+  , saType :: Text
+  , saTypeLoc :: TypeLoc 0 a
+  , saMaybeElems :: Maybe (StructuredAnnotationElems a)
+  , saResolvedType :: IfResolved s (Type l t)
+  , saResolvedVal :: IfResolved s (Some (StructVal l))
+  }
+
+data StructuredAnnotationElems a = StructuredAnnElems
+  { saOpenBrace  :: Located a
+  , saElems      :: [ListElem StructPair a]
+  , saCloseBrace :: Located a
+  }
+
+data Loc = Loc
+  { locFile :: FilePath
+  , locStartLine :: Int
+  , locStartCol  :: Int
+  , locEndLine   :: Int
+  , locEndCol    :: Int
+  } deriving (Show, Eq)
+
+instance Ord Loc where
+  l1 <= l2
+    | locFile l1 == locFile l2 =
+        if locStartLine l1 == locStartLine l2
+        then locStartCol l1 <= locStartCol l2
+        else locStartLine l1 <= locStartLine l2
+    | otherwise = locFile l1 <= locFile l2
+
+noLoc :: Loc
+noLoc = Loc "" 0 0 0 0
+
+nlc :: Located Loc
+nlc = Located [] noLoc
+
+data Comment a = Comment a Text
+  deriving (Show, Eq)
+
+data Located a = Located
+  { lComments :: [Comment a]
+  , lLocation :: a
+  } deriving (Show, Eq)
+
+data Separator a
+  = Semicolon (Located a)
+  | Comma (Located a)
+  | NoSep
+
+getSepLoc :: Separator a -> Maybe (Located a)
+getSepLoc (Semicolon loc) = Just loc
+getSepLoc (Comma loc) = Just loc
+getSepLoc NoSep = Nothing
+
+-- Environment -----------------------------------------------------------------
+
+-- | The type checking environment keeps track of
+data Env (l :: * {- Language -}) = Env
+  { typeMap    :: TypeMap l   -- ^ Local Named Types
+  , schemaMap  :: SchemaMap l -- ^ Local Schemas
+  , unionMap   :: UnionMap l  -- ^ Local Union Schemas
+  , enumMap    :: EnumMap     -- ^ Local Enums
+  , enumInt    :: EnumInt
+    -- ^ Local Enums as Int for default values, weird mode
+  , constMap   :: ConstMap l  -- ^ Local Constants
+  , serviceMap :: ServiceMap  -- ^ Local Services
+  , importMap  :: ImportMap l -- ^ all the modules that are in scope
+  , options    :: Options l   -- ^ Program options
+  , envName    :: Text        -- ^ The 'thriftName' of this 'Env'
+  }
+
+-- | Help build a specialized 'Env' for 'runTypechecker' while
+-- 'typecheckModule' is constructing the final 'Env' and 'Program'
+emptyEnv :: (Text, Options l) -> Env l
+emptyEnv (thriftName, opts) = Env
+  { typeMap   = emptyContext
+  , schemaMap = Map.empty
+  , unionMap  = Map.empty
+  , enumMap   = Map.empty
+  , enumInt   = Map.empty
+  , constMap  = emptyContext
+  , serviceMap = Map.empty
+  , importMap = Map.empty
+  , options   = opts
+  , envName   = thriftName
+  }
+
+data Context a = Context
+  { cMap   :: Map.Map Text a -- ^ Map to lookup value of a symbol
+  , cScope :: Set.Set Text   -- ^ Additional set of symbols that are in scope
+                             -- ie hsNames for types and constants
+  }
+
+emptyContext :: Context a
+emptyContext = Context
+  { cMap   = Map.empty
+  , cScope = Set.empty
+  }
+
+type TypeMap l   = Context (Some (Type l))
+type SchemaMap l = Map.Map Text (Some (Schema l))
+type UnionMap l  = Map.Map Text (Some (USchema l))
+type EnumMap     = Map.Map Text EnumValues
+-- For Constants, we store the renamed version in addition to the type
+type ConstMap l  = Context (Some (Type l), Name, Loc)
+-- For Service, we store the Set Text of renamed functions for scoping
+type ServiceMap  = Map.Map Text (Name, Set.Set Text, Loc)
+type ImportMap l = Map.Map Text (Env l)
+
+-- We need to be able to look up the constants keyed by their numeric value
+-- or themselves
+type EnumValues = (Map.Map EnumValueType (Name, Loc), Map.Map Text (Name, Loc))
+
+-- | There are weird thrift file using enum constants as I32 and I64 defaults,
+-- (as unqualified names).  If there is a name collision with different value
+-- this holds Nothing to detect the ambiguity. Active when weird mode is on.
+type EnumInt = Map.Map Text (Maybe EnumValueType)
+
+-- Thrift Typedef --------------------------------------------------------------
+
+data Typedef (s :: Status) (l :: * {- Language -}) a = forall v t. Typedef
+  { tdName         :: Text
+  , tdTag          :: TypedefTag s
+  , tdResolvedName :: IfResolved s Text
+  , tdType         :: AnnotatedType a v
+  , tdResolvedType :: IfResolved s (Type l t)
+  , tdLoc          :: TypedefLoc a
+  , tdAnns         :: Maybe (Annotations a)
+  , tdSAnns        :: [StructuredAnnotation s l a]
+  }
+
+data TypedefTag (s :: Status) where
+  IsTypedef :: TypedefTag s
+  IsNewtype :: TypedefTag 'Resolved
+
+data TypedefLoc a = TypedefLoc
+  { tdlKeyword :: Located a
+  , tdlName    :: Located a
+  }
+
+-- Thrift Constant--------------------------------------------------------------
+
+data Const (s :: Status) (l :: * {- Language -}) a = forall v t. Const
+  { constName         :: Text
+  , constResolvedName :: IfResolved s Text
+  , constType         :: AnnotatedType a v
+  , constVal          :: UntypedConst a
+  , constResolvedType :: IfResolved s (Type l t)
+  , constResolvedVal  :: IfResolved s (TypedConst l t)
+  , constLoc          :: ConstLoc a
+  , constSAnns        :: [StructuredAnnotation s l a]
+  }
+
+data ConstLoc a = ConstLoc
+  { clKeyword   :: Located a
+  , clName      :: Located a
+  , clEqual     :: Located a
+  , clSeparator :: Separator a
+  }
+
+data UntypedConst a = UntypedConst
+  { ucLoc   :: Located a
+  , ucConst :: ConstVal a
+  }
+
+data ConstVal a
+  = IntConst Int Text
+  -- ^ Includes are numeric types, enums, and booleans
+  | DoubleConst Double Text
+  -- ^ Doubles and Floats
+  | StringConst Text QuoteType
+  | IdConst Text
+  | ListConst
+    { lvElems      :: [ListElem UntypedConst a]
+    , lvCloseBrace :: Located a
+    }
+  -- ^ Lists and Sets
+  | MapConst
+    { mvElems      :: [ListElem MapPair a]
+    , mvCloseBrace :: Located a
+    }
+  -- ^ Maps and Structs
+  | StructConst
+    { svType       :: Text
+    , svOpenBrace  :: Located a
+    , svElems      :: [ListElem StructPair a]
+    , svCloseBrace :: Located a
+    }
+  | BoolConst Bool
+
+data ListElem t a = ListElem
+  { leElem :: t a
+  , leSeparator :: Separator a
+  }
+
+data MapPair a = MapPair
+  { mpKey   :: UntypedConst a
+  , mpColon :: Located a
+  , mpVal   :: UntypedConst a
+  }
+
+data StructPair a = StructPair
+  { spKey :: Text
+  , spKeyLoc :: Located a
+  , spEquals:: Located a
+  , spVal:: UntypedConst a
+  }
+
+data QuoteType = SingleQuote | DoubleQuote
+  deriving (Show, Eq)
+
+data TypedConst l t
+  = Literal t
+  | Identifier Name (Type l t) Loc -- ^ Loc for definition of Name
+  | WeirdEnumToInt (Type l t) Name (Type l EnumVal) Loc
+
+newtype List l t      = List [TypedConst l t]
+newtype Set l t       = Set [TypedConst l t]
+newtype HashSet l t   = HashSet [TypedConst l t]
+newtype Map l k v     = Map [(TypedConst l k, TypedConst l v)]
+newtype HashMap l k v = HashMap [(TypedConst l k, TypedConst l v)]
+
+-- | Include Loc of definition (from EnumValLoc)
+data EnumVal = EnumVal Name Loc
+
+newtype New t = New t
+
+-- The fields of a struct are encoded in the type parameter of the StructVal
+-- s has kind [(Symbol, *)]. The Symbol is a type-level string, which is the
+-- name of the field and the * is the actual type of the field. A list of these
+-- pairs makes a StructVal
+data StructVal (l :: * {- Language -}) (s :: [(Symbol, *)]) where
+  Empty :: StructVal l '[]
+
+  ConsVal
+    :: forall (name :: Symbol) l t s. KnownSymbol name
+    => Proxy name
+    -> Type l t
+    -> TypedConst l t
+    -> StructVal l s
+    -> StructVal l ('(name, t) ': s)
+  ConsDefault
+    :: forall (name :: Symbol) l t s. KnownSymbol name
+    => Proxy name
+    -> Type l t
+    -> StructVal l s
+    -> StructVal l ('(name, t) ': s)
+  ConsJust
+    :: forall (name :: Symbol) l t s. KnownSymbol name
+    => Proxy name
+    -> Type l t
+    -> TypedConst l t
+    -> StructVal l s
+    -> StructVal l ('(name, Maybe t) ': s)
+  ConsNothing
+    :: forall (name :: Symbol) l t s. KnownSymbol name
+    => Proxy name
+    -> StructVal l s
+    -> StructVal l ('(name, Maybe t) ': s)
+
+newtype ExceptionVal l s = EV (StructVal l s)
+
+-- Unions have exactly one value out of a list of possible values. However, they
+-- also need to include a MembershipProof which proves that the present field is
+-- a member of the union's schema
+data UnionVal (l :: * {- Language -}) (s :: [(Symbol, *)]) where
+  UnionVal
+    :: forall (name :: Symbol) l s t. KnownSymbol name
+    => Proxy name
+    -> Type l t
+    -> TypedConst l t
+    -> MembershipProof '(name, t) s
+    -> UnionVal l s
+
+-- Proof that a field is a memeber of a schema
+data MembershipProof x xs where
+  -- The field is the first field in the type list
+  PHere  :: MembershipProof x (x ': xs)
+  -- The field is buried somewhere deeper in the type list
+  PThere :: MembershipProof x xs -> MembershipProof x (y ': xs)
+
+-- Thrift Structs and Exceptions -----------------------------------------------
+
+data Struct s l a = Struct
+  { structName           :: Text
+  , structResolvedName   :: IfResolved s Text
+  , structType           :: StructType
+  , structMembers        :: [Field 'StructField s l a]
+  , structLoc            :: StructLoc a
+  , structAnns           :: Maybe (Annotations a)
+  , structSAnns          :: [StructuredAnnotation s l a]
+  , errorClassifications :: [ErrorClassification a]
+  }
+
+data StructType = StructTy | ExceptionTy
+
+data StructLoc a = StructLoc
+  { slKeyword    :: Located a
+  , slName       :: Located a
+  , slOpenBrace  :: Located a
+  , slCloseBrace :: Located a
+  }
+
+data ErrorClassification a = ErrorClassification
+  { ecType       :: ErrorClassificationType
+  , ecKeywordLoc :: Located a
+  }
+
+data ErrorClassificationType =
+  EcSafe | EcTransient | EcStateful | EcPermanent | EcServer | EcClient
+
+-- Thrift Fields ---------------------------------------------------------------
+
+data FieldType = StructField | Argument | ThrowsField
+
+data FieldTag u s l t where
+  STRUCT_FIELD :: FieldTag 'StructField s l t
+  ARGUMENT     :: FieldTag 'Argument s l t
+  THROWS_UNRESOLVED :: FieldTag 'ThrowsField 'Unresolved l t
+  THROWS_RESOLVED   :: FieldTag 'ThrowsField 'Resolved l (Some (ExceptionVal l))
+
+data Field u s l a = forall v t. Field
+  { fieldId           :: FieldId
+  , fieldName         :: Text
+  , fieldResolvedName :: IfResolved s Text
+  , fieldType         :: AnnotatedType a v
+  , fieldResolvedType :: IfResolved s (Type l t)
+  , fieldVal          :: Maybe (UntypedConst a)
+  , fieldResolvedVal  :: IfResolved s (Maybe (TypedConst l t))
+  , fieldRequiredness :: Requiredness u a
+  , fieldLaziness     :: Laziness
+  , fieldTag          :: FieldTag u s l t
+  , fieldLoc          :: FieldLoc a
+  , fieldAnns         :: Maybe (Annotations a)
+  , fieldSAnns        :: [StructuredAnnotation s l a]
+  }
+
+type FieldId = Int32
+
+data Requiredness u a where
+  Default :: Requiredness u a
+
+  -- Optional and Required are only for Struct Fields (not arguments)
+  Optional :: Located a -> Requiredness 'StructField a
+  Required :: Located a -> Requiredness 'StructField a
+
+data Laziness = Lazy | Strict
+
+data FieldLoc a = FieldLoc
+  { flId        :: Located a
+  , flIdRep     :: Text
+  , flColon     :: Located a
+  , flName      :: Located a
+  , flEqual     :: Maybe (Located a)
+  , flSeparator :: Separator a
+  }
+
+-- Thrift Unions ---------------------------------------------------------------
+
+data Union s l a = forall u. Union
+  { unionName         :: Text
+  , unionResolvedName :: IfResolved s Text
+  , unionAlts         :: [UnionAlt s l a]
+  , unionEmptyName    :: EmptyName s u
+  , unionHasEmpty     :: PossiblyEmpty u
+  , unionLoc          :: StructLoc a
+  , unionAnns         :: Maybe (Annotations a)
+  , unionSAnns        :: [StructuredAnnotation s l a]
+  }
+
+data UnionAlt (s :: Status) (l :: * {- Language -}) a = forall v t. UnionAlt
+  { altId           :: FieldId
+  , altName         :: Text
+  , altResolvedName :: IfResolved s Text
+  , altType         :: AnnotatedType a v
+  , altResolvedType :: IfResolved s (Type l t)
+  , altLoc          :: FieldLoc a
+  , altAnns         :: Maybe (Annotations a)
+  , altSAnns        :: [StructuredAnnotation s l a]
+  }
+
+data PossiblyEmpty (u :: Bool) where
+  HasEmpty :: PossiblyEmpty 'True
+  NonEmpty :: PossiblyEmpty 'False
+
+type family EmptyName s u where
+  EmptyName 'Unresolved u = ()
+  EmptyName 'Resolved 'True  = Text
+  EmptyName 'Resolved 'False = ()
+
+-- Thrift Enums ----------------------------------------------------------------
+
+data Enum (s :: Status) (l :: * {- Language -}) a = Enum
+  { enumName         :: Text
+  , enumResolvedName :: IfResolved s Text
+  , enumFlavour      :: IfResolved s EnumFlavour
+  , enumConstants    :: [EnumValue s l a]
+  , enumLoc          :: StructLoc a
+  , enumAnns         :: Maybe (Annotations a)
+  , enumSAnns        :: [StructuredAnnotation s l a]
+  }
+
+data EnumFlavour
+  = SumTypeEnum
+    { enumNoUnknown :: Bool
+    }
+  | PseudoEnum
+    { peThriftEnum :: Bool
+    }
+
+data EnumValue (s :: Status) (l :: * {- Language -}) a = EnumValue
+  { evName         :: Text
+  , evResolvedName :: IfResolved s Text
+  , evValue        :: EnumValueType
+  , evLoc          :: EnumValLoc a
+  , evAnns         :: Maybe (Annotations a)
+  , evSAnns        :: [StructuredAnnotation s l a]
+  }
+
+type EnumValueType = Int32
+
+enumValueType :: TType s l a EnumValueType
+enumValueType = I32
+
+data EnumValLoc a = EnumValLoc
+  { evlName      :: Located a
+  , evlEqual     :: Located a
+  , evlValue     :: Located a
+  , evlRep       :: Text
+  , evlSeparator :: Separator a
+  }
+
+-- Thrift Service --------------------------------------------------------------
+
+data Service (s :: Status) (l :: * {- Language -}) a = Service
+  { serviceName         :: Text
+  , serviceResolvedName :: IfResolved s Text
+  , serviceSuper        :: Maybe (Super s a)
+  -- , serviceFunctions    :: [Function s l a]
+  , serviceStmts        :: [ServiceStmt s l a]
+  , serviceLoc          :: StructLoc a
+  , serviceAnns         :: Maybe (Annotations a)
+  , serviceSAnns        :: [StructuredAnnotation s l a]
+  }
+
+getServiceFunctions :: Service s l a -> [Function s l a]
+getServiceFunctions Service {..} = concatMap getFn serviceStmts
+  where
+    getFn (FunctionStmt f ) = [f]
+    getFn _ = []
+
+data Super s a = Super
+  { supName         :: Text
+  , supResolvedName :: IfResolved s (Name, Loc)
+  , supExtends      :: Located a -- ^ location of "extends" keyword
+  , supLoc          :: Located a -- ^ location of "supName" after "extends"
+  }
+
+data ServiceStmt s l a
+  = FunctionStmt (Function s l a)
+  | PerformsStmt (Performs s l a)
+
+newtype Performs (s :: Status) (l :: * {- Language -}) a = Performs
+  { performsName :: Text
+  }
+
+data Function (s :: Status) (l :: * {- Language -}) a = Function
+  { funName         :: Text
+  , funResolvedName :: IfResolved s Text
+  , funType         :: FunctionType s l a
+  , funResolvedType :: IfResolved s (Maybe (Some (Type l)))
+  , funArgs         :: [Field 'Argument s l a]
+  , funExceptions   :: [Field 'ThrowsField s l a]
+  , funIsOneWay     :: Bool
+  , funPriority     :: ThriftPriority
+  , funLoc          :: FunLoc a
+  , funAnns         :: Maybe (Annotations a)
+  , funSAnns        :: [StructuredAnnotation s l a]
+  , funIdempotency  :: Maybe RpcIdempotency
+  }
+
+data FunctionType s l a
+  = FunType (Some (AnnotatedType a))
+  | FunTypeVoid (Located a)
+  | FunTypeResponseAndStreamReturn (ResponseAndStreamReturn s l a)
+
+data ResponseAndStreamReturn s l a = forall v. ResponseAndStreamReturn
+  { rsReturn :: Maybe (AnnotatedType a v)
+  , rsComma :: Maybe (Located a)
+  , rsStream :: Stream s l a
+  }
+
+rsTypeLoc :: ResponseAndStreamReturn s l a -> SomeTypeLoc a
+rsTypeLoc ResponseAndStreamReturn{rsStream = Stream{..}, ..} = case rsReturn of
+  Just AnnotatedType{..} -> ThisTypeLoc atLoc
+  Nothing -> ThisTypeLoc streamLoc
+
+rsLoc :: ResponseAndStreamReturn s l a -> a
+rsLoc = loc . rsTypeLoc
+  where loc (ThisTypeLoc l) = getTypeLoc l
+
+data Stream s l a = forall v. Stream
+  { streamType :: AnnotatedType a v
+  , streamThrows :: Maybe (Throws s l a)
+  , streamLoc :: TypeLoc 1 a
+  }
+
+data FunLoc a = FunLoc
+  { fnlOneway      :: Maybe (Located a)
+  , fnlIdempotency :: Maybe (Located a)
+  , fnlName        :: Located a
+  , fnlOpenParen   :: Located a
+  , fnlCloseParen  :: Located a
+  , fnlThrows      :: Maybe (ThrowsLoc a)
+  , fnlSeparator   :: Separator a
+  }
+
+data ThrowsLoc a = ThrowsLoc
+  { tlThrows     :: Located a
+  , tlOpenParen  :: Located a
+  , tlCloseParen :: Located a
+  }
+
+data Throws s l a = Throws
+  { throwsLoc :: ThrowsLoc a
+  , throwsFields :: [Field 'ThrowsField s l a]
+  }
+
+funThrows
+  :: Function s l a
+  -> Maybe (Throws s l a)
+funThrows Function{funLoc=FunLoc{..}, ..} = fmap f fnlThrows
+  where f throws = Throws throws funExceptions
+
+newtype RpcIdempotency = RpcIdempotency { riType :: RpcIdempotencyType }
+
+data RpcIdempotencyType = RiReadonly | RiIdempotent
+
+-- Thrift Interaction ----------------------------------------------------------
+
+data Interaction (s :: Status) (l :: * {- Language -}) a = Interaction
+  { interactionName         :: Text
+  , interactionResolvedName :: IfResolved s Text
+  , interactionSuper        :: Maybe (Super s a)
+  , interactionFunctions    :: [Function s l a]
+  , interactionLoc          :: StructLoc a
+  , interactionAnns         :: Maybe (Annotations a)
+  , interactionSAnns        :: [StructuredAnnotation s l a]
+  }
+
+
+-- Thrift Value Types ----------------------------------------------------------
+
+-- When a thrift file is parsed, all of the types are marked as 'Unresolved
+-- meaning that we don't know have any information about the named types.
+-- During type checking, these types become 'Resolved, a process by which all
+-- of the named types become either structs, enums, or typedefs
+type Type l = TType 'Resolved l Loc
+
+-- Annotations are resolved during typechecking, so we don't need them once
+-- types are resolved
+type family TypeOf (s :: Status) (l :: * {- Language -}) a :: * -> * where
+  TypeOf 'Resolved l a   = Type l
+  TypeOf 'Unresolved l a = AnnotatedType a
+
+data AnnotatedType a t = AnnotatedType
+  { atType        :: TType 'Unresolved () a t
+  , atAnnotations :: Maybe (Annotations a)
+  , atLoc         :: TypeLoc (GetArity t) a
+  }
+
+type family GetArity t :: Nat where
+  GetArity (List l a) = 1
+  GetArity (Set l a) = 1
+  GetArity (HashSet l a) = 1
+  GetArity (Map l a b) = 2
+  GetArity (HashMap l a b) = 2
+  GetArity a = 0
+
+data TypeLoc (n :: Nat) a where
+  Arity0Loc :: { a0Ty :: Located a } -> TypeLoc 0 a
+  Arity1Loc
+    :: { a1Ty         :: Located a
+       , a1OpenBrace  :: Located a
+       , a1CloseBrace :: Located a
+       }
+    -> TypeLoc 1 a
+  Arity2Loc
+    :: { a2Ty         :: Located a
+       , a2OpenBrace  :: Located a
+       , a2Comma      :: Located a
+       , a2CloseBrace :: Located a
+       }
+    -> TypeLoc 2 a
+
+getTypeLoc :: TypeLoc n a -> a
+getTypeLoc Arity0Loc{..} = lLocation a0Ty
+getTypeLoc Arity1Loc{..} = lLocation a1Ty
+getTypeLoc Arity2Loc{..} = lLocation a2Ty
+
+data SomeTypeLoc a =
+  forall n. ThisTypeLoc (TypeLoc n a)
+
+data SomeAnnTy s l =
+  forall t. ThisAnnTy (TType s l Loc t) (TypeLoc (GetArity t) Loc)
+
+data TType (s :: Status) (l :: * {- Language -}) a (t :: *) where
+  -- Integral TTypes
+  I8  :: TType s l a Int8
+  I16 :: TType s l a Int16
+  I32 :: TType s l a Int32
+  I64 :: TType s l a Int64
+
+  -- Floating Point TTypes
+  TFloat  :: TType s l a Float
+  TDouble :: TType s l a Double
+
+  -- Other Base TTypes
+  TBool   :: TType s l a Bool
+  TText   :: TType s l a Text
+  TBytes  :: TType s l a ByteString
+
+  -- Collections
+  TSet     :: TypeOf s l a t -> TType s l a (Set l t)
+  THashSet :: TypeOf s l a t -> TType s l a (HashSet l t)
+  TList    :: TypeOf s l a t -> TType s l a (List l t)
+  TMap     :: TypeOf s l a k -> TypeOf s l a v -> TType s l a (Map l k v)
+  THashMap :: TypeOf s l a k -> TypeOf s l a v -> TType s l a (HashMap l k v)
+
+  -- TTypedefs
+  TTypedef :: Name -> Type l t -> Loc -> TType 'Resolved l a t
+  TNewtype :: Name -> Type l t -> Loc -> TType 'Resolved l a (New t)
+
+  -- Structs
+  TStruct    :: Name -> Loc -> TType 'Resolved l a (Some (StructVal l))
+  TException :: Name -> Loc -> TType 'Resolved l a (Some (ExceptionVal l))
+  TUnion     :: Name -> Loc -> TType 'Resolved l a (Some (UnionVal l))
+
+  -- Enums
+  TEnum   :: Name -> Loc -> Bool -> TType 'Resolved l a EnumVal
+
+  -- Unresolved named types
+  TNamed :: Text -> TType 'Unresolved l a ()
+
+  -- Special types that we get by resolving annotations
+  TSpecial :: SpecialType l t -> TType 'Resolved l a t
+
+data family SpecialType (l :: * {- Language -}) (t :: *)
+
+data SchemaType = StructSchema | UnionSchema
+
+type Schema l = SCHEMA l 'StructSchema
+type USchema l = SCHEMA l 'UnionSchema
+
+-- Schema for a struct, defines exactly what must be present
+data SCHEMA (l :: * {- Language -}) (t :: SchemaType) (s :: [(Symbol, *)]) where
+  -- | Empty struct has type empty list
+  SEmpty :: SCHEMA l u '[]
+
+  SField
+    :: forall (name :: Symbol) l t s. KnownSymbol name
+    => Proxy name
+    -> Text
+    -> Type l t
+    -> SCHEMA l 'StructSchema s
+    -> SCHEMA l 'StructSchema ('(name, t) ': s)
+
+  -- | For required fields, the value must be present
+  SReqField
+    :: forall (name :: Symbol) l u t s. KnownSymbol name
+    => Proxy name
+    -> Text
+    -> Type l t
+    -> SCHEMA l u s
+    -> SCHEMA l u ('(name, t) ': s)
+
+  -- | For optional fields, the value is a Maybe
+  -- Only structs can have optional fields
+  SOptField
+     :: forall (name :: Symbol) l t s. KnownSymbol name
+     => Proxy name
+     -> Text
+     -> Type l t
+     -> SCHEMA l 'StructSchema s
+     -> SCHEMA l 'StructSchema ('(name, Maybe t) ': s)
+
+-- | Renamed for target langauge
+data Name = Name
+  { sourceName   :: ThriftName
+  , resolvedName :: Name_ 'Resolved
+  } deriving (Eq)
+
+-- | Name in the original thrift source file
+type ThriftName = Name_ 'Unresolved
+
+data Name_ (s :: Status)
+  = UName Text
+  | QName Text Text
+  deriving (Eq,Show)
+
+localName :: Name_ s -> Text
+localName (UName n) = n
+localName (QName _ n) = n
+
+mapName :: (Text -> Text) -> Name_ s -> Name_ s
+mapName f (UName n) = UName $ f n
+mapName f (QName m n) = QName m $ f n
+
+mkName :: Text -> Text -> Name
+mkName tname rname = Name
+  { sourceName = UName tname
+  , resolvedName = UName rname
+  }
+
+filterHiddenFields :: [Field u s l a] -> [Field u s l a]
+filterHiddenFields  = filter (not . isHiddenField)
+  where
+    isHiddenField Field{..} =
+      any (\annot -> case annot of
+        SimpleAnn{saTag = "hs.hidden"} -> True
+        _ -> False
+      ) $ getAnns fieldAnns
diff --git a/main/Main.hs b/main/Main.hs
new file mode 100644
--- /dev/null
+++ b/main/Main.hs
@@ -0,0 +1,20 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Main (main) where
+
+import Control.Monad
+import Options.Applicative
+
+import Thrift.Compiler as Compiler
+import Thrift.Compiler.OptParse
+
+main :: IO ()
+main = do
+  TheseOptions opts <- execParser (info (helper <*> optionsParser) fullDesc)
+  void $ Compiler.run opts
diff --git a/plugins/Thrift/Compiler/Plugins/Haskell.hs b/plugins/Thrift/Compiler/Plugins/Haskell.hs
new file mode 100644
--- /dev/null
+++ b/plugins/Thrift/Compiler/Plugins/Haskell.hs
@@ -0,0 +1,387 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Thrift.Compiler.Plugins.Haskell
+  ( Haskell, HSType, HS
+  , SpecialType(..)
+  , HsVectorKind(..), hsVectorImport, hsVectorQual
+  , HsInterface(..), RenameMap
+  , LangOpts(..), defaultHsOpts
+  , toCamel
+  ) where
+
+import Data.ByteString (ByteString)
+import qualified Data.Foldable as Foldable
+import qualified Data.Map as Map
+import Data.Maybe
+import Data.Some
+import Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import Data.Type.Equality
+
+import Language.Haskell.Exts.SrcLoc
+import Language.Haskell.Names hiding (None, resolve)
+import qualified Language.Haskell.Exts.Syntax as E -- TODO: t16933748 refactor
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Parser
+import Thrift.Compiler.Plugin
+import Thrift.Compiler.Typechecker
+import Thrift.Compiler.Typechecker.Monad
+import Thrift.Compiler.Types as Thrift hiding (noLoc)
+
+-- Haskell Types ---------------------------------------------------------------
+
+data Haskell
+
+type HSType = Type Haskell
+
+type HS t = t 'Resolved Haskell Thrift.Loc
+
+data HsVectorKind = HsVectorBoxed | HsVectorStorable
+  deriving (Eq, Ord, Prelude.Enum, Bounded)
+
+hsVectorImport :: HsVectorKind -> Text
+hsVectorImport HsVectorBoxed = "Data.Vector"
+hsVectorImport HsVectorStorable = "Data.Vector.Storable"
+
+hsVectorQual :: HsVectorKind -> Text
+hsVectorQual HsVectorBoxed = "Vector"
+hsVectorQual HsVectorStorable = "VectorStorable"
+
+data instance SpecialType Haskell t where
+  HsInt    :: SpecialType Haskell Int
+  HsString :: SpecialType Haskell String
+  HsByteString :: SpecialType Haskell ByteString
+  HsVector :: HsVectorKind -> HSType t -> SpecialType Haskell (List Haskell t)
+
+data HsInterface = HsInterface Environment RenameMap
+
+instance Semigroup HsInterface where
+  HsInterface e1 r1 <> HsInterface e2 r2 =
+    HsInterface (Map.unionWith (++) e1 e2) (Map.union r1 r2)
+
+instance Monoid HsInterface where
+  mempty = HsInterface Map.empty Map.empty
+
+
+-- | Map from Haskell name qualified Thrift name
+type RenameMap = Map.Map Symbol Text
+
+-- Haskell Options -------------------------------------------------------------
+
+data instance LangOpts Haskell = HsOpts
+  { hsoptsEnableHaddock :: Bool
+  , hsoptsUseInt :: Bool
+  , hsoptsUseHashMap :: Bool
+  , hsoptsUseHashSet :: Bool
+  , hsoptsDupNames :: Bool
+  , hsoptsExtensions :: [Text]
+  , hsoptsGenPrefix :: FilePath
+  , hsoptsExtraHasFields :: Bool
+  }
+
+defaultHsOpts :: LangOpts Haskell
+defaultHsOpts = HsOpts
+  { hsoptsEnableHaddock = False
+  , hsoptsUseInt = False
+  , hsoptsUseHashMap = False
+  , hsoptsUseHashSet = False
+  , hsoptsDupNames = False
+  , hsoptsExtensions = []
+  , hsoptsGenPrefix = "gen-hs2"
+  , hsoptsExtraHasFields = False
+  }
+
+-- Type Class Instance ---------------------------------------------------------
+
+instance Typecheckable Haskell where
+  type Interface Haskell = HsInterface
+
+  -- Annotation Processing
+
+  resolveTypeAnnotations ty anns = do
+    Env{ options = Options{..} } <- ask
+    case optsLangSpecific of
+      HsOpts{..} ->
+        ifFlag hsoptsUseInt i64ToInt .
+        ifFlag hsoptsUseHashMap map2HashMap .
+        ifFlag hsoptsUseHashSet set2HashSet <$>
+        resolve ty (getTypeAnns "hs" anns)
+    where
+      resolve
+        :: HSType t
+        -> [(Text, Annotation Thrift.Loc)]
+        -> TC Haskell (Some HSType)
+      resolve I64 [("Int",_)] = special HsInt
+      resolve TText [("String",_)] = special HsString
+      resolve (TMap k v) [("HashMap",_)] = pure $ Some $ THashMap k v
+      resolve (TSet u) [("HashSet",_)] = pure $ Some $ THashSet u
+      resolve TText [("ByteString",_)] = special HsByteString
+      resolve (TList u) [(vec,_)]
+        | Just kind <-
+            lookup vec [(hsVectorQual x,x) | x <- [minBound .. maxBound]] =
+              special $ HsVector kind u
+      resolve u [] = pure $ Some u
+      resolve u ((_,a):_) =
+        typeError (annLoc a) $ AnnotationMismatch (AnnType u) a
+
+      special = pure . Some . TSpecial
+
+      ifFlag
+        :: Bool
+        -> (forall t. HSType t -> Some HSType)
+        -> Some HSType
+        -> Some HSType
+      ifFlag flag fun (Some u)
+        | flag      = fun u
+        | otherwise = Some u
+      i64ToInt :: HSType t -> Some HSType
+      i64ToInt I64 = Some $ TSpecial HsInt
+      i64ToInt u  = Some u
+      map2HashMap (TMap k v) = Some $ THashMap k v
+      map2HashMap u = Some u
+      set2HashSet (TSet u) = Some $ THashSet u
+      set2HashSet u = Some u
+
+  -- Typechecking
+
+  qualifySpecialType _ HsInt = HsInt
+  qualifySpecialType _ HsString = HsString
+  qualifySpecialType _ HsByteString = HsByteString
+  qualifySpecialType m (HsVector kind ty) = HsVector kind $ qualifyType m ty
+
+  typecheckSpecialConst HsInt (UntypedConst _ (IntConst i _)) =
+    pure $ Literal $ fromIntegral i
+  typecheckSpecialConst HsString (UntypedConst _ (StringConst s _)) =
+    pure $ Literal $ Text.unpack s
+  typecheckSpecialConst HsByteString (UntypedConst _ (StringConst s _)) =
+    pure $ Literal $ Text.encodeUtf8 s
+  typecheckSpecialConst (HsVector _ u) (UntypedConst _ ListConst{..}) =
+    Literal . List <$> traverse (typecheckConst u . leElem) lvElems
+  typecheckSpecialConst ty val@(UntypedConst Located{..} _) =
+    typeError lLocation $ LiteralMismatch (TSpecial ty) val
+
+  eqSpecial HsInt HsInt = Just Refl
+  eqSpecial HsString HsString = Just Refl
+  eqSpecial HsByteString HsByteString = Just Refl
+  eqSpecial (HsVector a u) (HsVector b v)
+    | a == b = apply Refl <$> eqOrAlias u v
+  eqSpecial _ _ = Nothing
+
+  -- Interfaces
+
+  getInterface opts tf@ThriftFile{..} = mconcat $
+    map (getDeclIface opts thriftName mname) thriftDecls
+    where
+      mname = E.ModuleName () $ Text.unpack $ renameModule opts tf <> ".Types"
+
+  getExtraSymbols opts iface tf@ThriftFile{..} =
+    maybe [] (getHsIncludeDeps opts iface tf) thriftSplice
+
+  -- Renamers
+
+  renameModule _ ThriftFile{..} = case getNamespace "hs" thriftHeaders of
+    Just ns -> ns <> "." <> toCamel thriftName
+    Nothing -> toCamel thriftName
+
+  renameStruct _ Struct{..} = toConstructorName structName
+
+  renameField Options{..} ann sname Field{..} =
+    case optsLangSpecific of
+      HsOpts{..} ->
+        let basePrefix
+              | hsoptsDupNames = ""
+              | otherwise = sname <> "_"
+        in  lowercase $ fromMaybe basePrefix (getPrefix ann) <> fieldName
+
+  renameConst _ = lowercase
+
+  renameService _ Service{..} = toConstructorName serviceName
+
+  renameFunction _ Function{..} = lowercase $ prefix <> funName
+    where
+      prefix = fromMaybe "" $ getPrefix $ getAnns funAnns
+
+  renameTypedef _ Typedef{..} = toConstructorName tdName
+
+  renameEnum _ Enum{..} = toConstructorName enumName
+
+  renameEnumAlt opts e@Enum{..} name =
+    fixCase $ if
+      | Just prefix <- getPrefix (getAnns enumAnns) -> prefix <> name
+      | otherwise -> enumName <> "_" <> name
+    where
+      fixCase = case enumFlavourTag opts e of
+        PseudoEnum{} -> lowercase
+        _ -> uppercase
+
+  renameUnion _ Union{..} = toConstructorName unionName
+
+  renameUnionAlt _ Union{..} UnionAlt{..} =
+    toConstructorName $ fromMaybe (unionName <> "_") (getPrefix $ getAnns unionAnns) <>
+    altName
+
+  getUnionEmptyName _ Union{..} =
+    toConstructorName $ fromMaybe (unionName <> "_") (getPrefix $ getAnns unionAnns) <>
+    "EMPTY"
+
+  fieldsAreUnique Options{ optsLangSpecific = HsOpts{..} } = not hsoptsDupNames
+  unionAltsAreUnique _ = True
+  enumAltsAreUnique Options{} = True
+
+  enumFlavourTag _ Enum{..}
+    | hasSimpleAnn "hs.pseudoenum" = PseudoEnum False
+    | hasValueAnn "hs.pseudoenum" "thriftenum" = PseudoEnum True
+    | hasSimpleAnn "hs.nounknown" = SumTypeEnum True
+    | otherwise = SumTypeEnum False
+    where
+      hasSimpleAnn t = or
+        [ saTag == t
+        | SimpleAnn{..} <- getAnns enumAnns
+        ]
+      hasValueAnn t v = or
+        [ vaTag == t && av == v
+        | ValueAnn{ vaVal=TextAnn av _, ..} <- getAnns enumAnns
+        ]
+
+  -- Back-Translators
+
+  backTranslateType HsInt = (Some I64, "Int")
+  backTranslateType HsString = (Some TText, "String")
+  backTranslateType HsByteString = (Some TText, "ByteString")
+  backTranslateType (HsVector kind u) = (Some (TList u), hsVectorQual kind)
+
+  backTranslateLiteral HsInt i = ThisLit I64 (fromIntegral i)
+  backTranslateLiteral HsString s = ThisLit TText (Text.pack s)
+  backTranslateLiteral HsByteString s = ThisLit TText (Text.decodeUtf8 s)
+  backTranslateLiteral (HsVector _ u) l = ThisLit (TList u) l
+
+-- Compute Decl Interfaces -----------------------------------------------------
+
+getDeclIface
+  :: Options Haskell -> Text -> E.ModuleName () -> Parsed Decl -> HsInterface
+getDeclIface opts name mname decl = ifaceFromSymbols mname $ case decl of
+  -- Structs
+  D_Struct s@Struct{..} ->
+    mkStruct (packT structName) (packHs $ renameStruct opts s) ++
+    concatMap
+    (\field ->
+      mkSelector (packT structName)
+      (packHs $ renameField opts (getAnns structAnns) structName field)
+      (packHs $ renameStruct opts s))
+    structMembers
+  -- Unions
+  D_Union u@Union{..} ->
+    mkData (packT unionName) (packHs $ renameUnion opts u) ++
+    concatMap
+    (\alt ->
+      mkConstructor (packT unionName)
+      (packHs $ renameUnionAlt opts u alt)
+      (packHs $ renameUnion opts u))
+    unionAlts
+  -- Enums
+  D_Enum e@Enum{..} ->
+    case enumFlavourTag opts e of
+      PseudoEnum{} ->
+        mkNewtype (packT enumName) (packHs $ renameEnum opts e)
+          (packHs $ ("un" <>) $ renameEnum opts e) ++
+        concatMap
+        (\EnumValue{..} ->
+          mkValue (packT enumName) (packHs $ renameEnumAlt opts e evName))
+        enumConstants
+      SumTypeEnum{} ->
+        mkData (packT enumName) (packHs $ renameEnum opts e) ++
+        concatMap
+        (\EnumValue{..} ->
+          mkConstructor (packT enumName)
+          (packHs $ renameEnumAlt opts e evName)
+          (packHs $ renameEnum opts e))
+        enumConstants
+  -- Typedefs
+  D_Typedef t@Typedef{..}
+    | isNewtype (getAnns tdAnns) ->
+        mkNewtype (packT tdName) (packHs $ renameTypedef opts t)
+        (packHs $ ("un" <>) $ renameTypedef opts t)
+    | otherwise ->
+        mkType (packT tdName) (packHs $ renameTypedef opts t)
+  -- Constants
+  D_Const Const{..} ->
+    mkValue (packT constName) (packHs $ renameConst opts constName)
+  -- Services are not supported yet
+  D_Service{} -> []
+  -- Interaction are not supported yet
+  D_Interaction{} -> []
+
+  where
+    mkValue tname hsname =
+      [ (Value mname hsname, tname) ]
+    mkStruct tname hsname =
+      [ (Data mname hsname, tname)
+      , (Constructor mname hsname hsname, tname)
+      ]
+    mkSelector tname hsname tyname =
+      [ (Selector mname hsname tyname [tyname], tname)
+      ]
+    mkData tname hsname =
+      [ (Data mname hsname, tname) ]
+    mkConstructor tname hsname tyname =
+      [ (Constructor mname hsname tyname, tname) ]
+    mkType tname hsname =
+      [ (Type mname hsname, tname) ]
+    mkNewtype tname hsname selname =
+      [ (NewType mname hsname, tname)
+      , (Constructor mname hsname hsname, tname)
+      , (Selector mname selname hsname [hsname], tname)
+      ]
+
+    packHs = E.Ident () . Text.unpack
+    packT t = name <> "." <> t
+
+ifaceFromSymbols :: E.ModuleName () -> [(Symbol, Text)] -> HsInterface
+ifaceFromSymbols mname ss = HsInterface
+  (Map.singleton mname symbols)
+  rmap
+  where
+    rmap = Map.fromList ss
+    symbols = map fst ss
+
+-- HS Include Dependencies -----------------------------------------------------
+
+getHsIncludeDeps
+  :: Options Haskell
+  -> HsInterface
+  -> ThriftFile a l
+  -> E.Module SrcSpanInfo
+  -> [Text]
+getHsIncludeDeps opts (HsInterface env rmap) tf (E.Module loc mhead ps is ds)
+  | E.Module _ _ _ _ decls <- annotate env m' =
+    [ thriftSym
+    | decl <- decls
+    , (Scoped (GlobalSymbol hsSymbol _) _) <- Foldable.toList decl
+    , Just thriftSym <- [Map.lookup hsSymbol rmap]
+    ]
+  | otherwise = error "getHsIncludeDeps"
+  where
+    -- Add types module to imports so that haskell-names knows where the symbols
+    -- come from
+    m' = E.Module loc mhead ps (thriftImport : is) ds
+    thriftImport = E.ImportDecl
+      { importAnn = emptyLoc
+      , importModule =
+        E.ModuleName emptyLoc $ Text.unpack (renameModule opts tf) ++ ".Types"
+      , importQualified = False
+      , importSrc = False
+      , importSafe = False
+      , importPkg = Nothing
+      , importAs = Nothing
+      , importSpecs = Nothing
+      }
+    emptyLoc = toSrcInfo noLoc [] noLoc
+getHsIncludeDeps _ _ _ _ = []
diff --git a/plugins/Thrift/Compiler/Plugins/Linter.hs b/plugins/Thrift/Compiler/Plugins/Linter.hs
new file mode 100644
--- /dev/null
+++ b/plugins/Thrift/Compiler/Plugins/Linter.hs
@@ -0,0 +1,39 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
+
+module Thrift.Compiler.Plugins.Linter
+  ( Linter
+  , LangOpts(..)
+  ) where
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.Plugin
+
+-- Linter Types ----------------------------------------------------------------
+
+data Linter
+
+-- Linter Options -------------------------------------------------------------
+
+data instance LangOpts Linter = NoOpts
+
+-- Type Class Instance ---------------------------------------------------------
+
+instance Typecheckable Linter where
+  type Interface Linter = ()
+
+  -- These are all vacuously empty because there is no data family instance for
+  -- SpecialType Linter
+  typecheckSpecialConst ty _ = case ty of
+  qualifySpecialType _ ty = case ty of
+  eqSpecial ty _ =  case ty of
+
+  backTranslateType ty = case ty of
+  backTranslateLiteral ty _ = case ty of
diff --git a/test/TestFixtures.hs b/test/TestFixtures.hs
new file mode 100644
--- /dev/null
+++ b/test/TestFixtures.hs
@@ -0,0 +1,128 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+{-# LANGUAGE TypeApplications #-}
+module TestFixtures (main) where
+
+import Control.Monad (unless, when)
+import Data.Aeson.Encode.Pretty
+import Data.List
+import Data.List.Extra
+import qualified Data.Text.Lazy as Text
+import qualified Data.Text.Lazy.Encoding as Text
+import Data.Typeable
+import System.Exit
+import System.FilePath
+import System.IO.Temp (withSystemTempDirectory)
+import System.Process
+import Test.HUnit
+import TestRunner
+
+import Util
+
+import Thrift.Compiler
+import Thrift.Compiler.GenHaskell
+import Thrift.Compiler.GenJSON
+import Thrift.Compiler.GenJSONLoc
+import Thrift.Compiler.Options
+import Thrift.Compiler.OptParse
+
+import Language.Haskell.Exts
+
+main :: IO ()
+main = withFixtureOptions $ \opts -> do
+  fixtures <- mapM genFixtures opts
+  testRunner $ TestList $ map checkFixture $ concat fixtures
+
+genFixtures :: SomeOptions -> IO [ThriftModule]
+genFixtures (TheseOptions opts@Options{..}) = do
+  (headModule, deps) <- typecheckInput opts =<< parseAll opts optsPath
+  generator headModule deps
+  where
+    generator prog deps = case optsGenMode of
+      EmitCode
+        | Just (hsopts, ps) <- cast (opts, prog : deps) ->
+            concat <$> mapM @[] (genHsCode hsopts) ps
+      EmitJSON WithoutLoc
+        | optsSingleOutput -> return [genJSONThriftModule (Just deps) prog]
+        | otherwise -> return $ map (genJSONThriftModule Nothing) $ prog : deps
+      EmitJSON WithLoc
+        | optsSingleOutput -> return [genJSONLocThriftModule (Just deps) prog]
+        | otherwise -> return $ map (genJSONLocThriftModule Nothing)
+                              $ prog : deps
+      _ -> return []
+
+    prettyJSON = encodePretty' defConfig { confCompare = compare }
+
+    genJSONThriftModule ds prog = ThriftModule
+      { tmPath = uncurry (</>) $ getAstPath prog
+      , tmContents =
+          Text.unpack $ Text.decodeUtf8 $ prettyJSON $ genJSON prog ds
+      , tmModuleName = ""
+      }
+    genJSONLocThriftModule ds prog = ThriftModule
+      { tmPath = uncurry (</>) $ getAstPath prog
+      , tmContents =
+          Text.unpack $ Text.decodeUtf8 $ prettyJSON $ genJSONLoc prog ds
+      , tmModuleName = ""
+      }
+
+checkFixture :: ThriftModule -> Test
+checkFixture ThriftModule{..} = TestLabel mname $ TestCase $ do
+  when (canParse tmPath) $ assertParseOk tmPath tmContents exts
+  fixture <- readFile tmPath
+  assertFileEqual tmPath fixture tmContents
+  where
+    mname = snd $ breakOnEnd "/test/fixtures/" tmPath
+    canParse filename
+      | isSuffixOf ".ast" filename = False
+      | isSuffixOf "Service.hs" filename = False
+      -- Service.hs does not parse due to
+      -- https://github.com/haskell-suite/haskell-src-exts/issues/310
+      -- (I think)
+      | otherwise = True
+    exts = map EnableExtension [ConstraintKinds]
+
+assertParseOk :: FilePath -> String -> [Extension] -> IO ()
+assertParseOk path contents exts =
+  case parseFileContentsWithExts exts contents of
+    ParseOk _ -> return ()
+    ParseFailed loc str -> do
+      putStrLn path
+      putStrLn "Contents:"
+      putStrLn contents
+      assertFailure $ "Parse failed at [" ++ path ++ "] (" ++
+        show (srcLine loc) ++ ":" ++ show (srcColumn loc) ++ "): " ++ str
+
+assertFileEqual :: FilePath -> String -> String -> IO ()
+assertFileEqual _path expected obtained =
+  unless (normalize expected == normalize obtained) $ withSystemTempDirectory "diff" $ \dir -> do
+    let expectPath = dir </> "expect"
+        obtainPath = dir </> "obtain"
+    writeFile expectPath (normalize expected)
+    writeFile obtainPath (normalize obtained)
+    let cp = proc "diff" ["-U", "10", expectPath, obtainPath]
+    (ec, out, _err) <- readCreateProcessWithExitCode cp ""
+    unless (ExitSuccess == ec) $ do
+      assertFailure out
+  where
+    -- In dependent-sum > 0.6 the This constructor was renamed to Some
+    normalize
+      = Text.unpack
+      . Text.unlines
+      . map fixLine
+      . Text.lines
+      . Text.pack
+
+    fixLine
+      = Text.replace "\"compiler/test/fixtures/"
+                     "\"test/fixtures/"
+      . Text.replace "\"include_path\": \"compiler\","
+                     "\"include_path\": \".\","
+    -- TODO: update the fixtures and remove this replace once 8.8 lands
+      . Text.replace "Thrift.This" "Thrift.Some"
diff --git a/test/fixtures/gen-basic-loc/a.ast b/test/fixtures/gen-basic-loc/a.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic-loc/a.ast
@@ -0,0 +1,587 @@
+{
+    "consts": [
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 7, locEndLine = 9, locEndCol = 8}"
+                ],
+                "type": {
+                    "name": "T"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 1, locEndLine = 9, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 9, locEndLine = 9, locEndCol = 10}",
+            "name": "a",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+                "name": {
+                    "name": "T"
+                },
+                "type": "typedef"
+            },
+            "value": {
+                "named_constant": {
+                    "name": "i64_value",
+                    "src": "b"
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 7, locEndLine = 9, locEndCol = 8}",
+                    "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 13, locEndLine = 9, locEndCol = 24}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 11, locEndLine = 51, locEndCol = 20}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 7, locEndLine = 31, locEndCol = 8}"
+                ],
+                "type": {
+                    "name": "U"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 1, locEndLine = 31, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 9, locEndLine = 31, locEndCol = 10}",
+            "name": "u",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}",
+                "name": {
+                    "name": "U"
+                },
+                "type": "union"
+            },
+            "value": {
+                "literal": {
+                    "type": "union",
+                    "value": {
+                        "field_name": "y",
+                        "field_type": {
+                            "inner_type": {
+                                "type": "string"
+                            },
+                            "type": "list"
+                        },
+                        "field_value": {
+                            "literal": {
+                                "type": "list",
+                                "value": [
+                                    {
+                                        "named_constant": {
+                                            "name": "string_value",
+                                            "src": "b"
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 7, locEndLine = 31, locEndCol = 8}",
+                    "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 7, locEndLine = 33, locEndCol = 10}"
+                ],
+                "type": {
+                    "name": "b.B"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 1, locEndLine = 33, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 11, locEndLine = 33, locEndCol = 12}",
+            "name": "b",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                "name": {
+                    "name": "B",
+                    "src": "b"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i16_value",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i32_value",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i64_value",
+                                    "src": "b"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 7, locEndLine = 33, locEndCol = 10}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 7, locEndLine = 35, locEndCol = 10}"
+                ],
+                "type": {
+                    "name": "b.B"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 1, locEndLine = 35, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 11, locEndLine = 35, locEndCol = 20}",
+            "name": "default_d",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                "name": {
+                    "name": "B",
+                    "src": "b"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 7, locEndLine = 35, locEndCol = 10}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 7, locEndLine = 37, locEndCol = 15}"
+                ],
+                "type": {
+                    "name": "b.Number"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 1, locEndLine = 37, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 16, locEndLine = 37, locEndCol = 20}",
+            "name": "zero",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                "name": {
+                    "name": "Number",
+                    "src": "b"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero",
+                        "src": "b"
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 7, locEndLine = 37, locEndCol = 15}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 23, locEndLine = 37, locEndCol = 29}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}"
+                }
+            ]
+        }
+    ],
+    "enums": [],
+    "includes": [
+        "test/if/b.thrift"
+    ],
+    "name": "a",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic-loc",
+        "path": "test/if/a.thrift",
+        "recursive": true
+    },
+    "path": "test/if/a.thrift",
+    "services": [
+        {
+            "functions": [
+                {
+                    "args": [
+                        {
+                            "id": 1,
+                            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 40, locStartCol = 29, locEndLine = 40, locEndCol = 30}",
+                            "name": "x",
+                            "type": {
+                                "type": "i32"
+                            },
+                            "xref": []
+                        }
+                    ],
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 40, locStartCol = 12, locEndLine = 40, locEndCol = 21}",
+                    "name": "getNumber",
+                    "oneway": false,
+                    "return_type": {
+                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                        "name": {
+                            "name": "Number",
+                            "src": "b"
+                        },
+                        "type": "enum"
+                    },
+                    "throws": []
+                },
+                {
+                    "args": [],
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 8, locEndLine = 42, locEndCol = 17}",
+                    "name": "doNothing",
+                    "oneway": false,
+                    "return_type": {
+                        "type": "void"
+                    },
+                    "throws": [
+                        {
+                            "id": 1,
+                            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 33, locEndLine = 42, locEndCol = 35}",
+                            "name": "ex",
+                            "type": {
+                                "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}",
+                                "name": {
+                                    "name": "X"
+                                },
+                                "type": "exception"
+                            },
+                            "xref": [
+                                {
+                                    "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 31, locEndLine = 42, locEndCol = 32}",
+                                    "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 39, locStartCol = 1, locEndLine = 39, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 39, locStartCol = 9, locEndLine = 39, locEndCol = 10}",
+            "name": "S"
+        },
+        {
+            "functions": [],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 45, locStartCol = 1, locEndLine = 45, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 45, locStartCol = 9, locEndLine = 45, locEndCol = 22}",
+            "name": "ParentService"
+        },
+        {
+            "functions": [
+                {
+                    "args": [],
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 49, locStartCol = 7, locEndLine = 49, locEndCol = 10}",
+                    "name": "foo",
+                    "oneway": false,
+                    "return_type": {
+                        "type": "i32"
+                    },
+                    "throws": []
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 48, locStartCol = 1, locEndLine = 48, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 48, locStartCol = 9, locEndLine = 48, locEndCol = 21}",
+            "name": "ChildService",
+            "super": {
+                "name": "ParentService"
+            }
+        }
+    ],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "default_value": {
+                        "named_constant": {
+                            "name": "a"
+                        }
+                    },
+                    "id": 1,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 12, locStartCol = 8, locEndLine = 12, locEndCol = 9}",
+                    "name": "a",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "type": "i64"
+                        },
+                        "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+                        "name": {
+                            "name": "T"
+                        },
+                        "type": "typedef"
+                    },
+                    "xref": [
+                        {
+                            "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 12, locStartCol = 6, locEndLine = 12, locEndCol = 7}",
+                            "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}"
+                        }
+                    ]
+                },
+                {
+                    "default_value": {
+                        "named_constant": {
+                            "name": "bool_value",
+                            "src": "b"
+                        }
+                    },
+                    "id": 3,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 13, locStartCol = 11, locEndLine = 13, locEndCol = 12}",
+                    "name": "c",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "bool"
+                    },
+                    "xref": []
+                },
+                {
+                    "id": 4,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 14, locStartCol = 22, locEndLine = 14, locEndCol = 23}",
+                    "name": "d",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "inner_type": {
+                                "type": "i32"
+                            },
+                            "type": "list"
+                        },
+                        "type": "list"
+                    },
+                    "xref": []
+                },
+                {
+                    "id": 5,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 15, locStartCol = 23, locEndLine = 15, locEndCol = 24}",
+                    "name": "e",
+                    "requiredness": "default",
+                    "type": {
+                        "key_type": {
+                            "type": "i32"
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "type": "string"
+                        }
+                    },
+                    "xref": []
+                },
+                {
+                    "default_value": {
+                        "literal": {
+                            "type": "enum",
+                            "value": {
+                                "name": "Two",
+                                "src": "b"
+                            }
+                        }
+                    },
+                    "id": 6,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 16, locStartCol = 15, locEndLine = 16, locEndCol = 16}",
+                    "name": "f",
+                    "requiredness": "default",
+                    "type": {
+                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                        "name": {
+                            "name": "Number",
+                            "src": "b"
+                        },
+                        "type": "enum"
+                    },
+                    "xref": [
+                        {
+                            "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 16, locStartCol = 6, locEndLine = 16, locEndCol = 14}",
+                            "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                        }
+                    ]
+                },
+                {
+                    "id": 7,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 17, locStartCol = 22, locEndLine = 17, locEndCol = 23}",
+                    "name": "g",
+                    "requiredness": "optional",
+                    "type": {
+                        "type": "string"
+                    },
+                    "xref": []
+                },
+                {
+                    "id": 8,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 18, locStartCol = 22, locEndLine = 18, locEndCol = 23}",
+                    "name": "h",
+                    "requiredness": "required",
+                    "type": {
+                        "type": "string"
+                    },
+                    "xref": []
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 11, locStartCol = 1, locEndLine = 11, locEndCol = 7}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 11, locStartCol = 8, locEndLine = 11, locEndCol = 9}",
+            "name": "A",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 28, locStartCol = 13, locEndLine = 28, locEndCol = 19}",
+                    "name": "reason",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "string"
+                    },
+                    "xref": []
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 1, locEndLine = 27, locEndCol = 10}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}",
+            "name": "X",
+            "struct_type": "EXCEPTION"
+        }
+    ],
+    "typedefs": [
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 9, locEndLine = 7, locEndCol = 12}"
+                ],
+                "type": {
+                    "type": "i64"
+                }
+            },
+            "anns": null,
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 1, locEndLine = 7, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+            "name": "T",
+            "newtype": false,
+            "type": {
+                "type": "i64"
+            },
+            "xref": []
+        }
+    ],
+    "unions": [
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 22, locStartCol = 11, locEndLine = 22, locEndCol = 12}",
+                    "name": "x",
+                    "type": {
+                        "type": "byte"
+                    }
+                },
+                {
+                    "id": 2,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 23, locStartCol = 19, locEndLine = 23, locEndCol = 20}",
+                    "name": "y",
+                    "type": {
+                        "inner_type": {
+                            "type": "string"
+                        },
+                        "type": "list"
+                    }
+                },
+                {
+                    "id": 3,
+                    "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 24, locStartCol = 15, locEndLine = 24, locEndCol = 16}",
+                    "name": "z",
+                    "type": {
+                        "inner_type": {
+                            "type": "i64"
+                        },
+                        "type": "set"
+                    }
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 1, locEndLine = 21, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}",
+            "name": "U"
+        }
+    ]
+}
diff --git a/test/fixtures/gen-basic-loc/b.ast b/test/fixtures/gen-basic-loc/b.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic-loc/b.ast
@@ -0,0 +1,1258 @@
+{
+    "consts": [
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 7, locEndLine = 48, locEndCol = 11}"
+                ],
+                "type": {
+                    "type": "byte"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 1, locEndLine = 48, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 12, locEndLine = 48, locEndCol = 22}",
+            "name": "byte_value",
+            "type": {
+                "type": "byte"
+            },
+            "value": {
+                "literal": {
+                    "type": "byte",
+                    "value": 0
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 7, locEndLine = 49, locEndCol = 10}"
+                ],
+                "type": {
+                    "type": "i16"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 1, locEndLine = 49, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 11, locEndLine = 49, locEndCol = 20}",
+            "name": "i16_value",
+            "type": {
+                "type": "i16"
+            },
+            "value": {
+                "literal": {
+                    "type": "i16",
+                    "value": 1
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 7, locEndLine = 50, locEndCol = 10}"
+                ],
+                "type": {
+                    "type": "i32"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 1, locEndLine = 50, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 11, locEndLine = 50, locEndCol = 20}",
+            "name": "i32_value",
+            "type": {
+                "type": "i32"
+            },
+            "value": {
+                "literal": {
+                    "type": "i32",
+                    "value": 2
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 7, locEndLine = 51, locEndCol = 10}"
+                ],
+                "type": {
+                    "type": "i64"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 1, locEndLine = 51, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 11, locEndLine = 51, locEndCol = 20}",
+            "name": "i64_value",
+            "type": {
+                "type": "i64"
+            },
+            "value": {
+                "literal": {
+                    "string": "3",
+                    "type": "i64",
+                    "value": 3
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 7, locEndLine = 52, locEndCol = 12}"
+                ],
+                "type": {
+                    "type": "float"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 1, locEndLine = 52, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 13, locEndLine = 52, locEndCol = 24}",
+            "name": "float_value",
+            "type": {
+                "type": "float"
+            },
+            "value": {
+                "literal": {
+                    "binary": "3f000000",
+                    "type": "float",
+                    "value": 0.5
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 7, locEndLine = 53, locEndCol = 13}"
+                ],
+                "type": {
+                    "type": "double"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 1, locEndLine = 53, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 14, locEndLine = 53, locEndCol = 26}",
+            "name": "double_value",
+            "type": {
+                "type": "double"
+            },
+            "value": {
+                "literal": {
+                    "binary": "400921f9f01b866e",
+                    "type": "double",
+                    "value": 3.14159
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 7, locEndLine = 54, locEndCol = 11}"
+                ],
+                "type": {
+                    "type": "bool"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 1, locEndLine = 54, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 12, locEndLine = 54, locEndCol = 22}",
+            "name": "bool_value",
+            "type": {
+                "type": "bool"
+            },
+            "value": {
+                "literal": {
+                    "type": "bool",
+                    "value": true
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 7, locEndLine = 55, locEndCol = 13}"
+                ],
+                "type": {
+                    "type": "string"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 1, locEndLine = 55, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 14, locEndLine = 55, locEndCol = 26}",
+            "name": "string_value",
+            "type": {
+                "type": "string"
+            },
+            "value": {
+                "literal": {
+                    "type": "string",
+                    "value": "xxx"
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 7, locEndLine = 56, locEndCol = 13}"
+                ],
+                "type": {
+                    "type": "binary"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 1, locEndLine = 56, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 14, locEndLine = 56, locEndCol = 26}",
+            "name": "binary_value",
+            "type": {
+                "type": "binary"
+            },
+            "value": {
+                "literal": {
+                    "type": "binary",
+                    "value": "797979"
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 7, locEndLine = 57, locEndCol = 10}"
+                ],
+                "type": {
+                    "name": "Int"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 1, locEndLine = 57, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 11, locEndLine = 57, locEndCol = 24}",
+            "name": "newtype_value",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}",
+                "name": {
+                    "name": "Int"
+                },
+                "type": "newtype"
+            },
+            "value": {
+                "literal": {
+                    "type": "newtype",
+                    "value": {
+                        "string": "10",
+                        "type": "i64",
+                        "value": 10
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 7, locEndLine = 57, locEndCol = 10}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 7, locEndLine = 58, locEndCol = 13}"
+                ],
+                "type": {
+                    "name": "Number"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 1, locEndLine = 58, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 14, locEndLine = 58, locEndCol = 31}",
+            "name": "scoped_enum_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                "name": {
+                    "name": "Number"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero"
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 7, locEndLine = 58, locEndCol = 13}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 34, locEndLine = 58, locEndCol = 45}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 7, locEndLine = 59, locEndCol = 13}"
+                ],
+                "type": {
+                    "name": "Number"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 1, locEndLine = 59, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 14, locEndLine = 59, locEndCol = 24}",
+            "name": "enum_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                "name": {
+                    "name": "Number"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "One"
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 7, locEndLine = 59, locEndCol = 13}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 27, locEndLine = 59, locEndCol = 30}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 23, locStartCol = 3, locEndLine = 23, locEndCol = 6}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 7, locEndLine = 60, locEndCol = 20}"
+                ],
+                "type": {
+                    "name": "Number_Pseudo"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 1, locEndLine = 60, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 21, locEndLine = 60, locEndCol = 44}",
+            "name": "scoped_pseudoenum_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+                "name": {
+                    "name": "Number_Pseudo"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero"
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 7, locEndLine = 60, locEndCol = 20}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 47, locEndLine = 60, locEndCol = 65}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 33, locStartCol = 3, locEndLine = 33, locEndCol = 7}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 7, locEndLine = 61, locEndCol = 20}"
+                ],
+                "type": {
+                    "name": "Number_Pseudo"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 1, locEndLine = 61, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 21, locEndLine = 61, locEndCol = 37}",
+            "name": "pseudoenum_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+                "name": {
+                    "name": "Number_Pseudo"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Four"
+                    }
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 7, locEndLine = 61, locEndCol = 20}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}"
+                },
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 40, locEndLine = 61, locEndCol = 44}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 34, locStartCol = 3, locEndLine = 34, locEndCol = 7}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 7, locEndLine = 64, locEndCol = 11}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 11, locEndLine = 64, locEndCol = 12}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 15, locEndLine = 64, locEndCol = 16}"
+                ],
+                "type": {
+                    "inner_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 12, locEndLine = 64, locEndCol = 15}"
+                        ],
+                        "type": {
+                            "type": "i64"
+                        }
+                    },
+                    "type": "list"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 1, locEndLine = 64, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 17, locEndLine = 64, locEndCol = 27}",
+            "name": "list_value",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "type": "list"
+            },
+            "value": {
+                "literal": {
+                    "type": "list",
+                    "value": [
+                        {
+                            "literal": {
+                                "string": "0",
+                                "type": "i64",
+                                "value": 0
+                            }
+                        },
+                        {
+                            "named_constant": {
+                                "name": "i64_value"
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 7, locEndLine = 65, locEndCol = 10}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 10, locEndLine = 65, locEndCol = 11}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 17, locEndLine = 65, locEndCol = 18}"
+                ],
+                "type": {
+                    "inner_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 11, locEndLine = 65, locEndCol = 17}"
+                        ],
+                        "type": {
+                            "type": "string"
+                        }
+                    },
+                    "type": "set"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 1, locEndLine = 65, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 19, locEndLine = 65, locEndCol = 28}",
+            "name": "set_value",
+            "type": {
+                "inner_type": {
+                    "type": "string"
+                },
+                "type": "set"
+            },
+            "value": {
+                "literal": {
+                    "type": "set",
+                    "value": [
+                        {
+                            "named_constant": {
+                                "name": "string_value"
+                            }
+                        },
+                        {
+                            "literal": {
+                                "type": "string",
+                                "value": ""
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 7, locEndLine = 68, locEndCol = 10}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 10, locEndLine = 68, locEndCol = 11}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 14, locEndLine = 68, locEndCol = 15}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 20, locEndLine = 68, locEndCol = 21}"
+                ],
+                "type": {
+                    "key_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 11, locEndLine = 68, locEndCol = 14}"
+                        ],
+                        "type": {
+                            "type": "i64"
+                        }
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 16, locEndLine = 68, locEndCol = 20}"
+                        ],
+                        "type": {
+                            "type": "bool"
+                        }
+                    }
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 1, locEndLine = 68, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 22, locEndLine = 68, locEndCol = 31}",
+            "name": "map_value",
+            "type": {
+                "key_type": {
+                    "type": "i64"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "bool"
+                }
+            },
+            "value": {
+                "literal": {
+                    "type": "map",
+                    "value": [
+                        {
+                            "key": {
+                                "literal": {
+                                    "string": "0",
+                                    "type": "i64",
+                                    "value": 0
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "bool",
+                                    "value": true
+                                }
+                            }
+                        },
+                        {
+                            "key": {
+                                "literal": {
+                                    "string": "1",
+                                    "type": "i64",
+                                    "value": 1
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "bool",
+                                    "value": false
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 7, locEndLine = 69, locEndCol = 29}"
+                ],
+                "type": {
+                    "name": "map_string_string_6258"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 1, locEndLine = 69, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 30, locEndLine = 69, locEndCol = 44}",
+            "name": "hash_map_value",
+            "type": {
+                "inner_type": {
+                    "key_type": {
+                        "type": "string"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "string"
+                    }
+                },
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}",
+                "name": {
+                    "name": "map_string_string_6258"
+                },
+                "type": "typedef"
+            },
+            "value": {
+                "literal": {
+                    "type": "map",
+                    "value": [
+                        {
+                            "key": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "a"
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "A"
+                                }
+                            }
+                        },
+                        {
+                            "key": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "b"
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "B"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 7, locEndLine = 69, locEndCol = 29}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 7, locEndLine = 71, locEndCol = 8}"
+                ],
+                "type": {
+                    "name": "B"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 1, locEndLine = 71, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 9, locEndLine = 71, locEndCol = 21}",
+            "name": "struct_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                "name": {
+                    "name": "B"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i16",
+                                    "value": 1
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i32",
+                                    "value": 2
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "string": "3",
+                                    "type": "i64",
+                                    "value": 3
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 7, locEndLine = 71, locEndCol = 8}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 7, locEndLine = 72, locEndCol = 8}"
+                ],
+                "type": {
+                    "name": "B"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 1, locEndLine = 72, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 9, locEndLine = 72, locEndCol = 30}",
+            "name": "explicit_struct_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                "name": {
+                    "name": "B"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i16",
+                                    "value": 1
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i32",
+                                    "value": 2
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "string": "3",
+                                    "type": "i64",
+                                    "value": 3
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 7, locEndLine = 72, locEndCol = 8}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                }
+            ]
+        },
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 7, locEndLine = 73, locEndCol = 8}"
+                ],
+                "type": {
+                    "name": "C"
+                }
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 1, locEndLine = 73, locEndCol = 6}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 9, locEndLine = 73, locEndCol = 37}",
+            "name": "explicit_nested_struct_value",
+            "type": {
+                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}",
+                "name": {
+                    "name": "C"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "x",
+                            "field_type": {
+                                "inner_type": {
+                                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                                    "name": {
+                                        "name": "Number"
+                                    },
+                                    "type": "enum"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": []
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "y",
+                            "field_type": {
+                                "inner_type": {
+                                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+                                    "name": {
+                                        "name": "Number_Strict"
+                                    },
+                                    "type": "enum"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": []
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "z",
+                            "field_type": {
+                                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                                "name": {
+                                    "name": "B"
+                                },
+                                "type": "struct"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "struct",
+                                    "value": [
+                                        {
+                                            "field_name": "a",
+                                            "field_type": {
+                                                "type": "i16"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "type": "i16",
+                                                    "value": 1
+                                                }
+                                            }
+                                        },
+                                        {
+                                            "field_name": "b",
+                                            "field_type": {
+                                                "type": "i32"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "type": "i32",
+                                                    "value": 2
+                                                }
+                                            }
+                                        },
+                                        {
+                                            "field_name": "c",
+                                            "field_type": {
+                                                "type": "i64"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "string": "3",
+                                                    "type": "i64",
+                                                    "value": 3
+                                                }
+                                            }
+                                        }
+                                    ]
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "xref": [
+                {
+                    "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 7, locEndLine = 73, locEndCol = 8}",
+                    "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}"
+                }
+            ]
+        }
+    ],
+    "enums": [
+        {
+            "constants": [
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}",
+                    "name": "Zero",
+                    "value": 0
+                },
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 23, locStartCol = 3, locEndLine = 23, locEndCol = 6}",
+                    "name": "One",
+                    "value": 1
+                },
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 24, locStartCol = 3, locEndLine = 24, locEndCol = 6}",
+                    "name": "Two",
+                    "value": 2
+                },
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 25, locStartCol = 3, locEndLine = 25, locEndCol = 8}",
+                    "name": "Three",
+                    "value": 3
+                }
+            ],
+            "flavour": "sum_type",
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 1, locEndLine = 21, locEndCol = 5}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+            "name": "Number"
+        },
+        {
+            "constants": [
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 29, locStartCol = 3, locEndLine = 29, locEndCol = 7}",
+                    "name": "Zero",
+                    "value": 0
+                }
+            ],
+            "flavour": "sum_type",
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 1, locEndLine = 28, locEndCol = 5}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+            "name": "Number_Strict"
+        },
+        {
+            "constants": [
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 33, locStartCol = 3, locEndLine = 33, locEndCol = 7}",
+                    "name": "Zero",
+                    "value": 0
+                },
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 34, locStartCol = 3, locEndLine = 34, locEndCol = 7}",
+                    "name": "Four",
+                    "value": 4
+                }
+            ],
+            "flavour": "sum_type",
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 1, locEndLine = 32, locEndCol = 5}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+            "name": "Number_Pseudo"
+        },
+        {
+            "constants": [
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 38, locStartCol = 3, locEndLine = 38, locEndCol = 7}",
+                    "name": "Five",
+                    "value": 5
+                },
+                {
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 39, locStartCol = 3, locEndLine = 39, locEndCol = 7}",
+                    "name": "Zero",
+                    "value": 0
+                }
+            ],
+            "flavour": "sum_type",
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 37, locStartCol = 1, locEndLine = 37, locEndCol = 5}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 37, locStartCol = 6, locEndLine = 37, locEndCol = 26}",
+            "name": "Number_Discontinuous"
+        },
+        {
+            "constants": [],
+            "flavour": "sum_type",
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 42, locStartCol = 1, locEndLine = 42, locEndCol = 5}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 42, locStartCol = 6, locEndLine = 42, locEndCol = 18}",
+            "name": "Number_Empty"
+        }
+    ],
+    "includes": [],
+    "name": "b",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic-loc",
+        "path": "test/if/a.thrift",
+        "recursive": true
+    },
+    "path": "test/if/b.thrift",
+    "services": [],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "default_value": {
+                        "literal": {
+                            "type": "i16",
+                            "value": 1
+                        }
+                    },
+                    "id": 1,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 10, locStartCol = 10, locEndLine = 10, locEndCol = 11}",
+                    "name": "a",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i16"
+                    },
+                    "xref": []
+                },
+                {
+                    "id": 2,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 11, locStartCol = 10, locEndLine = 11, locEndCol = 11}",
+                    "name": "b",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    },
+                    "xref": []
+                },
+                {
+                    "id": 3,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 12, locStartCol = 10, locEndLine = 12, locEndCol = 11}",
+                    "name": "c",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i64"
+                    },
+                    "xref": []
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 1, locEndLine = 9, locEndCol = 7}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+            "name": "B",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 16, locStartCol = 19, locEndLine = 16, locEndCol = 20}",
+                    "name": "x",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                            "name": {
+                                "name": "Number"
+                            },
+                            "type": "enum"
+                        },
+                        "type": "list"
+                    },
+                    "xref": [
+                        {
+                            "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 16, locStartCol = 11, locEndLine = 16, locEndCol = 17}",
+                            "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                        }
+                    ]
+                },
+                {
+                    "id": 2,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 17, locStartCol = 26, locEndLine = 17, locEndCol = 27}",
+                    "name": "y",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+                            "name": {
+                                "name": "Number_Strict"
+                            },
+                            "type": "enum"
+                        },
+                        "type": "list"
+                    },
+                    "xref": [
+                        {
+                            "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 17, locStartCol = 11, locEndLine = 17, locEndCol = 24}",
+                            "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}"
+                        }
+                    ]
+                },
+                {
+                    "id": 3,
+                    "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 18, locStartCol = 8, locEndLine = 18, locEndCol = 9}",
+                    "name": "z",
+                    "requiredness": "default",
+                    "type": {
+                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                        "name": {
+                            "name": "B"
+                        },
+                        "type": "struct"
+                    },
+                    "xref": [
+                        {
+                            "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 18, locStartCol = 6, locEndLine = 18, locEndCol = 7}",
+                            "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                        }
+                    ]
+                }
+            ],
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 1, locEndLine = 15, locEndCol = 7}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}",
+            "name": "C",
+            "struct_type": "STRUCT"
+        }
+    ],
+    "typedefs": [
+        {
+            "ann_type": {
+                "anns": null,
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 9, locEndLine = 45, locEndCol = 12}"
+                ],
+                "type": {
+                    "type": "i64"
+                }
+            },
+            "anns": {
+                "loc_ann_list": [
+                    {
+                        "ann_tag": "hs.newtype",
+                        "ann_type": "SimpleAnn",
+                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 18, locEndLine = 45, locEndCol = 28}",
+                        "sep": {
+                            "sep_type": "NoSep"
+                        }
+                    }
+                ],
+                "loc_close": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 28, locEndLine = 45, locEndCol = 29}",
+                "loc_open": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 17, locEndLine = 45, locEndCol = 18}"
+            },
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 1, locEndLine = 45, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}",
+            "name": "Int",
+            "newtype": true,
+            "type": {
+                "type": "i64"
+            },
+            "xref": []
+        },
+        {
+            "ann_type": {
+                "anns": {
+                    "loc_ann_list": [
+                        {
+                            "ann_type": "ValueAnn",
+                            "loc_equal": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 38, locEndLine = 80, locEndCol = 39}",
+                            "loc_tag": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 30, locEndLine = 80, locEndCol = 37}",
+                            "loc_val": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 40, locEndLine = 80, locEndCol = 49}",
+                            "sep": {
+                                "sep_type": "NoSep"
+                            },
+                            "tag": "hs.type",
+                            "val": {
+                                "ann_value_type": "TextAnn",
+                                "q": "DoubleQuote",
+                                "t": "HashMap"
+                            }
+                        }
+                    ],
+                    "loc_close": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 49, locEndLine = 80, locEndCol = 50}",
+                    "loc_open": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 29, locEndLine = 80, locEndCol = 30}"
+                },
+                "loc": [
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 9, locEndLine = 80, locEndCol = 12}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 12, locEndLine = 80, locEndCol = 13}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 19, locEndLine = 80, locEndCol = 20}",
+                    "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 27, locEndLine = 80, locEndCol = 28}"
+                ],
+                "type": {
+                    "key_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 13, locEndLine = 80, locEndCol = 19}"
+                        ],
+                        "type": {
+                            "type": "string"
+                        }
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "anns": null,
+                        "loc": [
+                            "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 21, locEndLine = 80, locEndCol = 27}"
+                        ],
+                        "type": {
+                            "type": "string"
+                        }
+                    }
+                }
+            },
+            "anns": null,
+            "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 1, locEndLine = 80, locEndCol = 8}",
+            "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}",
+            "name": "map_string_string_6258",
+            "newtype": false,
+            "type": {
+                "key_type": {
+                    "type": "string"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "string"
+                }
+            },
+            "xref": []
+        }
+    ],
+    "unions": []
+}
diff --git a/test/fixtures/gen-basic/a.ast b/test/fixtures/gen-basic/a.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic/a.ast
@@ -0,0 +1,419 @@
+{
+    "consts": [
+        {
+            "name": "a",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "name": {
+                    "name": "T"
+                },
+                "type": "typedef"
+            },
+            "value": {
+                "named_constant": {
+                    "name": "i64_value",
+                    "src": "b"
+                }
+            }
+        },
+        {
+            "name": "u",
+            "type": {
+                "name": {
+                    "name": "U"
+                },
+                "type": "union"
+            },
+            "value": {
+                "literal": {
+                    "type": "union",
+                    "value": {
+                        "field_name": "y",
+                        "field_type": {
+                            "inner_type": {
+                                "type": "string"
+                            },
+                            "type": "list"
+                        },
+                        "field_value": {
+                            "literal": {
+                                "type": "list",
+                                "value": [
+                                    {
+                                        "named_constant": {
+                                            "name": "string_value",
+                                            "src": "b"
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        {
+            "name": "b",
+            "type": {
+                "name": {
+                    "name": "B",
+                    "src": "b"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i16_value",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i32_value",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "named_constant": {
+                                    "name": "i64_value",
+                                    "src": "b"
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "default_d",
+            "type": {
+                "name": {
+                    "name": "B",
+                    "src": "b"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "default": null
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "zero",
+            "type": {
+                "name": {
+                    "name": "Number",
+                    "src": "b"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero",
+                        "src": "b"
+                    }
+                }
+            }
+        }
+    ],
+    "enums": [],
+    "includes": [
+        "test/if/b.thrift"
+    ],
+    "name": "a",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic",
+        "path": "test/if/a.thrift",
+        "recursive": true
+    },
+    "path": "test/if/a.thrift",
+    "services": [
+        {
+            "functions": [
+                {
+                    "args": [
+                        {
+                            "id": 1,
+                            "name": "x",
+                            "type": {
+                                "type": "i32"
+                            }
+                        }
+                    ],
+                    "name": "getNumber",
+                    "oneway": false,
+                    "return_type": {
+                        "name": {
+                            "name": "Number",
+                            "src": "b"
+                        },
+                        "type": "enum"
+                    },
+                    "throws": []
+                },
+                {
+                    "args": [],
+                    "name": "doNothing",
+                    "oneway": false,
+                    "return_type": {
+                        "type": "void"
+                    },
+                    "throws": [
+                        {
+                            "id": 1,
+                            "name": "ex",
+                            "type": {
+                                "name": {
+                                    "name": "X"
+                                },
+                                "type": "exception"
+                            }
+                        }
+                    ]
+                }
+            ],
+            "name": "S"
+        },
+        {
+            "functions": [],
+            "name": "ParentService"
+        },
+        {
+            "functions": [
+                {
+                    "args": [],
+                    "name": "foo",
+                    "oneway": false,
+                    "return_type": {
+                        "type": "i32"
+                    },
+                    "throws": []
+                }
+            ],
+            "name": "ChildService",
+            "super": {
+                "name": "ParentService"
+            }
+        }
+    ],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "default_value": {
+                        "named_constant": {
+                            "name": "a"
+                        }
+                    },
+                    "id": 1,
+                    "name": "a",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "type": "i64"
+                        },
+                        "name": {
+                            "name": "T"
+                        },
+                        "type": "typedef"
+                    }
+                },
+                {
+                    "default_value": {
+                        "named_constant": {
+                            "name": "bool_value",
+                            "src": "b"
+                        }
+                    },
+                    "id": 3,
+                    "name": "c",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "bool"
+                    }
+                },
+                {
+                    "id": 4,
+                    "name": "d",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "inner_type": {
+                                "type": "i32"
+                            },
+                            "type": "list"
+                        },
+                        "type": "list"
+                    }
+                },
+                {
+                    "id": 5,
+                    "name": "e",
+                    "requiredness": "default",
+                    "type": {
+                        "key_type": {
+                            "type": "i32"
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "type": "string"
+                        }
+                    }
+                },
+                {
+                    "default_value": {
+                        "literal": {
+                            "type": "enum",
+                            "value": {
+                                "name": "Two",
+                                "src": "b"
+                            }
+                        }
+                    },
+                    "id": 6,
+                    "name": "f",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "Number",
+                            "src": "b"
+                        },
+                        "type": "enum"
+                    }
+                },
+                {
+                    "id": 7,
+                    "name": "g",
+                    "requiredness": "optional",
+                    "type": {
+                        "type": "string"
+                    }
+                },
+                {
+                    "id": 8,
+                    "name": "h",
+                    "requiredness": "required",
+                    "type": {
+                        "type": "string"
+                    }
+                }
+            ],
+            "name": "A",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "reason",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "string"
+                    }
+                }
+            ],
+            "name": "X",
+            "struct_type": "EXCEPTION"
+        }
+    ],
+    "typedefs": [
+        {
+            "name": "T",
+            "newtype": false,
+            "type": {
+                "type": "i64"
+            }
+        }
+    ],
+    "unions": [
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "x",
+                    "type": {
+                        "type": "byte"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "y",
+                    "type": {
+                        "inner_type": {
+                            "type": "string"
+                        },
+                        "type": "list"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "z",
+                    "type": {
+                        "inner_type": {
+                            "type": "i64"
+                        },
+                        "type": "set"
+                    }
+                }
+            ],
+            "name": "U"
+        }
+    ]
+}
diff --git a/test/fixtures/gen-basic/b.ast b/test/fixtures/gen-basic/b.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic/b.ast
@@ -0,0 +1,757 @@
+{
+    "consts": [
+        {
+            "name": "byte_value",
+            "type": {
+                "type": "byte"
+            },
+            "value": {
+                "literal": {
+                    "type": "byte",
+                    "value": 0
+                }
+            }
+        },
+        {
+            "name": "i16_value",
+            "type": {
+                "type": "i16"
+            },
+            "value": {
+                "literal": {
+                    "type": "i16",
+                    "value": 1
+                }
+            }
+        },
+        {
+            "name": "i32_value",
+            "type": {
+                "type": "i32"
+            },
+            "value": {
+                "literal": {
+                    "type": "i32",
+                    "value": 2
+                }
+            }
+        },
+        {
+            "name": "i64_value",
+            "type": {
+                "type": "i64"
+            },
+            "value": {
+                "literal": {
+                    "string": "3",
+                    "type": "i64",
+                    "value": 3
+                }
+            }
+        },
+        {
+            "name": "float_value",
+            "type": {
+                "type": "float"
+            },
+            "value": {
+                "literal": {
+                    "binary": "3f000000",
+                    "type": "float",
+                    "value": 0.5
+                }
+            }
+        },
+        {
+            "name": "double_value",
+            "type": {
+                "type": "double"
+            },
+            "value": {
+                "literal": {
+                    "binary": "400921f9f01b866e",
+                    "type": "double",
+                    "value": 3.14159
+                }
+            }
+        },
+        {
+            "name": "bool_value",
+            "type": {
+                "type": "bool"
+            },
+            "value": {
+                "literal": {
+                    "type": "bool",
+                    "value": true
+                }
+            }
+        },
+        {
+            "name": "string_value",
+            "type": {
+                "type": "string"
+            },
+            "value": {
+                "literal": {
+                    "type": "string",
+                    "value": "xxx"
+                }
+            }
+        },
+        {
+            "name": "binary_value",
+            "type": {
+                "type": "binary"
+            },
+            "value": {
+                "literal": {
+                    "type": "binary",
+                    "value": "797979"
+                }
+            }
+        },
+        {
+            "name": "newtype_value",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "name": {
+                    "name": "Int"
+                },
+                "type": "newtype"
+            },
+            "value": {
+                "literal": {
+                    "type": "newtype",
+                    "value": {
+                        "string": "10",
+                        "type": "i64",
+                        "value": 10
+                    }
+                }
+            }
+        },
+        {
+            "name": "scoped_enum_value",
+            "type": {
+                "name": {
+                    "name": "Number"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero"
+                    }
+                }
+            }
+        },
+        {
+            "name": "enum_value",
+            "type": {
+                "name": {
+                    "name": "Number"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "One"
+                    }
+                }
+            }
+        },
+        {
+            "name": "scoped_pseudoenum_value",
+            "type": {
+                "name": {
+                    "name": "Number_Pseudo"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Zero"
+                    }
+                }
+            }
+        },
+        {
+            "name": "pseudoenum_value",
+            "type": {
+                "name": {
+                    "name": "Number_Pseudo"
+                },
+                "type": "enum"
+            },
+            "value": {
+                "literal": {
+                    "type": "enum",
+                    "value": {
+                        "name": "Four"
+                    }
+                }
+            }
+        },
+        {
+            "name": "list_value",
+            "type": {
+                "inner_type": {
+                    "type": "i64"
+                },
+                "type": "list"
+            },
+            "value": {
+                "literal": {
+                    "type": "list",
+                    "value": [
+                        {
+                            "literal": {
+                                "string": "0",
+                                "type": "i64",
+                                "value": 0
+                            }
+                        },
+                        {
+                            "named_constant": {
+                                "name": "i64_value"
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "set_value",
+            "type": {
+                "inner_type": {
+                    "type": "string"
+                },
+                "type": "set"
+            },
+            "value": {
+                "literal": {
+                    "type": "set",
+                    "value": [
+                        {
+                            "named_constant": {
+                                "name": "string_value"
+                            }
+                        },
+                        {
+                            "literal": {
+                                "type": "string",
+                                "value": ""
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "map_value",
+            "type": {
+                "key_type": {
+                    "type": "i64"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "bool"
+                }
+            },
+            "value": {
+                "literal": {
+                    "type": "map",
+                    "value": [
+                        {
+                            "key": {
+                                "literal": {
+                                    "string": "0",
+                                    "type": "i64",
+                                    "value": 0
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "bool",
+                                    "value": true
+                                }
+                            }
+                        },
+                        {
+                            "key": {
+                                "literal": {
+                                    "string": "1",
+                                    "type": "i64",
+                                    "value": 1
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "bool",
+                                    "value": false
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "hash_map_value",
+            "type": {
+                "inner_type": {
+                    "key_type": {
+                        "type": "string"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "string"
+                    }
+                },
+                "name": {
+                    "name": "map_string_string_6258"
+                },
+                "type": "typedef"
+            },
+            "value": {
+                "literal": {
+                    "type": "map",
+                    "value": [
+                        {
+                            "key": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "a"
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "A"
+                                }
+                            }
+                        },
+                        {
+                            "key": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "b"
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "B"
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "struct_value",
+            "type": {
+                "name": {
+                    "name": "B"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i16",
+                                    "value": 1
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i32",
+                                    "value": 2
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "string": "3",
+                                    "type": "i64",
+                                    "value": 3
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "explicit_struct_value",
+            "type": {
+                "name": {
+                    "name": "B"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "a",
+                            "field_type": {
+                                "type": "i16"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i16",
+                                    "value": 1
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "b",
+                            "field_type": {
+                                "type": "i32"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "i32",
+                                    "value": 2
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "c",
+                            "field_type": {
+                                "type": "i64"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "string": "3",
+                                    "type": "i64",
+                                    "value": 3
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "explicit_nested_struct_value",
+            "type": {
+                "name": {
+                    "name": "C"
+                },
+                "type": "struct"
+            },
+            "value": {
+                "literal": {
+                    "type": "struct",
+                    "value": [
+                        {
+                            "field_name": "x",
+                            "field_type": {
+                                "inner_type": {
+                                    "name": {
+                                        "name": "Number"
+                                    },
+                                    "type": "enum"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": []
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "y",
+                            "field_type": {
+                                "inner_type": {
+                                    "name": {
+                                        "name": "Number_Strict"
+                                    },
+                                    "type": "enum"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": []
+                                }
+                            }
+                        },
+                        {
+                            "field_name": "z",
+                            "field_type": {
+                                "name": {
+                                    "name": "B"
+                                },
+                                "type": "struct"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "struct",
+                                    "value": [
+                                        {
+                                            "field_name": "a",
+                                            "field_type": {
+                                                "type": "i16"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "type": "i16",
+                                                    "value": 1
+                                                }
+                                            }
+                                        },
+                                        {
+                                            "field_name": "b",
+                                            "field_type": {
+                                                "type": "i32"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "type": "i32",
+                                                    "value": 2
+                                                }
+                                            }
+                                        },
+                                        {
+                                            "field_name": "c",
+                                            "field_type": {
+                                                "type": "i64"
+                                            },
+                                            "field_value": {
+                                                "literal": {
+                                                    "string": "3",
+                                                    "type": "i64",
+                                                    "value": 3
+                                                }
+                                            }
+                                        }
+                                    ]
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        }
+    ],
+    "enums": [
+        {
+            "constants": [
+                {
+                    "name": "Zero",
+                    "value": 0
+                },
+                {
+                    "name": "One",
+                    "value": 1
+                },
+                {
+                    "name": "Two",
+                    "value": 2
+                },
+                {
+                    "name": "Three",
+                    "value": 3
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "Number"
+        },
+        {
+            "constants": [
+                {
+                    "name": "Zero",
+                    "value": 0
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "Number_Strict"
+        },
+        {
+            "constants": [
+                {
+                    "name": "Zero",
+                    "value": 0
+                },
+                {
+                    "name": "Four",
+                    "value": 4
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "Number_Pseudo"
+        },
+        {
+            "constants": [
+                {
+                    "name": "Five",
+                    "value": 5
+                },
+                {
+                    "name": "Zero",
+                    "value": 0
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "Number_Discontinuous"
+        },
+        {
+            "constants": [],
+            "flavour": "sum_type",
+            "name": "Number_Empty"
+        }
+    ],
+    "includes": [],
+    "name": "b",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic",
+        "path": "test/if/a.thrift",
+        "recursive": true
+    },
+    "path": "test/if/b.thrift",
+    "services": [],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "default_value": {
+                        "literal": {
+                            "type": "i16",
+                            "value": 1
+                        }
+                    },
+                    "id": 1,
+                    "name": "a",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i16"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "b",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "c",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i64"
+                    }
+                }
+            ],
+            "name": "B",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "x",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "name": {
+                                "name": "Number"
+                            },
+                            "type": "enum"
+                        },
+                        "type": "list"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "y",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "name": {
+                                "name": "Number_Strict"
+                            },
+                            "type": "enum"
+                        },
+                        "type": "list"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "z",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "B"
+                        },
+                        "type": "struct"
+                    }
+                }
+            ],
+            "name": "C",
+            "struct_type": "STRUCT"
+        }
+    ],
+    "typedefs": [
+        {
+            "name": "Int",
+            "newtype": true,
+            "type": {
+                "type": "i64"
+            }
+        },
+        {
+            "name": "map_string_string_6258",
+            "newtype": false,
+            "type": {
+                "key_type": {
+                    "type": "string"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "string"
+                }
+            }
+        }
+    ],
+    "unions": []
+}
diff --git a/test/fixtures/gen-basic/c.ast b/test/fixtures/gen-basic/c.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic/c.ast
@@ -0,0 +1,250 @@
+{
+    "consts": [
+        {
+            "name": "MyConst",
+            "type": {
+                "key_type": {
+                    "type": "string"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "string"
+                }
+            },
+            "value": {
+                "literal": {
+                    "type": "map",
+                    "value": [
+                        {
+                            "key": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "ENUMERATOR"
+                                }
+                            },
+                            "val": {
+                                "literal": {
+                                    "type": "string",
+                                    "value": "value"
+                                }
+                            }
+                        }
+                    ]
+                }
+            }
+        }
+    ],
+    "enums": [
+        {
+            "constants": [
+                {
+                    "name": "UNKNOWN",
+                    "value": 0
+                },
+                {
+                    "name": "FIRST",
+                    "value": 1
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "MyEnum"
+        }
+    ],
+    "includes": [],
+    "name": "c",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic",
+        "path": "test/if/c.thrift",
+        "recursive": true
+    },
+    "path": "test/if/c.thrift",
+    "services": [
+        {
+            "functions": [
+                {
+                    "args": [
+                        {
+                            "id": 2,
+                            "name": "param",
+                            "type": {
+                                "inner_type": {
+                                    "type": "string"
+                                },
+                                "name": {
+                                    "name": "annotated_string"
+                                },
+                                "type": "typedef"
+                            }
+                        }
+                    ],
+                    "name": "my_function",
+                    "oneway": false,
+                    "return_type": {
+                        "type": "i64"
+                    },
+                    "throws": []
+                }
+            ],
+            "name": "MyService"
+        }
+    ],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "name",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "string"
+                    }
+                },
+                {
+                    "default_value": {
+                        "literal": {
+                            "string": "1",
+                            "type": "i64",
+                            "value": 1
+                        }
+                    },
+                    "id": 2,
+                    "name": "count",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i64"
+                    }
+                }
+            ],
+            "name": "FirstAnnotation",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "default_value": {
+                        "literal": {
+                            "string": "0",
+                            "type": "i64",
+                            "value": 0
+                        }
+                    },
+                    "id": 2,
+                    "name": "total",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "recurse",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "SecondAnnotation"
+                        },
+                        "type": "struct"
+                    }
+                },
+                {
+                    "id": 4,
+                    "name": "either",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "UnionAnnotation"
+                        },
+                        "type": "union"
+                    }
+                }
+            ],
+            "name": "SecondAnnotation",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 5,
+                    "name": "tag",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "type": "string"
+                        },
+                        "name": {
+                            "name": "annotated_string"
+                        },
+                        "type": "typedef"
+                    }
+                }
+            ],
+            "name": "MyStruct",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "message",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "string"
+                    }
+                }
+            ],
+            "name": "MyException",
+            "struct_type": "EXCEPTION"
+        }
+    ],
+    "typedefs": [
+        {
+            "name": "annotated_string",
+            "newtype": false,
+            "type": {
+                "type": "string"
+            }
+        }
+    ],
+    "unions": [
+        {
+            "fields": [
+                {
+                    "id": 2,
+                    "name": "left",
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "right",
+                    "type": {
+                        "type": "i64"
+                    }
+                }
+            ],
+            "name": "UnionAnnotation"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "int_value",
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "string_value",
+                    "type": {
+                        "type": "string"
+                    }
+                }
+            ],
+            "name": "MyUnion"
+        }
+    ]
+}
diff --git a/test/fixtures/gen-basic/d.ast b/test/fixtures/gen-basic/d.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-basic/d.ast
@@ -0,0 +1,383 @@
+{
+    "consts": [],
+    "enums": [
+        {
+            "constants": [
+                {
+                    "name": "HsEnum_ONE",
+                    "value": 1
+                },
+                {
+                    "name": "HsEnum_TWO",
+                    "value": 2
+                },
+                {
+                    "name": "HsEnum_THREE",
+                    "value": 3
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "HsEnum"
+        },
+        {
+            "constants": [],
+            "flavour": "sum_type",
+            "name": "HsEnumEmpty"
+        },
+        {
+            "constants": [
+                {
+                    "name": "HsEnumNoUnknownAnn_ONE",
+                    "value": 1
+                },
+                {
+                    "name": "HsEnumNoUnknownAnn_TWO",
+                    "value": 2
+                },
+                {
+                    "name": "HsEnumNoUnknownAnn_THREE",
+                    "value": 3
+                }
+            ],
+            "flavour": "sum_type",
+            "name": "HsEnumNoUnknownAnn"
+        },
+        {
+            "constants": [],
+            "flavour": "sum_type",
+            "name": "HsEnumEmptyNoUnknownAnn"
+        },
+        {
+            "constants": [
+                {
+                    "name": "hsEnumPseudoenumAnn_ONE",
+                    "value": 1
+                },
+                {
+                    "name": "hsEnumPseudoenumAnn_TWO",
+                    "value": 2
+                },
+                {
+                    "name": "hsEnumPseudoenumAnn_THREE",
+                    "value": 3
+                }
+            ],
+            "flavour": "pseudo",
+            "name": "HsEnumPseudoenumAnn"
+        },
+        {
+            "constants": [
+                {
+                    "name": "hsEnumDuplicatedPseudoenumAnn_ONE",
+                    "value": 1
+                },
+                {
+                    "name": "hsEnumDuplicatedPseudoenumAnn_TWO",
+                    "value": 2
+                },
+                {
+                    "name": "hsEnumDuplicatedPseudoenumAnn_THREE",
+                    "value": 3
+                }
+            ],
+            "flavour": "pseudo",
+            "name": "HsEnumDuplicatedPseudoenumAnn"
+        },
+        {
+            "constants": [],
+            "flavour": "pseudo",
+            "name": "HsEnumEmptyPseudoenumAnn"
+        },
+        {
+            "constants": [
+                {
+                    "name": "hsEnumPseudoenumThriftAnn_ONE",
+                    "value": 1
+                },
+                {
+                    "name": "hsEnumPseudoenumThriftAnn_TWO",
+                    "value": 2
+                },
+                {
+                    "name": "hsEnumPseudoenumThriftAnn_THREE",
+                    "value": 3
+                }
+            ],
+            "flavour": "pseudo",
+            "name": "HsEnumPseudoenumThriftAnn"
+        },
+        {
+            "constants": [],
+            "flavour": "pseudo",
+            "name": "HsEnumEmptyPseudoenumThriftAnn"
+        }
+    ],
+    "includes": [],
+    "name": "D",
+    "options": {
+        "genfiles": null,
+        "include_path": ".",
+        "out_path": "test/fixtures/gen-basic",
+        "path": "test/if/d.thrift",
+        "recursive": true
+    },
+    "path": "test/if/d.thrift",
+    "services": [],
+    "structs": [
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "hsStruct_strictann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "hsStruct_lazyann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "hsStruct_inherit",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsStruct",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "hsStrictAnn_strictann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "hsStrictAnn_lazyann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "hsStrictAnn_inherit",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsStrictAnn",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "hsLazyAnn_strictann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "hsLazyAnn_lazyann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "hsLazyAnn_inherit",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsLazyAnn",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "structprefixstrictann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "structprefixlazyann",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "structprefixinherit",
+                    "requiredness": "default",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsPrefixAnn",
+            "struct_type": "STRUCT"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "hsStructOfComplexTypes_a_struct",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "HsStruct"
+                        },
+                        "type": "struct"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "hsStructOfComplexTypes_a_union",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "HsUnion"
+                        },
+                        "type": "union"
+                    }
+                },
+                {
+                    "id": 3,
+                    "name": "hsStructOfComplexTypes_an_enum",
+                    "requiredness": "default",
+                    "type": {
+                        "name": {
+                            "name": "HsEnum"
+                        },
+                        "type": "enum"
+                    }
+                },
+                {
+                    "id": 4,
+                    "name": "hsStructOfComplexTypes_a_pseudoenum",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "type": "i32"
+                        },
+                        "name": {
+                            "name": "HsEnumPseudoenumAnn"
+                        },
+                        "type": "newtype"
+                    }
+                },
+                {
+                    "id": 5,
+                    "name": "hsStructOfComplexTypes_a_thrift_pseudoenum",
+                    "requiredness": "default",
+                    "type": {
+                        "inner_type": {
+                            "type": "i32"
+                        },
+                        "name": {
+                            "name": "HsEnumPseudoenumThriftAnn"
+                        },
+                        "type": "newtype"
+                    }
+                }
+            ],
+            "name": "HsStructOfComplexTypes",
+            "struct_type": "STRUCT"
+        }
+    ],
+    "typedefs": [
+        {
+            "name": "Hstypedef",
+            "newtype": false,
+            "type": {
+                "key_type": {
+                    "type": "string"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "string"
+                }
+            }
+        },
+        {
+            "name": "Hsnewtypeann",
+            "newtype": true,
+            "type": {
+                "key_type": {
+                    "type": "string"
+                },
+                "type": "map",
+                "val_type": {
+                    "type": "string"
+                }
+            }
+        }
+    ],
+    "unions": [
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "HsUnion_left",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "HsUnion_right",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsUnion"
+        },
+        {
+            "fields": [
+                {
+                    "id": 1,
+                    "name": "HsUnionNonEmptyAnn_left",
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                {
+                    "id": 2,
+                    "name": "HsUnionNonEmptyAnn_right",
+                    "type": {
+                        "type": "i32"
+                    }
+                }
+            ],
+            "name": "HsUnionNonEmptyAnn"
+        }
+    ]
+}
diff --git a/test/fixtures/gen-hs2/A/ChildService/Client.hs b/test/fixtures/gen-hs2/A/ChildService/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/ChildService/Client.hs
@@ -0,0 +1,143 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module A.ChildService.Client
+       (ChildService, foo, fooIO, send_foo, _build_foo, recv_foo,
+        _parse_foo)
+       where
+import qualified A.ParentService.Client as ParentService
+import qualified B.Types as B
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import A.Types
+
+data ChildService
+
+type instance Thrift.Super ChildService =
+     ParentService.ParentService
+
+foo ::
+      (Thrift.Protocol p, Thrift.ClientChannel c,
+       (Thrift.<:) s ChildService) =>
+      Thrift.ThriftM p c s Int.Int32
+foo
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (fooIO _proxy _channel _counter _opts)
+
+fooIO ::
+        (Thrift.Protocol p, Thrift.ClientChannel c,
+         (Thrift.<:) s ChildService) =>
+        Proxy.Proxy p ->
+          c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO Int.Int32
+fooIO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_foo _proxy)
+       send_foo _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_foo ::
+           (Thrift.Protocol p, Thrift.ClientChannel c,
+            (Thrift.<:) s ChildService) =>
+           Proxy.Proxy p ->
+             c s ->
+               Thrift.Counter ->
+                 Thrift.SendCallback ->
+                   Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_foo _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_foo _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_foo ::
+           (Thrift.Protocol p) =>
+           Proxy.Proxy p ->
+             Thrift.Response -> Prelude.Either Exception.SomeException Int.Int32
+recv_foo _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_foo _proxy) _response))
+
+_build_foo ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_foo _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "foo" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_foo ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p ->
+               Parser.Parser (Prelude.Either Exception.SomeException Int.Int32)
+_parse_foo _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "foo: expected reply but got function call"
+                    2 | _name == "foo" ->
+                        do let
+                             _idMap = HashMap.fromList [("foo_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI32Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseI32
+                                                                                _proxy)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "foo: expected reply but got oneway function call"
+                    _ -> Prelude.fail "foo: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/A/ChildService/Service.hs b/test/fixtures/gen-hs2/A/ChildService/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/ChildService/Service.hs
@@ -0,0 +1,122 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module A.ChildService.Service
+       (ChildServiceCommand(..), reqName', reqParser', respWriter',
+        methodsInfo')
+       where
+import qualified A.ParentService.Service as ParentService
+import qualified A.Types as Types
+import qualified B.Types as B
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data ChildServiceCommand a where
+  Foo :: ChildServiceCommand Int.Int32
+  SuperParentService ::
+    ParentService.ParentServiceCommand a -> ChildServiceCommand a
+
+instance Thrift.Processor ChildServiceCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: ChildServiceCommand a -> Text.Text
+reqName' Foo = "foo"
+reqName' (SuperParentService x) = ParentService.reqName' x
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p ->
+               Text.Text -> Parser.Parser (Thrift.Some ChildServiceCommand)
+reqParser' _proxy "foo"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some Foo)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _proxy funName
+  = do Thrift.Some x <- ParentService.reqParser' _proxy funName
+       Prelude.return (Thrift.Some (SuperParentService x))
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  ChildServiceCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum Foo{} _r
+  = (Thrift.genMsgBegin _proxy "foo" _msgType _seqNum <> _msgBody <>
+       Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genFieldPrim _proxy "" (Thrift.getI32Type _proxy) 0 0
+                                         (Thrift.genI32Prim _proxy)
+                                         _result],
+                                    Prelude.Nothing)
+respWriter' _proxy _seqNum (SuperParentService _x) _r
+  = ParentService.respWriter' _proxy _seqNum _x _r
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.union
+      (Map.fromList
+         [("foo", Thrift.MethodInfo Thrift.NormalPriority Prelude.False)])
+      ParentService.methodsInfo'
diff --git a/test/fixtures/gen-hs2/A/ParentService/Client.hs b/test/fixtures/gen-hs2/A/ParentService/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/ParentService/Client.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module A.ParentService.Client (ParentService) where
+import qualified B.Types as B
+import qualified Thrift.Codegen as Thrift
+import A.Types
+
+data ParentService
diff --git a/test/fixtures/gen-hs2/A/ParentService/Service.hs b/test/fixtures/gen-hs2/A/ParentService/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/ParentService/Service.hs
@@ -0,0 +1,71 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module A.ParentService.Service
+       (ParentServiceCommand, reqName', reqParser', respWriter',
+        methodsInfo')
+       where
+import qualified A.Types as Types
+import qualified B.Types as B
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data ParentServiceCommand a where
+
+instance Thrift.Processor ParentServiceCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: ParentServiceCommand a -> Text.Text
+reqName' _ = "unknown function"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p ->
+               Text.Text -> Parser.Parser (Thrift.Some ParentServiceCommand)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  ParentServiceCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _ = Prelude.errorWithoutStackTrace ("unknown function")
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo' = Map.fromList []
diff --git a/test/fixtures/gen-hs2/A/S/Client.hs b/test/fixtures/gen-hs2/A/S/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/S/Client.hs
@@ -0,0 +1,243 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module A.S.Client
+       (S, getNumber, getNumberIO, send_getNumber, _build_getNumber,
+        recv_getNumber, _parse_getNumber, doNothing, doNothingIO,
+        send_doNothing, _build_doNothing, recv_doNothing, _parse_doNothing)
+       where
+import qualified B.Types as B
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import A.Types
+
+data S
+
+getNumber ::
+            (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+            Int.Int32 -> Thrift.ThriftM p c s B.Number
+getNumber __field__x
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (getNumberIO _proxy _channel _counter _opts __field__x)
+
+getNumberIO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+              Proxy.Proxy p ->
+                c s ->
+                  Thrift.Counter ->
+                    Thrift.RpcOptions -> Int.Int32 -> Prelude.IO B.Number
+getNumberIO _proxy _channel _counter _opts __field__x
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_getNumber _proxy)
+       send_getNumber _proxy _channel _counter _sendCob _recvCob _opts
+         __field__x
+       Thrift.wait _handle
+
+send_getNumber ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback ->
+                         Thrift.RecvCallback ->
+                           Thrift.RpcOptions -> Int.Int32 -> Prelude.IO ()
+send_getNumber _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  __field__x
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString
+                  (_build_getNumber _proxy _seqNum __field__x))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_getNumber ::
+                 (Thrift.Protocol p) =>
+                 Proxy.Proxy p ->
+                   Thrift.Response -> Prelude.Either Exception.SomeException B.Number
+recv_getNumber _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_getNumber _proxy) _response))
+
+_build_getNumber ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> Int.Int32 -> ByteString.Builder
+_build_getNumber _proxy _seqNum __field__x
+  = Thrift.genMsgBegin _proxy "getNumber" 1 _seqNum <>
+      Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "x" (Thrift.getI32Type _proxy) 1 0
+           (Thrift.genI32Prim _proxy)
+           __field__x
+           : [])
+      <> Thrift.genMsgEnd _proxy
+
+_parse_getNumber ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p ->
+                     Parser.Parser (Prelude.Either Exception.SomeException B.Number)
+_parse_getNumber _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "getNumber: expected reply but got function call"
+                    2 | _name == "getNumber" ->
+                        do let
+                             _idMap = HashMap.fromList [("getNumber_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI32Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseEnum
+                                                                                _proxy
+                                                                                "Number")
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "getNumber: expected reply but got oneway function call"
+                    _ -> Prelude.fail "getNumber: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
+
+doNothing ::
+            (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+            Thrift.ThriftM p c s ()
+doNothing
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (doNothingIO _proxy _channel _counter _opts)
+
+doNothingIO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+              Proxy.Proxy p ->
+                c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO ()
+doNothingIO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_doNothing _proxy)
+       send_doNothing _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_doNothing ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s S) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback ->
+                         Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_doNothing _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_doNothing _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_doNothing ::
+                 (Thrift.Protocol p) =>
+                 Proxy.Proxy p ->
+                   Thrift.Response -> Prelude.Either Exception.SomeException ()
+recv_doNothing _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_doNothing _proxy) _response))
+
+_build_doNothing ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_doNothing _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "doNothing" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_doNothing ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p ->
+                     Parser.Parser (Prelude.Either Exception.SomeException ())
+_parse_doNothing _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "doNothing: expected reply but got function call"
+                    2 | _name == "doNothing" ->
+                        do let
+                             _idMap = HashMap.fromList [("ex", 1)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       1 | _type ==
+                                                                             Thrift.getStructType
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             (Prelude.Left .
+                                                                                Exception.SomeException)
+                                                                             (Thrift.parseStruct
+                                                                                _proxy
+                                                                                :: Parser.Parser X)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.return (Prelude.Right ())
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "doNothing: expected reply but got oneway function call"
+                    _ -> Prelude.fail "doNothing: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/A/S/Service.hs b/test/fixtures/gen-hs2/A/S/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/S/Service.hs
@@ -0,0 +1,171 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module A.S.Service
+       (SCommand(..), reqName', reqParser', respWriter', methodsInfo')
+       where
+import qualified A.Types as Types
+import qualified B.Types as B
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data SCommand a where
+  GetNumber :: Int.Int32 -> SCommand B.Number
+  DoNothing :: SCommand ()
+
+instance Thrift.Processor SCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: SCommand a -> Text.Text
+reqName' (GetNumber __field__x) = "getNumber"
+reqName' DoNothing = "doNothing"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p -> Text.Text -> Parser.Parser (Thrift.Some SCommand)
+reqParser' _proxy "getNumber"
+  = ST.runSTT
+      (do Prelude.return ()
+          __field__x <- ST.newSTRef Default.def
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               1 | _type == Thrift.getI32Type _proxy
+                                                                   ->
+                                                                   do !_val <- Trans.lift
+                                                                                 (Thrift.parseI32
+                                                                                    _proxy)
+                                                                      ST.writeSTRef __field__x _val
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do !__val__x <- ST.readSTRef __field__x
+                                           Prelude.pure (Thrift.Some (GetNumber __val__x))
+            _idMap = HashMap.fromList [("x", 1)]
+          _parse 0)
+reqParser' _proxy "doNothing"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some DoNothing)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  SCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum GetNumber{} _r
+  = (Thrift.genMsgBegin _proxy "getNumber" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genField _proxy "" (Thrift.getI32Type _proxy) 0 0
+                                         ((Thrift.genI32 _proxy . Prelude.fromIntegral .
+                                             Thrift.fromThriftEnum)
+                                            _result)],
+                                    Prelude.Nothing)
+respWriter' _proxy _seqNum DoNothing{} _r
+  = (Thrift.genMsgBegin _proxy "doNothing" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.Just _e@Types.X{} <- Exception.fromException _ex ->
+                             (2,
+                              Thrift.genStruct _proxy
+                                [Thrift.genField _proxy "ex" (Thrift.getStructType _proxy) 1 0
+                                   (Thrift.buildStruct _proxy _e)],
+                              Prelude.Just (_ex, Thrift.ClientError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2, Thrift.genStruct _proxy [],
+                                    Prelude.Nothing)
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.fromList
+      [("getNumber",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False),
+       ("doNothing",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False)]
diff --git a/test/fixtures/gen-hs2/A/Types.hs b/test/fixtures/gen-hs2/A/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/A/Types.hs
@@ -0,0 +1,408 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module A.Types
+       (T, a, A(A, a_a, a_c, a_d, a_e, a_f, a_g, a_h),
+        U(U_EMPTY, U_x, U_y, U_z), X(X, x_reason), u, b, default_d, zero)
+       where
+import qualified B.Types as B
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Map.Strict as Map
+import qualified Data.Ord as Ord
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Aeson ((.:), (.=))
+import Data.Monoid ((<>))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (++))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+type T = Int.Int64
+
+a :: T
+a = B.i64_value
+
+data A = A{a_a :: T, a_c :: Prelude.Bool, a_d :: [[Int.Int32]],
+           a_e :: Map.Map Int.Int32 Text.Text, a_f :: B.Number,
+           a_g :: Prelude.Maybe Text.Text, a_h :: Text.Text}
+         deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON A where
+  toJSON
+    (A __field__a __field__c __field__d __field__e __field__f
+       __field__g __field__h)
+    = Aeson.object
+        ("a" .= __field__a :
+           "c" .= __field__c :
+             "d" .= __field__d :
+               "e" .= Map.mapKeys Thrift.keyToStr __field__e :
+                 "f" .= __field__f :
+                   Prelude.maybe Prelude.id ((:) . ("g" .=)) __field__g
+                     ("h" .= __field__h : Prelude.mempty))
+
+instance Thrift.ThriftStruct A where
+  buildStruct _proxy
+    (A __field__a __field__c __field__d __field__e __field__f
+       __field__g __field__h)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "a" (Thrift.getI64Type _proxy) 1 0
+           (Thrift.genI64 _proxy __field__a)
+           :
+           Thrift.genFieldBool _proxy "c" 3 1 __field__c :
+             Thrift.genField _proxy "d" (Thrift.getListType _proxy) 4 3
+               (Thrift.genList _proxy (Thrift.getListType _proxy)
+                  (Thrift.genListPrim _proxy (Thrift.getI32Type _proxy)
+                     (Thrift.genI32Prim _proxy))
+                  __field__d)
+               :
+               Thrift.genField _proxy "e" (Thrift.getMapType _proxy) 5 4
+                 ((Thrift.genMap _proxy (Thrift.getI32Type _proxy)
+                     (Thrift.getStringType _proxy)
+                     Prelude.False
+                     (Thrift.genI32 _proxy)
+                     (Thrift.genText _proxy)
+                     . Map.toList)
+                    __field__e)
+                 :
+                 Thrift.genField _proxy "f" (Thrift.getI32Type _proxy) 6 5
+                   ((Thrift.genI32 _proxy . Prelude.fromIntegral .
+                       Thrift.fromThriftEnum)
+                      __field__f)
+                   :
+                   let (__cereal__g, __id__g)
+                         = case __field__g of
+                             Prelude.Just _val -> ((:)
+                                                     (Thrift.genField _proxy "g"
+                                                        (Thrift.getStringType _proxy)
+                                                        7
+                                                        6
+                                                        (Thrift.genText _proxy _val)),
+                                                   7)
+                             Prelude.Nothing -> (Prelude.id, 6)
+                     in
+                     __cereal__g
+                       (Thrift.genField _proxy "h" (Thrift.getStringType _proxy) 8 __id__g
+                          (Thrift.genText _proxy __field__h)
+                          : []))
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__a <- ST.newSTRef a
+            __field__c <- ST.newSTRef B.bool_value
+            __field__d <- ST.newSTRef Default.def
+            __field__e <- ST.newSTRef Default.def
+            __field__f <- ST.newSTRef B.Number_Two
+            __field__g <- ST.newSTRef Prelude.Nothing
+            __field__h <- ST.newSTRef Prelude.Nothing
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI64Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI64
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__a
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getBoolType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseBoolF
+                                                                                      _proxy
+                                                                                      _bool)
+                                                                        ST.writeSTRef __field__c
+                                                                          _val
+                                                                 4 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Prelude.snd
+                                                                                           <$>
+                                                                                           Thrift.parseList
+                                                                                             _proxy
+                                                                                             (Thrift.parseI32
+                                                                                                _proxy)))
+                                                                        ST.writeSTRef __field__d
+                                                                          _val
+                                                                 5 | _type ==
+                                                                       Thrift.getMapType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Map.fromList <$>
+                                                                                      Thrift.parseMap
+                                                                                        _proxy
+                                                                                        (Thrift.parseI32
+                                                                                           _proxy)
+                                                                                        (Thrift.parseText
+                                                                                           _proxy)
+                                                                                        Prelude.False)
+                                                                        ST.writeSTRef __field__e
+                                                                          _val
+                                                                 6 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseEnum
+                                                                                      _proxy
+                                                                                      "Number")
+                                                                        ST.writeSTRef __field__f
+                                                                          _val
+                                                                 7 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__g
+                                                                          (Prelude.Just _val)
+                                                                 8 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__h
+                                                                          (Prelude.Just _val)
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__a <- ST.readSTRef __field__a
+                                             !__val__c <- ST.readSTRef __field__c
+                                             !__val__d <- ST.readSTRef __field__d
+                                             !__val__e <- ST.readSTRef __field__e
+                                             !__val__f <- ST.readSTRef __field__f
+                                             !__val__g <- ST.readSTRef __field__g
+                                             !__maybe__h <- ST.readSTRef __field__h
+                                             case __maybe__h of
+                                               Prelude.Nothing -> Prelude.fail
+                                                                    "Error parsing type A: missing required field h of type Text.Text"
+                                               Prelude.Just __val__h -> Prelude.pure
+                                                                          (A __val__a __val__c
+                                                                             __val__d
+                                                                             __val__e
+                                                                             __val__f
+                                                                             __val__g
+                                                                             __val__h)
+              _idMap
+                = HashMap.fromList
+                    [("a", 1), ("c", 3), ("d", 4), ("e", 5), ("f", 6), ("g", 7),
+                     ("h", 8)]
+            _parse 0)
+
+instance DeepSeq.NFData A where
+  rnf
+    (A __field__a __field__c __field__d __field__e __field__f
+       __field__g __field__h)
+    = DeepSeq.rnf __field__a `Prelude.seq`
+        DeepSeq.rnf __field__c `Prelude.seq`
+          DeepSeq.rnf __field__d `Prelude.seq`
+            DeepSeq.rnf __field__e `Prelude.seq`
+              DeepSeq.rnf __field__f `Prelude.seq`
+                DeepSeq.rnf __field__g `Prelude.seq`
+                  DeepSeq.rnf __field__h `Prelude.seq` ()
+
+instance Default.Default A where
+  def
+    = A a B.bool_value Default.def Default.def B.Number_Two
+        Prelude.Nothing
+        ""
+
+instance Hashable.Hashable A where
+  hashWithSalt __salt (A _a _c _d _e _f _g _h)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt
+           (Hashable.hashWithSalt
+              (Hashable.hashWithSalt
+                 (Hashable.hashWithSalt
+                    (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _a) _c)
+                    _d)
+                 ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList) _e))
+              _f)
+           _g)
+        _h
+
+data U = U_x Int.Int8
+       | U_y [Text.Text]
+       | U_z (Set.Set Int.Int64)
+       | U_EMPTY
+         deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON U where
+  toJSON (U_x __x) = Aeson.object ["x" .= __x]
+  toJSON (U_y __y) = Aeson.object ["y" .= __y]
+  toJSON (U_z __z) = Aeson.object ["z" .= __z]
+  toJSON U_EMPTY = Aeson.object []
+
+instance Thrift.ThriftStruct U where
+  buildStruct _proxy (U_x __x)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "x" (Thrift.getByteType _proxy) 1 0
+           (Thrift.genBytePrim _proxy)
+           __x]
+  buildStruct _proxy (U_y __y)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "y" (Thrift.getListType _proxy) 2 0
+           (Thrift.genList _proxy (Thrift.getStringType _proxy)
+              (Thrift.genText _proxy)
+              __y)]
+  buildStruct _proxy (U_z __z)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "z" (Thrift.getSetType _proxy) 3 0
+           ((Thrift.genListPrim _proxy (Thrift.getI64Type _proxy)
+               (Thrift.genI64Prim _proxy)
+               . Set.toList)
+              __z)]
+  buildStruct _proxy U_EMPTY = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = do _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+         case _fieldBegin of
+           Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                     1 | _type == Thrift.getByteType _proxy ->
+                                                         do _val <- Thrift.parseByte _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (U_x _val)
+                                                     2 | _type == Thrift.getListType _proxy ->
+                                                         do _val <- Prelude.snd <$>
+                                                                      Thrift.parseList _proxy
+                                                                        (Thrift.parseText _proxy)
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (U_y _val)
+                                                     3 | _type == Thrift.getSetType _proxy ->
+                                                         do _val <- Set.fromList . Prelude.snd <$>
+                                                                      Thrift.parseList _proxy
+                                                                        (Thrift.parseI64 _proxy)
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (U_z _val)
+                                                     _ -> do Thrift.parseSkip _proxy _type
+                                                               Prelude.Nothing
+                                                             Thrift.parseStop _proxy
+                                                             Prelude.return U_EMPTY
+           Thrift.FieldEnd -> Prelude.return U_EMPTY
+    where
+      _idMap = HashMap.fromList [("x", 1), ("y", 2), ("z", 3)]
+
+instance DeepSeq.NFData U where
+  rnf (U_x __x) = DeepSeq.rnf __x
+  rnf (U_y __y) = DeepSeq.rnf __y
+  rnf (U_z __z) = DeepSeq.rnf __z
+  rnf U_EMPTY = ()
+
+instance Default.Default U where
+  def = U_EMPTY
+
+instance Hashable.Hashable U where
+  hashWithSalt __salt (U_x _x)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 1 _x)
+  hashWithSalt __salt (U_y _y)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 2 _y)
+  hashWithSalt __salt (U_z _z)
+    = Hashable.hashWithSalt __salt
+        (Hashable.hashWithSalt 3 (Set.elems _z))
+  hashWithSalt __salt U_EMPTY
+    = Hashable.hashWithSalt __salt (0 :: Prelude.Int)
+
+newtype X = X{x_reason :: Text.Text}
+            deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON X where
+  toJSON (X __field__reason)
+    = Aeson.object ("reason" .= __field__reason : Prelude.mempty)
+
+instance Thrift.ThriftStruct X where
+  buildStruct _proxy (X __field__reason)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "reason" (Thrift.getStringType _proxy) 1 0
+           (Thrift.genText _proxy __field__reason)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__reason <- ST.newSTRef ""
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__reason
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__reason <- ST.readSTRef
+                                                                 __field__reason
+                                             Prelude.pure (X __val__reason)
+              _idMap = HashMap.fromList [("reason", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData X where
+  rnf (X __field__reason)
+    = DeepSeq.rnf __field__reason `Prelude.seq` ()
+
+instance Default.Default X where
+  def = X ""
+
+instance Hashable.Hashable X where
+  hashWithSalt __salt (X _reason)
+    = Hashable.hashWithSalt __salt _reason
+
+instance Exception.Exception X
+
+u :: U
+u = U_y [B.string_value]
+
+b :: B.B
+b = (Default.def :: B.B){B.b_a = B.i16_value, B.b_b = B.i32_value,
+                         B.b_c = B.i64_value}
+
+default_d :: B.B
+default_d = Default.def :: B.B
+
+zero :: B.Number
+zero = B.Number_Zero
diff --git a/test/fixtures/gen-hs2/B/Types.hs b/test/fixtures/gen-hs2/B/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/B/Types.hs
@@ -0,0 +1,481 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module B.Types
+       (B(B, b_a, b_b, b_c), C(C, c_x, c_y, c_z),
+        Number(Number_Zero, Number_One, Number_Two, Number_Three,
+               Number__UNKNOWN),
+        Number_Strict(Number_Strict_Zero),
+        Number_Pseudo(Number_Pseudo, unNumber_Pseudo), number_Pseudo_Zero,
+        number_Pseudo_Four,
+        Number_Discontinuous(Number_Discontinuous_Five,
+                             Number_Discontinuous_Zero, Number_Discontinuous__UNKNOWN),
+        Number_Empty(Number_Empty__UNKNOWN), Int(Int, unInt), byte_value,
+        i16_value, i32_value, i64_value, float_value, double_value,
+        bool_value, string_value, binary_value, newtype_value,
+        scoped_enum_value, enum_value, scoped_pseudoenum_value,
+        pseudoenum_value, list_value, set_value, map_value, hash_map_value,
+        struct_value, explicit_struct_value, explicit_nested_struct_value,
+        Map_string_string_6258)
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.ByteString as ByteString
+import qualified Data.Default as Default
+import qualified Data.Function as Function
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Map.Strict as Map
+import qualified Data.Ord as Ord
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified GHC.Magic as GHC
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Monoid ((<>))
+import Prelude ((.), (++), (>), (==))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+data B = B{b_a :: Int.Int16, b_b :: Int.Int32, b_c :: Int.Int64}
+         deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON B where
+  toJSON (B __field__a __field__b __field__c)
+    = Aeson.object
+        ("a" .= __field__a :
+           "b" .= __field__b : "c" .= __field__c : Prelude.mempty)
+
+instance Thrift.ThriftStruct B where
+  buildStruct _proxy (B __field__a __field__b __field__c)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "a" (Thrift.getI16Type _proxy) 1 0
+           (Thrift.genI16Prim _proxy)
+           __field__a
+           :
+           Thrift.genFieldPrim _proxy "b" (Thrift.getI32Type _proxy) 2 1
+             (Thrift.genI32Prim _proxy)
+             __field__b
+             :
+             Thrift.genFieldPrim _proxy "c" (Thrift.getI64Type _proxy) 3 2
+               (Thrift.genI64Prim _proxy)
+               __field__c
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__a <- ST.newSTRef 1
+            __field__b <- ST.newSTRef Default.def
+            __field__c <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI16Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI16
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__a
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__b
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI64Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI64
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__c
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__a <- ST.readSTRef __field__a
+                                             !__val__b <- ST.readSTRef __field__b
+                                             !__val__c <- ST.readSTRef __field__c
+                                             Prelude.pure (B __val__a __val__b __val__c)
+              _idMap = HashMap.fromList [("a", 1), ("b", 2), ("c", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData B where
+  rnf (B __field__a __field__b __field__c)
+    = DeepSeq.rnf __field__a `Prelude.seq`
+        DeepSeq.rnf __field__b `Prelude.seq`
+          DeepSeq.rnf __field__c `Prelude.seq` ()
+
+instance Default.Default B where
+  def = B 1 Default.def Default.def
+
+instance Hashable.Hashable B where
+  hashWithSalt __salt (B _a _b _c)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _a) _b)
+        _c
+
+data C = C{c_x :: [Number], c_y :: [Number_Strict], c_z :: B}
+         deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON C where
+  toJSON (C __field__x __field__y __field__z)
+    = Aeson.object
+        ("x" .= __field__x :
+           "y" .= __field__y : "z" .= __field__z : Prelude.mempty)
+
+instance Thrift.ThriftStruct C where
+  buildStruct _proxy (C __field__x __field__y __field__z)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "x" (Thrift.getListType _proxy) 1 0
+           (Thrift.genList _proxy (Thrift.getI32Type _proxy)
+              (Thrift.genI32 _proxy . Prelude.fromIntegral .
+                 Thrift.fromThriftEnum)
+              __field__x)
+           :
+           Thrift.genField _proxy "y" (Thrift.getListType _proxy) 2 1
+             (Thrift.genList _proxy (Thrift.getI32Type _proxy)
+                (Thrift.genI32 _proxy . Prelude.fromIntegral .
+                   Thrift.fromThriftEnum)
+                __field__y)
+             :
+             Thrift.genField _proxy "z" (Thrift.getStructType _proxy) 3 2
+               (Thrift.buildStruct _proxy __field__z)
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__x <- ST.newSTRef Default.def
+            __field__y <- ST.newSTRef Default.def
+            __field__z <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Thrift.parseEnum
+                                                                                           _proxy
+                                                                                           "Number"))
+                                                                        ST.writeSTRef __field__x
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Thrift.parseEnumNoUnknown
+                                                                                           _proxy
+                                                                                           "Number_Strict"))
+                                                                        ST.writeSTRef __field__y
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getStructType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseStruct
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__z
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__x <- ST.readSTRef __field__x
+                                             !__val__y <- ST.readSTRef __field__y
+                                             !__val__z <- ST.readSTRef __field__z
+                                             Prelude.pure (C __val__x __val__y __val__z)
+              _idMap = HashMap.fromList [("x", 1), ("y", 2), ("z", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData C where
+  rnf (C __field__x __field__y __field__z)
+    = DeepSeq.rnf __field__x `Prelude.seq`
+        DeepSeq.rnf __field__y `Prelude.seq`
+          DeepSeq.rnf __field__z `Prelude.seq` ()
+
+instance Default.Default C where
+  def = C Default.def Default.def Default.def
+
+instance Hashable.Hashable C where
+  hashWithSalt __salt (C _x _y _z)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _x) _y)
+        _z
+
+data Number = Number_Zero
+            | Number_One
+            | Number_Two
+            | Number_Three
+            | Number__UNKNOWN Prelude.Int
+              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Number where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Number where
+  rnf __Number = Prelude.seq __Number ()
+
+instance Default.Default Number where
+  def = Number_Zero
+
+instance Hashable.Hashable Number where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Number where
+  toThriftEnum 0 = Number_Zero
+  toThriftEnum 1 = Number_One
+  toThriftEnum 2 = Number_Two
+  toThriftEnum 3 = Number_Three
+  toThriftEnum val = Number__UNKNOWN val
+  fromThriftEnum Number_Zero = 0
+  fromThriftEnum Number_One = 1
+  fromThriftEnum Number_Two = 2
+  fromThriftEnum Number_Three = 3
+  fromThriftEnum (Number__UNKNOWN val) = val
+  allThriftEnumValues
+    = [Number_Zero, Number_One, Number_Two, Number_Three]
+  toThriftEnumEither 0 = Prelude.Right Number_Zero
+  toThriftEnumEither 1 = Prelude.Right Number_One
+  toThriftEnumEither 2 = Prelude.Right Number_Two
+  toThriftEnumEither 3 = Prelude.Right Number_Three
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Number: " ++
+           Prelude.show val)
+
+data Number_Strict = Number_Strict_Zero
+                     deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Number_Strict where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Number_Strict where
+  rnf __Number_Strict = Prelude.seq __Number_Strict ()
+
+instance Default.Default Number_Strict where
+  def = Number_Strict_Zero
+
+instance Hashable.Hashable Number_Strict where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Number_Strict where
+  toThriftEnum 0 = Number_Strict_Zero
+  toThriftEnum _val
+    = Exception.throw
+        (Thrift.ProtocolException
+           ("toThriftEnum: not a valid identifier for enum Number_Strict: " ++
+              Prelude.show _val))
+  fromThriftEnum Number_Strict_Zero = 0
+  fromThriftEnum _val
+    = Exception.throw
+        (Thrift.ProtocolException
+           ("fromThriftEnum: not a valid identifier for enum Number_Strict: "
+              ++ Prelude.show _val))
+  allThriftEnumValues = [Number_Strict_Zero]
+  toThriftEnumEither 0 = Prelude.Right Number_Strict_Zero
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Number_Strict: "
+           ++ Prelude.show val)
+
+newtype Number_Pseudo = Number_Pseudo{unNumber_Pseudo :: Int.Int32}
+                        deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable Number_Pseudo where
+  hashWithSalt __salt (Number_Pseudo __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON Number_Pseudo where
+  toJSON (Number_Pseudo __val) = Aeson.toJSON __val
+
+number_Pseudo_Zero :: Number_Pseudo
+number_Pseudo_Zero = Number_Pseudo 0
+
+number_Pseudo_Four :: Number_Pseudo
+number_Pseudo_Four = Number_Pseudo 4
+
+data Number_Discontinuous = Number_Discontinuous_Zero
+                          | Number_Discontinuous_Five
+                          | Number_Discontinuous__UNKNOWN Prelude.Int
+                            deriving (Prelude.Eq, Prelude.Show)
+
+instance Aeson.ToJSON Number_Discontinuous where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Number_Discontinuous where
+  rnf __Number_Discontinuous = Prelude.seq __Number_Discontinuous ()
+
+instance Default.Default Number_Discontinuous where
+  def = Number_Discontinuous_Five
+
+instance Hashable.Hashable Number_Discontinuous where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Number_Discontinuous where
+  toThriftEnum 5 = Number_Discontinuous_Five
+  toThriftEnum 0 = Number_Discontinuous_Zero
+  toThriftEnum val = Number_Discontinuous__UNKNOWN val
+  fromThriftEnum Number_Discontinuous_Five = 5
+  fromThriftEnum Number_Discontinuous_Zero = 0
+  fromThriftEnum (Number_Discontinuous__UNKNOWN val) = val
+  allThriftEnumValues
+    = [Number_Discontinuous_Zero, Number_Discontinuous_Five]
+  toThriftEnumEither 5 = Prelude.Right Number_Discontinuous_Five
+  toThriftEnumEither 0 = Prelude.Right Number_Discontinuous_Zero
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Number_Discontinuous: "
+           ++ Prelude.show val)
+
+instance Prelude.Ord Number_Discontinuous where
+  compare = Function.on Prelude.compare Thrift.fromThriftEnum
+
+data Number_Empty = Number_Empty__UNKNOWN Prelude.Int
+                    deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Number_Empty where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Number_Empty where
+  rnf __Number_Empty = Prelude.seq __Number_Empty ()
+
+instance Default.Default Number_Empty where
+  def
+    = Exception.throw
+        (Thrift.ProtocolException
+           "def: enum Number_Empty has no constructors")
+
+instance Hashable.Hashable Number_Empty where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Number_Empty where
+  toThriftEnum val = Number_Empty__UNKNOWN val
+  fromThriftEnum (Number_Empty__UNKNOWN val) = val
+  allThriftEnumValues = []
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Number_Empty: "
+           ++ Prelude.show val)
+
+newtype Int = Int{unInt :: Int.Int64}
+              deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable Int where
+  hashWithSalt __salt (Int __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON Int where
+  toJSON (Int __val) = Aeson.toJSON __val
+
+byte_value :: Int.Int8
+byte_value = 0
+
+i16_value :: Int.Int16
+i16_value = 1
+
+i32_value :: Int.Int32
+i32_value = 2
+
+i64_value :: Int.Int64
+i64_value = 3
+
+float_value :: Prelude.Float
+float_value = 0.5
+
+double_value :: Prelude.Double
+double_value = 3.14159
+
+bool_value :: Prelude.Bool
+bool_value = Prelude.True
+
+string_value :: Text.Text
+string_value = "xxx"
+
+binary_value :: ByteString.ByteString
+binary_value = "yyy"
+
+newtype_value :: Int
+newtype_value = Int 10
+
+scoped_enum_value :: Number
+scoped_enum_value = Number_Zero
+
+enum_value :: Number
+enum_value = Number_One
+
+scoped_pseudoenum_value :: Number_Pseudo
+scoped_pseudoenum_value = number_Pseudo_Zero
+
+pseudoenum_value :: Number_Pseudo
+pseudoenum_value = number_Pseudo_Four
+
+list_value :: [Int.Int64]
+list_value = [0, i64_value]
+
+set_value :: Set.Set Text.Text
+set_value = Set.fromList [string_value, ""]
+
+map_value :: Map.Map Int.Int64 Prelude.Bool
+map_value = Map.fromList [(0, Prelude.True), (1, Prelude.False)]
+
+hash_map_value :: Map_string_string_6258
+hash_map_value = HashMap.fromList [("a", "A"), ("b", "B")]
+
+struct_value :: B
+struct_value = (Default.def :: B){b_a = 1, b_b = 2, b_c = 3}
+
+explicit_struct_value :: B
+explicit_struct_value
+  = (Default.def :: B){b_a = 1, b_b = 2, b_c = 3}
+
+explicit_nested_struct_value :: C
+explicit_nested_struct_value
+  = (Default.def :: C){c_x = [], c_y = [],
+                       c_z = (Default.def :: B){b_a = 1, b_b = 2, b_c = 3}}
+
+type Map_string_string_6258 = HashMap.HashMap Text.Text Text.Text
diff --git a/test/fixtures/gen-hs2/D/Types.hs b/test/fixtures/gen-hs2/D/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/D/Types.hs
@@ -0,0 +1,1127 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module D.Types
+       (Hstypedef, Hsnewtypeann(Hsnewtypeann, unHsnewtypeann),
+        HsStruct(HsStruct, hsStruct_strictann, hsStruct_lazyann,
+                 hsStruct_inherit),
+        HsStrictAnn(HsStrictAnn, hsStrictAnn_strictann,
+                    hsStrictAnn_lazyann, hsStrictAnn_inherit),
+        HsLazyAnn(HsLazyAnn, hsLazyAnn_strictann, hsLazyAnn_lazyann,
+                  hsLazyAnn_inherit),
+        HsPrefixAnn(HsPrefixAnn, structprefixstrictann,
+                    structprefixlazyann, structprefixinherit),
+        HsUnion(HsUnion_EMPTY, HsUnion_left, HsUnion_right),
+        HsUnionNonEmptyAnn(HsUnionNonEmptyAnn_left,
+                           HsUnionNonEmptyAnn_right),
+        HsEnum(HsEnum_ONE, HsEnum_TWO, HsEnum_THREE, HsEnum__UNKNOWN),
+        HsEnumEmpty(HsEnumEmpty__UNKNOWN),
+        HsEnumNoUnknownAnn(HsEnumNoUnknownAnn_ONE, HsEnumNoUnknownAnn_TWO,
+                           HsEnumNoUnknownAnn_THREE),
+        HsEnumEmptyNoUnknownAnn(),
+        HsEnumPseudoenumAnn(HsEnumPseudoenumAnn, unHsEnumPseudoenumAnn),
+        hsEnumPseudoenumAnn_ONE, hsEnumPseudoenumAnn_TWO,
+        hsEnumPseudoenumAnn_THREE,
+        HsEnumDuplicatedPseudoenumAnn(HsEnumDuplicatedPseudoenumAnn,
+                                      unHsEnumDuplicatedPseudoenumAnn),
+        hsEnumDuplicatedPseudoenumAnn_ONE,
+        hsEnumDuplicatedPseudoenumAnn_TWO,
+        hsEnumDuplicatedPseudoenumAnn_THREE,
+        HsEnumEmptyPseudoenumAnn(HsEnumEmptyPseudoenumAnn,
+                                 unHsEnumEmptyPseudoenumAnn),
+        HsEnumPseudoenumThriftAnn(HsEnumPseudoenumThriftAnn,
+                                  unHsEnumPseudoenumThriftAnn),
+        hsEnumPseudoenumThriftAnn_ONE, hsEnumPseudoenumThriftAnn_TWO,
+        hsEnumPseudoenumThriftAnn_THREE,
+        HsEnumEmptyPseudoenumThriftAnn(HsEnumEmptyPseudoenumThriftAnn,
+                                       unHsEnumEmptyPseudoenumThriftAnn),
+        HsStructOfComplexTypes(HsStructOfComplexTypes,
+                               hsStructOfComplexTypes_a_struct, hsStructOfComplexTypes_a_union,
+                               hsStructOfComplexTypes_an_enum,
+                               hsStructOfComplexTypes_a_pseudoenum,
+                               hsStructOfComplexTypes_a_thrift_pseudoenum))
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.Function as Function
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Map.Strict as Map
+import qualified Data.Ord as Ord
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified GHC.Magic as GHC
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Aeson ((.:), (.=))
+import Data.Monoid ((<>))
+import Prelude ((.), (++), (>), (==))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (++))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+type Hstypedef = Map.Map Text.Text Text.Text
+
+newtype Hsnewtypeann = Hsnewtypeann{unHsnewtypeann ::
+                                    Map.Map Text.Text Text.Text}
+                       deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable Hsnewtypeann where
+  hashWithSalt __salt (Hsnewtypeann __val)
+    = Hashable.hashWithSalt __salt
+        ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList) __val)
+
+instance Aeson.ToJSON Hsnewtypeann where
+  toJSON (Hsnewtypeann __val) = Aeson.toJSON __val
+
+data HsStruct = HsStruct{hsStruct_strictann ::
+                         {-# UNPACK #-} !Int.Int32,
+                         hsStruct_lazyann :: Int.Int32, hsStruct_inherit :: Int.Int32}
+                deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsStruct where
+  toJSON
+    (HsStruct __field__strictann __field__lazyann __field__inherit)
+    = Aeson.object
+        ("strictann" .= __field__strictann :
+           "lazyann" .= __field__lazyann :
+             "inherit" .= __field__inherit : Prelude.mempty)
+
+instance Thrift.ThriftStruct HsStruct where
+  buildStruct _proxy
+    (HsStruct __field__strictann __field__lazyann __field__inherit)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "strictann" (Thrift.getI32Type _proxy)
+           1
+           0
+           (Thrift.genI32Prim _proxy)
+           __field__strictann
+           :
+           Thrift.genFieldPrim _proxy "lazyann" (Thrift.getI32Type _proxy) 2 1
+             (Thrift.genI32Prim _proxy)
+             __field__lazyann
+             :
+             Thrift.genFieldPrim _proxy "inherit" (Thrift.getI32Type _proxy) 3 2
+               (Thrift.genI32Prim _proxy)
+               __field__inherit
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__strictann <- ST.newSTRef Default.def
+            __field__lazyann <- ST.newSTRef Default.def
+            __field__inherit <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__strictann
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__lazyann
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__inherit
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__strictann <- ST.readSTRef
+                                                                    __field__strictann
+                                             !__val__lazyann <- ST.readSTRef __field__lazyann
+                                             !__val__inherit <- ST.readSTRef __field__inherit
+                                             Prelude.pure
+                                               (HsStruct __val__strictann __val__lazyann
+                                                  __val__inherit)
+              _idMap
+                = HashMap.fromList
+                    [("strictann", 1), ("lazyann", 2), ("inherit", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData HsStruct where
+  rnf (HsStruct __field__strictann __field__lazyann __field__inherit)
+    = DeepSeq.rnf __field__strictann `Prelude.seq`
+        DeepSeq.rnf __field__lazyann `Prelude.seq`
+          DeepSeq.rnf __field__inherit `Prelude.seq` ()
+
+instance Default.Default HsStruct where
+  def = HsStruct Default.def Default.def Default.def
+
+instance Hashable.Hashable HsStruct where
+  hashWithSalt __salt (HsStruct _strictann _lazyann _inherit)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _strictann)
+           _lazyann)
+        _inherit
+
+data HsStrictAnn = HsStrictAnn{hsStrictAnn_strictann ::
+                               {-# UNPACK #-} !Int.Int32,
+                               hsStrictAnn_lazyann :: Int.Int32,
+                               hsStrictAnn_inherit :: {-# UNPACK #-} !Int.Int32}
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsStrictAnn where
+  toJSON
+    (HsStrictAnn __field__strictann __field__lazyann __field__inherit)
+    = Aeson.object
+        ("strictann" .= __field__strictann :
+           "lazyann" .= __field__lazyann :
+             "inherit" .= __field__inherit : Prelude.mempty)
+
+instance Thrift.ThriftStruct HsStrictAnn where
+  buildStruct _proxy
+    (HsStrictAnn __field__strictann __field__lazyann __field__inherit)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "strictann" (Thrift.getI32Type _proxy)
+           1
+           0
+           (Thrift.genI32Prim _proxy)
+           __field__strictann
+           :
+           Thrift.genFieldPrim _proxy "lazyann" (Thrift.getI32Type _proxy) 2 1
+             (Thrift.genI32Prim _proxy)
+             __field__lazyann
+             :
+             Thrift.genFieldPrim _proxy "inherit" (Thrift.getI32Type _proxy) 3 2
+               (Thrift.genI32Prim _proxy)
+               __field__inherit
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__strictann <- ST.newSTRef Default.def
+            __field__lazyann <- ST.newSTRef Default.def
+            __field__inherit <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__strictann
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__lazyann
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__inherit
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__strictann <- ST.readSTRef
+                                                                    __field__strictann
+                                             !__val__lazyann <- ST.readSTRef __field__lazyann
+                                             !__val__inherit <- ST.readSTRef __field__inherit
+                                             Prelude.pure
+                                               (HsStrictAnn __val__strictann __val__lazyann
+                                                  __val__inherit)
+              _idMap
+                = HashMap.fromList
+                    [("strictann", 1), ("lazyann", 2), ("inherit", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData HsStrictAnn where
+  rnf
+    (HsStrictAnn __field__strictann __field__lazyann __field__inherit)
+    = DeepSeq.rnf __field__strictann `Prelude.seq`
+        DeepSeq.rnf __field__lazyann `Prelude.seq`
+          DeepSeq.rnf __field__inherit `Prelude.seq` ()
+
+instance Default.Default HsStrictAnn where
+  def = HsStrictAnn Default.def Default.def Default.def
+
+instance Hashable.Hashable HsStrictAnn where
+  hashWithSalt __salt (HsStrictAnn _strictann _lazyann _inherit)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _strictann)
+           _lazyann)
+        _inherit
+
+data HsLazyAnn = HsLazyAnn{hsLazyAnn_strictann ::
+                           {-# UNPACK #-} !Int.Int32,
+                           hsLazyAnn_lazyann :: Int.Int32, hsLazyAnn_inherit :: Int.Int32}
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsLazyAnn where
+  toJSON
+    (HsLazyAnn __field__strictann __field__lazyann __field__inherit)
+    = Aeson.object
+        ("strictann" .= __field__strictann :
+           "lazyann" .= __field__lazyann :
+             "inherit" .= __field__inherit : Prelude.mempty)
+
+instance Thrift.ThriftStruct HsLazyAnn where
+  buildStruct _proxy
+    (HsLazyAnn __field__strictann __field__lazyann __field__inherit)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "strictann" (Thrift.getI32Type _proxy)
+           1
+           0
+           (Thrift.genI32Prim _proxy)
+           __field__strictann
+           :
+           Thrift.genFieldPrim _proxy "lazyann" (Thrift.getI32Type _proxy) 2 1
+             (Thrift.genI32Prim _proxy)
+             __field__lazyann
+             :
+             Thrift.genFieldPrim _proxy "inherit" (Thrift.getI32Type _proxy) 3 2
+               (Thrift.genI32Prim _proxy)
+               __field__inherit
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__strictann <- ST.newSTRef Default.def
+            __field__lazyann <- ST.newSTRef Default.def
+            __field__inherit <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__strictann
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__lazyann
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__inherit
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__strictann <- ST.readSTRef
+                                                                    __field__strictann
+                                             !__val__lazyann <- ST.readSTRef __field__lazyann
+                                             !__val__inherit <- ST.readSTRef __field__inherit
+                                             Prelude.pure
+                                               (HsLazyAnn __val__strictann __val__lazyann
+                                                  __val__inherit)
+              _idMap
+                = HashMap.fromList
+                    [("strictann", 1), ("lazyann", 2), ("inherit", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData HsLazyAnn where
+  rnf
+    (HsLazyAnn __field__strictann __field__lazyann __field__inherit)
+    = DeepSeq.rnf __field__strictann `Prelude.seq`
+        DeepSeq.rnf __field__lazyann `Prelude.seq`
+          DeepSeq.rnf __field__inherit `Prelude.seq` ()
+
+instance Default.Default HsLazyAnn where
+  def = HsLazyAnn Default.def Default.def Default.def
+
+instance Hashable.Hashable HsLazyAnn where
+  hashWithSalt __salt (HsLazyAnn _strictann _lazyann _inherit)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _strictann)
+           _lazyann)
+        _inherit
+
+data HsPrefixAnn = HsPrefixAnn{structprefixstrictann ::
+                               {-# UNPACK #-} !Int.Int32,
+                               structprefixlazyann :: Int.Int32, structprefixinherit :: Int.Int32}
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsPrefixAnn where
+  toJSON
+    (HsPrefixAnn __field__strictann __field__lazyann __field__inherit)
+    = Aeson.object
+        ("strictann" .= __field__strictann :
+           "lazyann" .= __field__lazyann :
+             "inherit" .= __field__inherit : Prelude.mempty)
+
+instance Thrift.ThriftStruct HsPrefixAnn where
+  buildStruct _proxy
+    (HsPrefixAnn __field__strictann __field__lazyann __field__inherit)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "strictann" (Thrift.getI32Type _proxy)
+           1
+           0
+           (Thrift.genI32Prim _proxy)
+           __field__strictann
+           :
+           Thrift.genFieldPrim _proxy "lazyann" (Thrift.getI32Type _proxy) 2 1
+             (Thrift.genI32Prim _proxy)
+             __field__lazyann
+             :
+             Thrift.genFieldPrim _proxy "inherit" (Thrift.getI32Type _proxy) 3 2
+               (Thrift.genI32Prim _proxy)
+               __field__inherit
+               : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__strictann <- ST.newSTRef Default.def
+            __field__lazyann <- ST.newSTRef Default.def
+            __field__inherit <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__strictann
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__lazyann
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__inherit
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__strictann <- ST.readSTRef
+                                                                    __field__strictann
+                                             !__val__lazyann <- ST.readSTRef __field__lazyann
+                                             !__val__inherit <- ST.readSTRef __field__inherit
+                                             Prelude.pure
+                                               (HsPrefixAnn __val__strictann __val__lazyann
+                                                  __val__inherit)
+              _idMap
+                = HashMap.fromList
+                    [("strictann", 1), ("lazyann", 2), ("inherit", 3)]
+            _parse 0)
+
+instance DeepSeq.NFData HsPrefixAnn where
+  rnf
+    (HsPrefixAnn __field__strictann __field__lazyann __field__inherit)
+    = DeepSeq.rnf __field__strictann `Prelude.seq`
+        DeepSeq.rnf __field__lazyann `Prelude.seq`
+          DeepSeq.rnf __field__inherit `Prelude.seq` ()
+
+instance Default.Default HsPrefixAnn where
+  def = HsPrefixAnn Default.def Default.def Default.def
+
+instance Hashable.Hashable HsPrefixAnn where
+  hashWithSalt __salt (HsPrefixAnn _strictann _lazyann _inherit)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _strictann)
+           _lazyann)
+        _inherit
+
+data HsUnion = HsUnion_left Int.Int32
+             | HsUnion_right Int.Int32
+             | HsUnion_EMPTY
+               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsUnion where
+  toJSON (HsUnion_left __left) = Aeson.object ["left" .= __left]
+  toJSON (HsUnion_right __right) = Aeson.object ["right" .= __right]
+  toJSON HsUnion_EMPTY = Aeson.object []
+
+instance Thrift.ThriftStruct HsUnion where
+  buildStruct _proxy (HsUnion_left __left)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "left" (Thrift.getI32Type _proxy) 1 0
+           (Thrift.genI32Prim _proxy)
+           __left]
+  buildStruct _proxy (HsUnion_right __right)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "right" (Thrift.getI32Type _proxy) 2 0
+           (Thrift.genI32Prim _proxy)
+           __right]
+  buildStruct _proxy HsUnion_EMPTY = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = do _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+         case _fieldBegin of
+           Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                     1 | _type == Thrift.getI32Type _proxy ->
+                                                         do _val <- Thrift.parseI32 _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (HsUnion_left _val)
+                                                     2 | _type == Thrift.getI32Type _proxy ->
+                                                         do _val <- Thrift.parseI32 _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (HsUnion_right _val)
+                                                     _ -> do Thrift.parseSkip _proxy _type
+                                                               Prelude.Nothing
+                                                             Thrift.parseStop _proxy
+                                                             Prelude.return HsUnion_EMPTY
+           Thrift.FieldEnd -> Prelude.return HsUnion_EMPTY
+    where
+      _idMap = HashMap.fromList [("left", 1), ("right", 2)]
+
+instance DeepSeq.NFData HsUnion where
+  rnf (HsUnion_left __left) = DeepSeq.rnf __left
+  rnf (HsUnion_right __right) = DeepSeq.rnf __right
+  rnf HsUnion_EMPTY = ()
+
+instance Default.Default HsUnion where
+  def = HsUnion_EMPTY
+
+instance Hashable.Hashable HsUnion where
+  hashWithSalt __salt (HsUnion_left _left)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 1 _left)
+  hashWithSalt __salt (HsUnion_right _right)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 2 _right)
+  hashWithSalt __salt HsUnion_EMPTY
+    = Hashable.hashWithSalt __salt (0 :: Prelude.Int)
+
+data HsUnionNonEmptyAnn = HsUnionNonEmptyAnn_left Int.Int32
+                        | HsUnionNonEmptyAnn_right Int.Int32
+                          deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsUnionNonEmptyAnn where
+  toJSON (HsUnionNonEmptyAnn_left __left)
+    = Aeson.object ["left" .= __left]
+  toJSON (HsUnionNonEmptyAnn_right __right)
+    = Aeson.object ["right" .= __right]
+
+instance Thrift.ThriftStruct HsUnionNonEmptyAnn where
+  buildStruct _proxy (HsUnionNonEmptyAnn_left __left)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "left" (Thrift.getI32Type _proxy) 1 0
+           (Thrift.genI32Prim _proxy)
+           __left]
+  buildStruct _proxy (HsUnionNonEmptyAnn_right __right)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "right" (Thrift.getI32Type _proxy) 2 0
+           (Thrift.genI32Prim _proxy)
+           __right]
+  parseStruct _proxy
+    = do _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+         case _fieldBegin of
+           Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                     1 | _type == Thrift.getI32Type _proxy ->
+                                                         do _val <- Thrift.parseI32 _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return
+                                                              (HsUnionNonEmptyAnn_left _val)
+                                                     2 | _type == Thrift.getI32Type _proxy ->
+                                                         do _val <- Thrift.parseI32 _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return
+                                                              (HsUnionNonEmptyAnn_right _val)
+                                                     _ -> Prelude.fail
+                                                            ("unrecognized alternative for union 'HsUnionNonEmptyAnn': "
+                                                               ++ Prelude.show _id)
+           Thrift.FieldEnd -> Prelude.fail
+                                "union 'HsUnionNonEmptyAnn' is empty"
+    where
+      _idMap = HashMap.fromList [("left", 1), ("right", 2)]
+
+instance DeepSeq.NFData HsUnionNonEmptyAnn where
+  rnf (HsUnionNonEmptyAnn_left __left) = DeepSeq.rnf __left
+  rnf (HsUnionNonEmptyAnn_right __right) = DeepSeq.rnf __right
+
+instance Default.Default HsUnionNonEmptyAnn where
+  def = HsUnionNonEmptyAnn_left Default.def
+
+instance Hashable.Hashable HsUnionNonEmptyAnn where
+  hashWithSalt __salt (HsUnionNonEmptyAnn_left _left)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 1 _left)
+  hashWithSalt __salt (HsUnionNonEmptyAnn_right _right)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 2 _right)
+
+data HsEnum = HsEnum_ONE
+            | HsEnum_TWO
+            | HsEnum_THREE
+            | HsEnum__UNKNOWN Prelude.Int
+              deriving (Prelude.Eq, Prelude.Show)
+
+instance Aeson.ToJSON HsEnum where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData HsEnum where
+  rnf __HsEnum = Prelude.seq __HsEnum ()
+
+instance Default.Default HsEnum where
+  def = HsEnum_ONE
+
+instance Hashable.Hashable HsEnum where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum HsEnum where
+  toThriftEnum 1 = HsEnum_ONE
+  toThriftEnum 2 = HsEnum_TWO
+  toThriftEnum 3 = HsEnum_THREE
+  toThriftEnum val = HsEnum__UNKNOWN val
+  fromThriftEnum HsEnum_ONE = 1
+  fromThriftEnum HsEnum_TWO = 2
+  fromThriftEnum HsEnum_THREE = 3
+  fromThriftEnum (HsEnum__UNKNOWN val) = val
+  allThriftEnumValues = [HsEnum_ONE, HsEnum_TWO, HsEnum_THREE]
+  toThriftEnumEither 1 = Prelude.Right HsEnum_ONE
+  toThriftEnumEither 2 = Prelude.Right HsEnum_TWO
+  toThriftEnumEither 3 = Prelude.Right HsEnum_THREE
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum HsEnum: " ++
+           Prelude.show val)
+
+instance Prelude.Ord HsEnum where
+  compare = Function.on Prelude.compare Thrift.fromThriftEnum
+
+data HsEnumEmpty = HsEnumEmpty__UNKNOWN Prelude.Int
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsEnumEmpty where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData HsEnumEmpty where
+  rnf __HsEnumEmpty = Prelude.seq __HsEnumEmpty ()
+
+instance Default.Default HsEnumEmpty where
+  def
+    = Exception.throw
+        (Thrift.ProtocolException
+           "def: enum HsEnumEmpty has no constructors")
+
+instance Hashable.Hashable HsEnumEmpty where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum HsEnumEmpty where
+  toThriftEnum val = HsEnumEmpty__UNKNOWN val
+  fromThriftEnum (HsEnumEmpty__UNKNOWN val) = val
+  allThriftEnumValues = []
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum HsEnumEmpty: "
+           ++ Prelude.show val)
+
+data HsEnumNoUnknownAnn = HsEnumNoUnknownAnn_ONE
+                        | HsEnumNoUnknownAnn_TWO
+                        | HsEnumNoUnknownAnn_THREE
+                          deriving (Prelude.Eq, Prelude.Show)
+
+instance Aeson.ToJSON HsEnumNoUnknownAnn where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData HsEnumNoUnknownAnn where
+  rnf __HsEnumNoUnknownAnn = Prelude.seq __HsEnumNoUnknownAnn ()
+
+instance Default.Default HsEnumNoUnknownAnn where
+  def = HsEnumNoUnknownAnn_ONE
+
+instance Hashable.Hashable HsEnumNoUnknownAnn where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum HsEnumNoUnknownAnn where
+  toThriftEnum 1 = HsEnumNoUnknownAnn_ONE
+  toThriftEnum 2 = HsEnumNoUnknownAnn_TWO
+  toThriftEnum 3 = HsEnumNoUnknownAnn_THREE
+  toThriftEnum _val
+    = Exception.throw
+        (Thrift.ProtocolException
+           ("toThriftEnum: not a valid identifier for enum HsEnumNoUnknownAnn: "
+              ++ Prelude.show _val))
+  fromThriftEnum HsEnumNoUnknownAnn_ONE = 1
+  fromThriftEnum HsEnumNoUnknownAnn_TWO = 2
+  fromThriftEnum HsEnumNoUnknownAnn_THREE = 3
+  fromThriftEnum _val
+    = Exception.throw
+        (Thrift.ProtocolException
+           ("fromThriftEnum: not a valid identifier for enum HsEnumNoUnknownAnn: "
+              ++ Prelude.show _val))
+  allThriftEnumValues
+    = [HsEnumNoUnknownAnn_ONE, HsEnumNoUnknownAnn_TWO,
+       HsEnumNoUnknownAnn_THREE]
+  toThriftEnumEither 1 = Prelude.Right HsEnumNoUnknownAnn_ONE
+  toThriftEnumEither 2 = Prelude.Right HsEnumNoUnknownAnn_TWO
+  toThriftEnumEither 3 = Prelude.Right HsEnumNoUnknownAnn_THREE
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum HsEnumNoUnknownAnn: "
+           ++ Prelude.show val)
+
+instance Prelude.Ord HsEnumNoUnknownAnn where
+  compare = Function.on Prelude.compare Thrift.fromThriftEnum
+
+data HsEnumEmptyNoUnknownAnn
+
+instance Prelude.Eq HsEnumEmptyNoUnknownAnn where
+  (==)
+    = Exception.throw
+        (Thrift.ProtocolException
+           "(==): Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Prelude.Show HsEnumEmptyNoUnknownAnn where
+  show
+    = Exception.throw
+        (Thrift.ProtocolException
+           "show: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Prelude.Ord HsEnumEmptyNoUnknownAnn where
+  compare
+    = Exception.throw
+        (Thrift.ProtocolException
+           "compare: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Aeson.ToJSON HsEnumEmptyNoUnknownAnn where
+  toJSON
+    = Exception.throw
+        (Thrift.ProtocolException
+           "toJSON: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Default.Default HsEnumEmptyNoUnknownAnn where
+  def
+    = Exception.throw
+        (Thrift.ProtocolException
+           "def: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Hashable.Hashable HsEnumEmptyNoUnknownAnn where
+  hashWithSalt
+    = Exception.throw
+        (Thrift.ProtocolException
+           "hashWithSalt: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance DeepSeq.NFData HsEnumEmptyNoUnknownAnn where
+  rnf
+    = Exception.throw
+        (Thrift.ProtocolException
+           "rnf: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+
+instance Thrift.ThriftEnum HsEnumEmptyNoUnknownAnn where
+  toThriftEnum
+    = Exception.throw
+        (Thrift.ProtocolException
+           "toThriftEnum: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+  fromThriftEnum
+    = Exception.throw
+        (Thrift.ProtocolException
+           "fromThriftEnum: Thrift enum 'HsEnumEmptyNoUnknownAnn' is uninhabited")
+  allThriftEnumValues = []
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum HsEnumEmptyNoUnknownAnn: "
+           ++ Prelude.show val)
+
+newtype HsEnumPseudoenumAnn = HsEnumPseudoenumAnn{unHsEnumPseudoenumAnn
+                                                  :: Int.Int32}
+                              deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable HsEnumPseudoenumAnn where
+  hashWithSalt __salt (HsEnumPseudoenumAnn __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HsEnumPseudoenumAnn where
+  toJSON (HsEnumPseudoenumAnn __val) = Aeson.toJSON __val
+
+hsEnumPseudoenumAnn_ONE :: HsEnumPseudoenumAnn
+hsEnumPseudoenumAnn_ONE = HsEnumPseudoenumAnn 1
+
+hsEnumPseudoenumAnn_TWO :: HsEnumPseudoenumAnn
+hsEnumPseudoenumAnn_TWO = HsEnumPseudoenumAnn 2
+
+hsEnumPseudoenumAnn_THREE :: HsEnumPseudoenumAnn
+hsEnumPseudoenumAnn_THREE = HsEnumPseudoenumAnn 3
+
+newtype HsEnumDuplicatedPseudoenumAnn = HsEnumDuplicatedPseudoenumAnn{unHsEnumDuplicatedPseudoenumAnn
+                                                                      :: Int.Int32}
+                                        deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData,
+                                                  Prelude.Ord)
+
+instance Hashable.Hashable HsEnumDuplicatedPseudoenumAnn where
+  hashWithSalt __salt (HsEnumDuplicatedPseudoenumAnn __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HsEnumDuplicatedPseudoenumAnn where
+  toJSON (HsEnumDuplicatedPseudoenumAnn __val) = Aeson.toJSON __val
+
+hsEnumDuplicatedPseudoenumAnn_ONE :: HsEnumDuplicatedPseudoenumAnn
+hsEnumDuplicatedPseudoenumAnn_ONE = HsEnumDuplicatedPseudoenumAnn 1
+
+hsEnumDuplicatedPseudoenumAnn_TWO :: HsEnumDuplicatedPseudoenumAnn
+hsEnumDuplicatedPseudoenumAnn_TWO = HsEnumDuplicatedPseudoenumAnn 2
+
+hsEnumDuplicatedPseudoenumAnn_THREE ::
+                                    HsEnumDuplicatedPseudoenumAnn
+hsEnumDuplicatedPseudoenumAnn_THREE
+  = HsEnumDuplicatedPseudoenumAnn 3
+
+newtype HsEnumEmptyPseudoenumAnn = HsEnumEmptyPseudoenumAnn{unHsEnumEmptyPseudoenumAnn
+                                                            :: Int.Int32}
+                                   deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable HsEnumEmptyPseudoenumAnn where
+  hashWithSalt __salt (HsEnumEmptyPseudoenumAnn __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HsEnumEmptyPseudoenumAnn where
+  toJSON (HsEnumEmptyPseudoenumAnn __val) = Aeson.toJSON __val
+
+newtype HsEnumPseudoenumThriftAnn = HsEnumPseudoenumThriftAnn{unHsEnumPseudoenumThriftAnn
+                                                              :: Int.Int32}
+                                    deriving (Prelude.Eq, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable HsEnumPseudoenumThriftAnn where
+  hashWithSalt __salt (HsEnumPseudoenumThriftAnn __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HsEnumPseudoenumThriftAnn where
+  toJSON (HsEnumPseudoenumThriftAnn __val) = Aeson.toJSON __val
+
+hsEnumPseudoenumThriftAnn_ONE :: HsEnumPseudoenumThriftAnn
+hsEnumPseudoenumThriftAnn_ONE = HsEnumPseudoenumThriftAnn 1
+
+hsEnumPseudoenumThriftAnn_TWO :: HsEnumPseudoenumThriftAnn
+hsEnumPseudoenumThriftAnn_TWO = HsEnumPseudoenumThriftAnn 2
+
+hsEnumPseudoenumThriftAnn_THREE :: HsEnumPseudoenumThriftAnn
+hsEnumPseudoenumThriftAnn_THREE = HsEnumPseudoenumThriftAnn 3
+
+instance Default.Default HsEnumPseudoenumThriftAnn where
+  def = hsEnumPseudoenumThriftAnn_ONE
+
+instance Prelude.Show HsEnumPseudoenumThriftAnn where
+  showsPrec __d (HsEnumPseudoenumThriftAnn __val)
+    = case HashMap.lookup __val __m of
+        Prelude.Just __s -> Prelude.showString __s
+        Prelude.Nothing -> Prelude.showParen (__d > 10)
+                             (Prelude.showString "HsEnumPseudoenumThriftAnn__UNKNOWN " .
+                                Prelude.showsPrec 11 __val)
+    where
+      __m
+        = HashMap.fromList
+            [(1, "HsEnumPseudoenumThriftAnn_ONE"),
+             (2, "HsEnumPseudoenumThriftAnn_TWO"),
+             (3, "HsEnumPseudoenumThriftAnn_THREE")]
+
+instance Thrift.ThriftEnum HsEnumPseudoenumThriftAnn where
+  toThriftEnum __val
+    = HsEnumPseudoenumThriftAnn (Prelude.fromIntegral __val)
+  fromThriftEnum (HsEnumPseudoenumThriftAnn __val)
+    = Prelude.fromIntegral __val
+  allThriftEnumValues
+    = [hsEnumPseudoenumThriftAnn_ONE, hsEnumPseudoenumThriftAnn_TWO,
+       hsEnumPseudoenumThriftAnn_THREE]
+  toThriftEnumEither val
+    = if Prelude.elem __val Thrift.allThriftEnumValues then
+        Prelude.Right __val else
+        Prelude.Left
+          ("toThriftEnumEither: not a valid identifier for enum HsEnumPseudoenumThriftAnn: "
+             ++ Prelude.show val)
+    where
+      __val = HsEnumPseudoenumThriftAnn (Prelude.fromIntegral val)
+
+newtype HsEnumEmptyPseudoenumThriftAnn = HsEnumEmptyPseudoenumThriftAnn{unHsEnumEmptyPseudoenumThriftAnn
+                                                                        :: Int.Int32}
+                                         deriving (Prelude.Eq, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable HsEnumEmptyPseudoenumThriftAnn where
+  hashWithSalt __salt (HsEnumEmptyPseudoenumThriftAnn __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HsEnumEmptyPseudoenumThriftAnn where
+  toJSON (HsEnumEmptyPseudoenumThriftAnn __val) = Aeson.toJSON __val
+
+instance Default.Default HsEnumEmptyPseudoenumThriftAnn where
+  def
+    = Exception.throw
+        (Thrift.ProtocolException
+           "def: enum HsEnumEmptyPseudoenumThriftAnn has no constructors")
+
+instance Prelude.Show HsEnumEmptyPseudoenumThriftAnn where
+  showsPrec __d (HsEnumEmptyPseudoenumThriftAnn __val)
+    = case HashMap.lookup __val __m of
+        Prelude.Just __s -> Prelude.showString __s
+        Prelude.Nothing -> Prelude.showParen (__d > 10)
+                             (Prelude.showString "HsEnumEmptyPseudoenumThriftAnn__UNKNOWN " .
+                                Prelude.showsPrec 11 __val)
+    where
+      __m = HashMap.fromList []
+
+instance Thrift.ThriftEnum HsEnumEmptyPseudoenumThriftAnn where
+  toThriftEnum __val
+    = HsEnumEmptyPseudoenumThriftAnn (Prelude.fromIntegral __val)
+  fromThriftEnum (HsEnumEmptyPseudoenumThriftAnn __val)
+    = Prelude.fromIntegral __val
+  allThriftEnumValues = []
+  toThriftEnumEither val
+    = if Prelude.elem __val Thrift.allThriftEnumValues then
+        Prelude.Right __val else
+        Prelude.Left
+          ("toThriftEnumEither: not a valid identifier for enum HsEnumEmptyPseudoenumThriftAnn: "
+             ++ Prelude.show val)
+    where
+      __val = HsEnumEmptyPseudoenumThriftAnn (Prelude.fromIntegral val)
+
+data HsStructOfComplexTypes = HsStructOfComplexTypes{hsStructOfComplexTypes_a_struct
+                                                     :: HsStruct,
+                                                     hsStructOfComplexTypes_a_union :: HsUnion,
+                                                     hsStructOfComplexTypes_an_enum :: HsEnum,
+                                                     hsStructOfComplexTypes_a_pseudoenum ::
+                                                     HsEnumPseudoenumAnn,
+                                                     hsStructOfComplexTypes_a_thrift_pseudoenum ::
+                                                     HsEnumPseudoenumThriftAnn}
+                              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON HsStructOfComplexTypes where
+  toJSON
+    (HsStructOfComplexTypes __field__a_struct __field__a_union
+       __field__an_enum __field__a_pseudoenum
+       __field__a_thrift_pseudoenum)
+    = Aeson.object
+        ("a_struct" .= __field__a_struct :
+           "a_union" .= __field__a_union :
+             "an_enum" .= __field__an_enum :
+               "a_pseudoenum" .= unHsEnumPseudoenumAnn __field__a_pseudoenum :
+                 "a_thrift_pseudoenum" .=
+                   unHsEnumPseudoenumThriftAnn __field__a_thrift_pseudoenum
+                   : Prelude.mempty)
+
+instance Thrift.ThriftStruct HsStructOfComplexTypes where
+  buildStruct _proxy
+    (HsStructOfComplexTypes __field__a_struct __field__a_union
+       __field__an_enum __field__a_pseudoenum
+       __field__a_thrift_pseudoenum)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "a_struct" (Thrift.getStructType _proxy) 1
+           0
+           (Thrift.buildStruct _proxy __field__a_struct)
+           :
+           Thrift.genField _proxy "a_union" (Thrift.getStructType _proxy) 2 1
+             (Thrift.buildStruct _proxy __field__a_union)
+             :
+             Thrift.genField _proxy "an_enum" (Thrift.getI32Type _proxy) 3 2
+               ((Thrift.genI32 _proxy . Prelude.fromIntegral .
+                   Thrift.fromThriftEnum)
+                  __field__an_enum)
+               :
+               Thrift.genField _proxy "a_pseudoenum" (Thrift.getI32Type _proxy) 4
+                 3
+                 ((Thrift.genI32 _proxy . unHsEnumPseudoenumAnn)
+                    __field__a_pseudoenum)
+                 :
+                 Thrift.genField _proxy "a_thrift_pseudoenum"
+                   (Thrift.getI32Type _proxy)
+                   5
+                   4
+                   ((Thrift.genI32 _proxy . unHsEnumPseudoenumThriftAnn)
+                      __field__a_thrift_pseudoenum)
+                   : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__a_struct <- ST.newSTRef Default.def
+            __field__a_union <- ST.newSTRef Default.def
+            __field__an_enum <- ST.newSTRef Default.def
+            __field__a_pseudoenum <- ST.newSTRef
+                                       (HsEnumPseudoenumAnn Default.def)
+            __field__a_thrift_pseudoenum <- ST.newSTRef
+                                              (HsEnumPseudoenumThriftAnn Default.def)
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStructType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseStruct
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__a_struct
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getStructType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseStruct
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__a_union
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseEnum
+                                                                                      _proxy
+                                                                                      "HsEnum")
+                                                                        ST.writeSTRef
+                                                                          __field__an_enum
+                                                                          _val
+                                                                 4 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.fmap
+                                                                                      HsEnumPseudoenumAnn
+                                                                                      (Thrift.parseI32
+                                                                                         _proxy))
+                                                                        ST.writeSTRef
+                                                                          __field__a_pseudoenum
+                                                                          _val
+                                                                 5 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.fmap
+                                                                                      HsEnumPseudoenumThriftAnn
+                                                                                      (Thrift.parseI32
+                                                                                         _proxy))
+                                                                        ST.writeSTRef
+                                                                          __field__a_thrift_pseudoenum
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__a_struct <- ST.readSTRef
+                                                                   __field__a_struct
+                                             !__val__a_union <- ST.readSTRef __field__a_union
+                                             !__val__an_enum <- ST.readSTRef __field__an_enum
+                                             !__val__a_pseudoenum <- ST.readSTRef
+                                                                       __field__a_pseudoenum
+                                             !__val__a_thrift_pseudoenum <- ST.readSTRef
+                                                                              __field__a_thrift_pseudoenum
+                                             Prelude.pure
+                                               (HsStructOfComplexTypes __val__a_struct
+                                                  __val__a_union
+                                                  __val__an_enum
+                                                  __val__a_pseudoenum
+                                                  __val__a_thrift_pseudoenum)
+              _idMap
+                = HashMap.fromList
+                    [("a_struct", 1), ("a_union", 2), ("an_enum", 3),
+                     ("a_pseudoenum", 4), ("a_thrift_pseudoenum", 5)]
+            _parse 0)
+
+instance DeepSeq.NFData HsStructOfComplexTypes where
+  rnf
+    (HsStructOfComplexTypes __field__a_struct __field__a_union
+       __field__an_enum __field__a_pseudoenum
+       __field__a_thrift_pseudoenum)
+    = DeepSeq.rnf __field__a_struct `Prelude.seq`
+        DeepSeq.rnf __field__a_union `Prelude.seq`
+          DeepSeq.rnf __field__an_enum `Prelude.seq`
+            DeepSeq.rnf __field__a_pseudoenum `Prelude.seq`
+              DeepSeq.rnf __field__a_thrift_pseudoenum `Prelude.seq` ()
+
+instance Default.Default HsStructOfComplexTypes where
+  def
+    = HsStructOfComplexTypes Default.def Default.def Default.def
+        (HsEnumPseudoenumAnn Default.def)
+        (HsEnumPseudoenumThriftAnn Default.def)
+
+instance Hashable.Hashable HsStructOfComplexTypes where
+  hashWithSalt __salt
+    (HsStructOfComplexTypes _a_struct _a_union _an_enum _a_pseudoenum
+       _a_thrift_pseudoenum)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt
+           (Hashable.hashWithSalt
+              (Hashable.hashWithSalt (Hashable.hashWithSalt __salt _a_struct)
+                 _a_union)
+              _an_enum)
+           _a_pseudoenum)
+        _a_thrift_pseudoenum
diff --git a/test/fixtures/gen-hs2/F/Types.hs b/test/fixtures/gen-hs2/F/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/F/Types.hs
@@ -0,0 +1,4240 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module F.Types
+       (HugeEnum(HugeEnum, unHugeEnum), hugeEnum_VALUE_0001,
+        hugeEnum_VALUE_0002, hugeEnum_VALUE_0003, hugeEnum_VALUE_0004,
+        hugeEnum_VALUE_0005, hugeEnum_VALUE_0006, hugeEnum_VALUE_0007,
+        hugeEnum_VALUE_0008, hugeEnum_VALUE_0009, hugeEnum_VALUE_0010,
+        hugeEnum_VALUE_0011, hugeEnum_VALUE_0012, hugeEnum_VALUE_0013,
+        hugeEnum_VALUE_0014, hugeEnum_VALUE_0015, hugeEnum_VALUE_0016,
+        hugeEnum_VALUE_0017, hugeEnum_VALUE_0018, hugeEnum_VALUE_0019,
+        hugeEnum_VALUE_0020, hugeEnum_VALUE_0021, hugeEnum_VALUE_0022,
+        hugeEnum_VALUE_0023, hugeEnum_VALUE_0024, hugeEnum_VALUE_0025,
+        hugeEnum_VALUE_0026, hugeEnum_VALUE_0027, hugeEnum_VALUE_0028,
+        hugeEnum_VALUE_0029, hugeEnum_VALUE_0030, hugeEnum_VALUE_0031,
+        hugeEnum_VALUE_0032, hugeEnum_VALUE_0033, hugeEnum_VALUE_0034,
+        hugeEnum_VALUE_0035, hugeEnum_VALUE_0036, hugeEnum_VALUE_0037,
+        hugeEnum_VALUE_0038, hugeEnum_VALUE_0039, hugeEnum_VALUE_0040,
+        hugeEnum_VALUE_0041, hugeEnum_VALUE_0042, hugeEnum_VALUE_0043,
+        hugeEnum_VALUE_0044, hugeEnum_VALUE_0045, hugeEnum_VALUE_0046,
+        hugeEnum_VALUE_0047, hugeEnum_VALUE_0048, hugeEnum_VALUE_0049,
+        hugeEnum_VALUE_0050, hugeEnum_VALUE_0051, hugeEnum_VALUE_0052,
+        hugeEnum_VALUE_0053, hugeEnum_VALUE_0054, hugeEnum_VALUE_0055,
+        hugeEnum_VALUE_0056, hugeEnum_VALUE_0057, hugeEnum_VALUE_0058,
+        hugeEnum_VALUE_0059, hugeEnum_VALUE_0060, hugeEnum_VALUE_0061,
+        hugeEnum_VALUE_0062, hugeEnum_VALUE_0063, hugeEnum_VALUE_0064,
+        hugeEnum_VALUE_0065, hugeEnum_VALUE_0066, hugeEnum_VALUE_0067,
+        hugeEnum_VALUE_0068, hugeEnum_VALUE_0069, hugeEnum_VALUE_0070,
+        hugeEnum_VALUE_0071, hugeEnum_VALUE_0072, hugeEnum_VALUE_0073,
+        hugeEnum_VALUE_0074, hugeEnum_VALUE_0075, hugeEnum_VALUE_0076,
+        hugeEnum_VALUE_0077, hugeEnum_VALUE_0078, hugeEnum_VALUE_0079,
+        hugeEnum_VALUE_0080, hugeEnum_VALUE_0081, hugeEnum_VALUE_0082,
+        hugeEnum_VALUE_0083, hugeEnum_VALUE_0084, hugeEnum_VALUE_0085,
+        hugeEnum_VALUE_0086, hugeEnum_VALUE_0087, hugeEnum_VALUE_0088,
+        hugeEnum_VALUE_0089, hugeEnum_VALUE_0090, hugeEnum_VALUE_0091,
+        hugeEnum_VALUE_0092, hugeEnum_VALUE_0093, hugeEnum_VALUE_0094,
+        hugeEnum_VALUE_0095, hugeEnum_VALUE_0096, hugeEnum_VALUE_0097,
+        hugeEnum_VALUE_0098, hugeEnum_VALUE_0099, hugeEnum_VALUE_0100,
+        hugeEnum_VALUE_0101, hugeEnum_VALUE_0102, hugeEnum_VALUE_0103,
+        hugeEnum_VALUE_0104, hugeEnum_VALUE_0105, hugeEnum_VALUE_0106,
+        hugeEnum_VALUE_0107, hugeEnum_VALUE_0108, hugeEnum_VALUE_0109,
+        hugeEnum_VALUE_0110, hugeEnum_VALUE_0111, hugeEnum_VALUE_0112,
+        hugeEnum_VALUE_0113, hugeEnum_VALUE_0114, hugeEnum_VALUE_0115,
+        hugeEnum_VALUE_0116, hugeEnum_VALUE_0117, hugeEnum_VALUE_0118,
+        hugeEnum_VALUE_0119, hugeEnum_VALUE_0120, hugeEnum_VALUE_0121,
+        hugeEnum_VALUE_0122, hugeEnum_VALUE_0123, hugeEnum_VALUE_0124,
+        hugeEnum_VALUE_0125, hugeEnum_VALUE_0126, hugeEnum_VALUE_0127,
+        hugeEnum_VALUE_0128, hugeEnum_VALUE_0129, hugeEnum_VALUE_0130,
+        hugeEnum_VALUE_0131, hugeEnum_VALUE_0132, hugeEnum_VALUE_0133,
+        hugeEnum_VALUE_0134, hugeEnum_VALUE_0135, hugeEnum_VALUE_0136,
+        hugeEnum_VALUE_0137, hugeEnum_VALUE_0138, hugeEnum_VALUE_0139,
+        hugeEnum_VALUE_0140, hugeEnum_VALUE_0141, hugeEnum_VALUE_0142,
+        hugeEnum_VALUE_0143, hugeEnum_VALUE_0144, hugeEnum_VALUE_0145,
+        hugeEnum_VALUE_0146, hugeEnum_VALUE_0147, hugeEnum_VALUE_0148,
+        hugeEnum_VALUE_0149, hugeEnum_VALUE_0150, hugeEnum_VALUE_0151,
+        hugeEnum_VALUE_0152, hugeEnum_VALUE_0153, hugeEnum_VALUE_0154,
+        hugeEnum_VALUE_0155, hugeEnum_VALUE_0156, hugeEnum_VALUE_0157,
+        hugeEnum_VALUE_0158, hugeEnum_VALUE_0159, hugeEnum_VALUE_0160,
+        hugeEnum_VALUE_0161, hugeEnum_VALUE_0162, hugeEnum_VALUE_0163,
+        hugeEnum_VALUE_0164, hugeEnum_VALUE_0165, hugeEnum_VALUE_0166,
+        hugeEnum_VALUE_0167, hugeEnum_VALUE_0168, hugeEnum_VALUE_0169,
+        hugeEnum_VALUE_0170, hugeEnum_VALUE_0171, hugeEnum_VALUE_0172,
+        hugeEnum_VALUE_0173, hugeEnum_VALUE_0174, hugeEnum_VALUE_0175,
+        hugeEnum_VALUE_0176, hugeEnum_VALUE_0177, hugeEnum_VALUE_0178,
+        hugeEnum_VALUE_0179, hugeEnum_VALUE_0180, hugeEnum_VALUE_0181,
+        hugeEnum_VALUE_0182, hugeEnum_VALUE_0183, hugeEnum_VALUE_0184,
+        hugeEnum_VALUE_0185, hugeEnum_VALUE_0186, hugeEnum_VALUE_0187,
+        hugeEnum_VALUE_0188, hugeEnum_VALUE_0189, hugeEnum_VALUE_0190,
+        hugeEnum_VALUE_0191, hugeEnum_VALUE_0192, hugeEnum_VALUE_0193,
+        hugeEnum_VALUE_0194, hugeEnum_VALUE_0195, hugeEnum_VALUE_0196,
+        hugeEnum_VALUE_0197, hugeEnum_VALUE_0198, hugeEnum_VALUE_0199,
+        hugeEnum_VALUE_0200, hugeEnum_VALUE_0201, hugeEnum_VALUE_0202,
+        hugeEnum_VALUE_0203, hugeEnum_VALUE_0204, hugeEnum_VALUE_0205,
+        hugeEnum_VALUE_0206, hugeEnum_VALUE_0207, hugeEnum_VALUE_0208,
+        hugeEnum_VALUE_0209, hugeEnum_VALUE_0210, hugeEnum_VALUE_0211,
+        hugeEnum_VALUE_0212, hugeEnum_VALUE_0213, hugeEnum_VALUE_0214,
+        hugeEnum_VALUE_0215, hugeEnum_VALUE_0216, hugeEnum_VALUE_0217,
+        hugeEnum_VALUE_0218, hugeEnum_VALUE_0219, hugeEnum_VALUE_0220,
+        hugeEnum_VALUE_0221, hugeEnum_VALUE_0222, hugeEnum_VALUE_0223,
+        hugeEnum_VALUE_0224, hugeEnum_VALUE_0225, hugeEnum_VALUE_0226,
+        hugeEnum_VALUE_0227, hugeEnum_VALUE_0228, hugeEnum_VALUE_0229,
+        hugeEnum_VALUE_0230, hugeEnum_VALUE_0231, hugeEnum_VALUE_0232,
+        hugeEnum_VALUE_0233, hugeEnum_VALUE_0234, hugeEnum_VALUE_0235,
+        hugeEnum_VALUE_0236, hugeEnum_VALUE_0237, hugeEnum_VALUE_0238,
+        hugeEnum_VALUE_0239, hugeEnum_VALUE_0240, hugeEnum_VALUE_0241,
+        hugeEnum_VALUE_0242, hugeEnum_VALUE_0243, hugeEnum_VALUE_0244,
+        hugeEnum_VALUE_0245, hugeEnum_VALUE_0246, hugeEnum_VALUE_0247,
+        hugeEnum_VALUE_0248, hugeEnum_VALUE_0249, hugeEnum_VALUE_0250,
+        hugeEnum_VALUE_0251, hugeEnum_VALUE_0252, hugeEnum_VALUE_0253,
+        hugeEnum_VALUE_0254, hugeEnum_VALUE_0255, hugeEnum_VALUE_0256,
+        hugeEnum_VALUE_0257, hugeEnum_VALUE_0258, hugeEnum_VALUE_0259,
+        hugeEnum_VALUE_0260, hugeEnum_VALUE_0261, hugeEnum_VALUE_0262,
+        hugeEnum_VALUE_0263, hugeEnum_VALUE_0264, hugeEnum_VALUE_0265,
+        hugeEnum_VALUE_0266, hugeEnum_VALUE_0267, hugeEnum_VALUE_0268,
+        hugeEnum_VALUE_0269, hugeEnum_VALUE_0270, hugeEnum_VALUE_0271,
+        hugeEnum_VALUE_0272, hugeEnum_VALUE_0273, hugeEnum_VALUE_0274,
+        hugeEnum_VALUE_0275, hugeEnum_VALUE_0276, hugeEnum_VALUE_0277,
+        hugeEnum_VALUE_0278, hugeEnum_VALUE_0279, hugeEnum_VALUE_0280,
+        hugeEnum_VALUE_0281, hugeEnum_VALUE_0282, hugeEnum_VALUE_0283,
+        hugeEnum_VALUE_0284, hugeEnum_VALUE_0285, hugeEnum_VALUE_0286,
+        hugeEnum_VALUE_0287, hugeEnum_VALUE_0288, hugeEnum_VALUE_0289,
+        hugeEnum_VALUE_0290, hugeEnum_VALUE_0291, hugeEnum_VALUE_0292,
+        hugeEnum_VALUE_0293, hugeEnum_VALUE_0294, hugeEnum_VALUE_0295,
+        hugeEnum_VALUE_0296, hugeEnum_VALUE_0297, hugeEnum_VALUE_0298,
+        hugeEnum_VALUE_0299, hugeEnum_VALUE_0300, hugeEnum_VALUE_0301,
+        hugeEnum_VALUE_0302, hugeEnum_VALUE_0303, hugeEnum_VALUE_0304,
+        hugeEnum_VALUE_0305, hugeEnum_VALUE_0306, hugeEnum_VALUE_0307,
+        hugeEnum_VALUE_0308, hugeEnum_VALUE_0309, hugeEnum_VALUE_0310,
+        hugeEnum_VALUE_0311, hugeEnum_VALUE_0312, hugeEnum_VALUE_0313,
+        hugeEnum_VALUE_0314, hugeEnum_VALUE_0315, hugeEnum_VALUE_0316,
+        hugeEnum_VALUE_0317, hugeEnum_VALUE_0318, hugeEnum_VALUE_0319,
+        hugeEnum_VALUE_0320, hugeEnum_VALUE_0321, hugeEnum_VALUE_0322,
+        hugeEnum_VALUE_0323, hugeEnum_VALUE_0324, hugeEnum_VALUE_0325,
+        hugeEnum_VALUE_0326, hugeEnum_VALUE_0327, hugeEnum_VALUE_0328,
+        hugeEnum_VALUE_0329, hugeEnum_VALUE_0330, hugeEnum_VALUE_0331,
+        hugeEnum_VALUE_0332, hugeEnum_VALUE_0333, hugeEnum_VALUE_0334,
+        hugeEnum_VALUE_0335, hugeEnum_VALUE_0336, hugeEnum_VALUE_0337,
+        hugeEnum_VALUE_0338, hugeEnum_VALUE_0339, hugeEnum_VALUE_0340,
+        hugeEnum_VALUE_0341, hugeEnum_VALUE_0342, hugeEnum_VALUE_0343,
+        hugeEnum_VALUE_0344, hugeEnum_VALUE_0345, hugeEnum_VALUE_0346,
+        hugeEnum_VALUE_0347, hugeEnum_VALUE_0348, hugeEnum_VALUE_0349,
+        hugeEnum_VALUE_0350, hugeEnum_VALUE_0351, hugeEnum_VALUE_0352,
+        hugeEnum_VALUE_0353, hugeEnum_VALUE_0354, hugeEnum_VALUE_0355,
+        hugeEnum_VALUE_0356, hugeEnum_VALUE_0357, hugeEnum_VALUE_0358,
+        hugeEnum_VALUE_0359, hugeEnum_VALUE_0360, hugeEnum_VALUE_0361,
+        hugeEnum_VALUE_0362, hugeEnum_VALUE_0363, hugeEnum_VALUE_0364,
+        hugeEnum_VALUE_0365, hugeEnum_VALUE_0366, hugeEnum_VALUE_0367,
+        hugeEnum_VALUE_0368, hugeEnum_VALUE_0369, hugeEnum_VALUE_0370,
+        hugeEnum_VALUE_0371, hugeEnum_VALUE_0372, hugeEnum_VALUE_0373,
+        hugeEnum_VALUE_0374, hugeEnum_VALUE_0375, hugeEnum_VALUE_0376,
+        hugeEnum_VALUE_0377, hugeEnum_VALUE_0378, hugeEnum_VALUE_0379,
+        hugeEnum_VALUE_0380, hugeEnum_VALUE_0381, hugeEnum_VALUE_0382,
+        hugeEnum_VALUE_0383, hugeEnum_VALUE_0384, hugeEnum_VALUE_0385,
+        hugeEnum_VALUE_0386, hugeEnum_VALUE_0387, hugeEnum_VALUE_0388,
+        hugeEnum_VALUE_0389, hugeEnum_VALUE_0390, hugeEnum_VALUE_0391,
+        hugeEnum_VALUE_0392, hugeEnum_VALUE_0393, hugeEnum_VALUE_0394,
+        hugeEnum_VALUE_0395, hugeEnum_VALUE_0396, hugeEnum_VALUE_0397,
+        hugeEnum_VALUE_0398, hugeEnum_VALUE_0399, hugeEnum_VALUE_0400,
+        hugeEnum_VALUE_0401, hugeEnum_VALUE_0402, hugeEnum_VALUE_0403,
+        hugeEnum_VALUE_0404, hugeEnum_VALUE_0405, hugeEnum_VALUE_0406,
+        hugeEnum_VALUE_0407, hugeEnum_VALUE_0408, hugeEnum_VALUE_0409,
+        hugeEnum_VALUE_0410, hugeEnum_VALUE_0411, hugeEnum_VALUE_0412,
+        hugeEnum_VALUE_0413, hugeEnum_VALUE_0414, hugeEnum_VALUE_0415,
+        hugeEnum_VALUE_0416, hugeEnum_VALUE_0417, hugeEnum_VALUE_0418,
+        hugeEnum_VALUE_0419, hugeEnum_VALUE_0420, hugeEnum_VALUE_0421,
+        hugeEnum_VALUE_0422, hugeEnum_VALUE_0423, hugeEnum_VALUE_0424,
+        hugeEnum_VALUE_0425, hugeEnum_VALUE_0426, hugeEnum_VALUE_0427,
+        hugeEnum_VALUE_0428, hugeEnum_VALUE_0429, hugeEnum_VALUE_0430,
+        hugeEnum_VALUE_0431, hugeEnum_VALUE_0432, hugeEnum_VALUE_0433,
+        hugeEnum_VALUE_0434, hugeEnum_VALUE_0435, hugeEnum_VALUE_0436,
+        hugeEnum_VALUE_0437, hugeEnum_VALUE_0438, hugeEnum_VALUE_0439,
+        hugeEnum_VALUE_0440, hugeEnum_VALUE_0441, hugeEnum_VALUE_0442,
+        hugeEnum_VALUE_0443, hugeEnum_VALUE_0444, hugeEnum_VALUE_0445,
+        hugeEnum_VALUE_0446, hugeEnum_VALUE_0447, hugeEnum_VALUE_0448,
+        hugeEnum_VALUE_0449, hugeEnum_VALUE_0450, hugeEnum_VALUE_0451,
+        hugeEnum_VALUE_0452, hugeEnum_VALUE_0453, hugeEnum_VALUE_0454,
+        hugeEnum_VALUE_0455, hugeEnum_VALUE_0456, hugeEnum_VALUE_0457,
+        hugeEnum_VALUE_0458, hugeEnum_VALUE_0459, hugeEnum_VALUE_0460,
+        hugeEnum_VALUE_0461, hugeEnum_VALUE_0462, hugeEnum_VALUE_0463,
+        hugeEnum_VALUE_0464, hugeEnum_VALUE_0465, hugeEnum_VALUE_0466,
+        hugeEnum_VALUE_0467, hugeEnum_VALUE_0468, hugeEnum_VALUE_0469,
+        hugeEnum_VALUE_0470, hugeEnum_VALUE_0471, hugeEnum_VALUE_0472,
+        hugeEnum_VALUE_0473, hugeEnum_VALUE_0474, hugeEnum_VALUE_0475,
+        hugeEnum_VALUE_0476, hugeEnum_VALUE_0477, hugeEnum_VALUE_0478,
+        hugeEnum_VALUE_0479, hugeEnum_VALUE_0480, hugeEnum_VALUE_0481,
+        hugeEnum_VALUE_0482, hugeEnum_VALUE_0483, hugeEnum_VALUE_0484,
+        hugeEnum_VALUE_0485, hugeEnum_VALUE_0486, hugeEnum_VALUE_0487,
+        hugeEnum_VALUE_0488, hugeEnum_VALUE_0489, hugeEnum_VALUE_0490,
+        hugeEnum_VALUE_0491, hugeEnum_VALUE_0492, hugeEnum_VALUE_0493,
+        hugeEnum_VALUE_0494, hugeEnum_VALUE_0495, hugeEnum_VALUE_0496,
+        hugeEnum_VALUE_0497, hugeEnum_VALUE_0498, hugeEnum_VALUE_0499,
+        hugeEnum_VALUE_0500, hugeEnum_VALUE_0501, hugeEnum_VALUE_0502,
+        hugeEnum_VALUE_0503, hugeEnum_VALUE_0504, hugeEnum_VALUE_0505,
+        hugeEnum_VALUE_0506, hugeEnum_VALUE_0507, hugeEnum_VALUE_0508,
+        hugeEnum_VALUE_0509, hugeEnum_VALUE_0510, hugeEnum_VALUE_0511,
+        hugeEnum_VALUE_0512, hugeEnum_VALUE_0513, hugeEnum_VALUE_0514,
+        hugeEnum_VALUE_0515, hugeEnum_VALUE_0516, hugeEnum_VALUE_0517,
+        hugeEnum_VALUE_0518, hugeEnum_VALUE_0519, hugeEnum_VALUE_0520,
+        hugeEnum_VALUE_0521, hugeEnum_VALUE_0522, hugeEnum_VALUE_0523,
+        hugeEnum_VALUE_0524, hugeEnum_VALUE_0525, hugeEnum_VALUE_0526,
+        hugeEnum_VALUE_0527, hugeEnum_VALUE_0528, hugeEnum_VALUE_0529,
+        hugeEnum_VALUE_0530, hugeEnum_VALUE_0531, hugeEnum_VALUE_0532,
+        hugeEnum_VALUE_0533, hugeEnum_VALUE_0534, hugeEnum_VALUE_0535,
+        hugeEnum_VALUE_0536, hugeEnum_VALUE_0537, hugeEnum_VALUE_0538,
+        hugeEnum_VALUE_0539, hugeEnum_VALUE_0540, hugeEnum_VALUE_0541,
+        hugeEnum_VALUE_0542, hugeEnum_VALUE_0543, hugeEnum_VALUE_0544,
+        hugeEnum_VALUE_0545, hugeEnum_VALUE_0546, hugeEnum_VALUE_0547,
+        hugeEnum_VALUE_0548, hugeEnum_VALUE_0549, hugeEnum_VALUE_0550,
+        hugeEnum_VALUE_0551, hugeEnum_VALUE_0552, hugeEnum_VALUE_0553,
+        hugeEnum_VALUE_0554, hugeEnum_VALUE_0555, hugeEnum_VALUE_0556,
+        hugeEnum_VALUE_0557, hugeEnum_VALUE_0558, hugeEnum_VALUE_0559,
+        hugeEnum_VALUE_0560, hugeEnum_VALUE_0561, hugeEnum_VALUE_0562,
+        hugeEnum_VALUE_0563, hugeEnum_VALUE_0564, hugeEnum_VALUE_0565,
+        hugeEnum_VALUE_0566, hugeEnum_VALUE_0567, hugeEnum_VALUE_0568,
+        hugeEnum_VALUE_0569, hugeEnum_VALUE_0570, hugeEnum_VALUE_0571,
+        hugeEnum_VALUE_0572, hugeEnum_VALUE_0573, hugeEnum_VALUE_0574,
+        hugeEnum_VALUE_0575, hugeEnum_VALUE_0576, hugeEnum_VALUE_0577,
+        hugeEnum_VALUE_0578, hugeEnum_VALUE_0579, hugeEnum_VALUE_0580,
+        hugeEnum_VALUE_0581, hugeEnum_VALUE_0582, hugeEnum_VALUE_0583,
+        hugeEnum_VALUE_0584, hugeEnum_VALUE_0585, hugeEnum_VALUE_0586,
+        hugeEnum_VALUE_0587, hugeEnum_VALUE_0588, hugeEnum_VALUE_0589,
+        hugeEnum_VALUE_0590, hugeEnum_VALUE_0591, hugeEnum_VALUE_0592,
+        hugeEnum_VALUE_0593, hugeEnum_VALUE_0594, hugeEnum_VALUE_0595,
+        hugeEnum_VALUE_0596, hugeEnum_VALUE_0597, hugeEnum_VALUE_0598,
+        hugeEnum_VALUE_0599, hugeEnum_VALUE_0600, hugeEnum_VALUE_0601,
+        hugeEnum_VALUE_0602, hugeEnum_VALUE_0603, hugeEnum_VALUE_0604,
+        hugeEnum_VALUE_0605, hugeEnum_VALUE_0606, hugeEnum_VALUE_0607,
+        hugeEnum_VALUE_0608, hugeEnum_VALUE_0609, hugeEnum_VALUE_0610,
+        hugeEnum_VALUE_0611, hugeEnum_VALUE_0612, hugeEnum_VALUE_0613,
+        hugeEnum_VALUE_0614, hugeEnum_VALUE_0615, hugeEnum_VALUE_0616,
+        hugeEnum_VALUE_0617, hugeEnum_VALUE_0618, hugeEnum_VALUE_0619,
+        hugeEnum_VALUE_0620, hugeEnum_VALUE_0621, hugeEnum_VALUE_0622,
+        hugeEnum_VALUE_0623, hugeEnum_VALUE_0624, hugeEnum_VALUE_0625,
+        hugeEnum_VALUE_0626, hugeEnum_VALUE_0627, hugeEnum_VALUE_0628,
+        hugeEnum_VALUE_0629, hugeEnum_VALUE_0630, hugeEnum_VALUE_0631,
+        hugeEnum_VALUE_0632, hugeEnum_VALUE_0633, hugeEnum_VALUE_0634,
+        hugeEnum_VALUE_0635, hugeEnum_VALUE_0636, hugeEnum_VALUE_0637,
+        hugeEnum_VALUE_0638, hugeEnum_VALUE_0639, hugeEnum_VALUE_0640,
+        hugeEnum_VALUE_0641, hugeEnum_VALUE_0642, hugeEnum_VALUE_0643,
+        hugeEnum_VALUE_0644, hugeEnum_VALUE_0645, hugeEnum_VALUE_0646,
+        hugeEnum_VALUE_0647, hugeEnum_VALUE_0648, hugeEnum_VALUE_0649,
+        hugeEnum_VALUE_0650, hugeEnum_VALUE_0651, hugeEnum_VALUE_0652,
+        hugeEnum_VALUE_0653, hugeEnum_VALUE_0654, hugeEnum_VALUE_0655,
+        hugeEnum_VALUE_0656, hugeEnum_VALUE_0657, hugeEnum_VALUE_0658,
+        hugeEnum_VALUE_0659, hugeEnum_VALUE_0660, hugeEnum_VALUE_0661,
+        hugeEnum_VALUE_0662, hugeEnum_VALUE_0663, hugeEnum_VALUE_0664,
+        hugeEnum_VALUE_0665, hugeEnum_VALUE_0666, hugeEnum_VALUE_0667,
+        hugeEnum_VALUE_0668, hugeEnum_VALUE_0669, hugeEnum_VALUE_0670,
+        hugeEnum_VALUE_0671, hugeEnum_VALUE_0672, hugeEnum_VALUE_0673,
+        hugeEnum_VALUE_0674, hugeEnum_VALUE_0675, hugeEnum_VALUE_0676,
+        hugeEnum_VALUE_0677, hugeEnum_VALUE_0678, hugeEnum_VALUE_0679,
+        hugeEnum_VALUE_0680, hugeEnum_VALUE_0681, hugeEnum_VALUE_0682,
+        hugeEnum_VALUE_0683, hugeEnum_VALUE_0684, hugeEnum_VALUE_0685,
+        hugeEnum_VALUE_0686, hugeEnum_VALUE_0687, hugeEnum_VALUE_0688,
+        hugeEnum_VALUE_0689, hugeEnum_VALUE_0690, hugeEnum_VALUE_0691,
+        hugeEnum_VALUE_0692, hugeEnum_VALUE_0693, hugeEnum_VALUE_0694,
+        hugeEnum_VALUE_0695, hugeEnum_VALUE_0696, hugeEnum_VALUE_0697,
+        hugeEnum_VALUE_0698, hugeEnum_VALUE_0699, hugeEnum_VALUE_0700,
+        hugeEnum_VALUE_0701, hugeEnum_VALUE_0702, hugeEnum_VALUE_0703,
+        hugeEnum_VALUE_0704, hugeEnum_VALUE_0705, hugeEnum_VALUE_0706,
+        hugeEnum_VALUE_0707, hugeEnum_VALUE_0708, hugeEnum_VALUE_0709,
+        hugeEnum_VALUE_0710, hugeEnum_VALUE_0711, hugeEnum_VALUE_0712,
+        hugeEnum_VALUE_0713, hugeEnum_VALUE_0714, hugeEnum_VALUE_0715,
+        hugeEnum_VALUE_0716, hugeEnum_VALUE_0717, hugeEnum_VALUE_0718,
+        hugeEnum_VALUE_0719, hugeEnum_VALUE_0720, hugeEnum_VALUE_0721,
+        hugeEnum_VALUE_0722, hugeEnum_VALUE_0723, hugeEnum_VALUE_0724,
+        hugeEnum_VALUE_0725, hugeEnum_VALUE_0726, hugeEnum_VALUE_0727,
+        hugeEnum_VALUE_0728, hugeEnum_VALUE_0729, hugeEnum_VALUE_0730,
+        hugeEnum_VALUE_0731, hugeEnum_VALUE_0732, hugeEnum_VALUE_0733,
+        hugeEnum_VALUE_0734, hugeEnum_VALUE_0735, hugeEnum_VALUE_0736,
+        hugeEnum_VALUE_0737, hugeEnum_VALUE_0738, hugeEnum_VALUE_0739,
+        hugeEnum_VALUE_0740, hugeEnum_VALUE_0741, hugeEnum_VALUE_0742,
+        hugeEnum_VALUE_0743, hugeEnum_VALUE_0744, hugeEnum_VALUE_0745,
+        hugeEnum_VALUE_0746, hugeEnum_VALUE_0747, hugeEnum_VALUE_0748,
+        hugeEnum_VALUE_0749, hugeEnum_VALUE_0750, hugeEnum_VALUE_0751,
+        hugeEnum_VALUE_0752, hugeEnum_VALUE_0753, hugeEnum_VALUE_0754,
+        hugeEnum_VALUE_0755, hugeEnum_VALUE_0756, hugeEnum_VALUE_0757,
+        hugeEnum_VALUE_0758, hugeEnum_VALUE_0759, hugeEnum_VALUE_0760,
+        hugeEnum_VALUE_0761, hugeEnum_VALUE_0762, hugeEnum_VALUE_0763,
+        hugeEnum_VALUE_0764, hugeEnum_VALUE_0765, hugeEnum_VALUE_0766,
+        hugeEnum_VALUE_0767, hugeEnum_VALUE_0768, hugeEnum_VALUE_0769,
+        hugeEnum_VALUE_0770, hugeEnum_VALUE_0771, hugeEnum_VALUE_0772,
+        hugeEnum_VALUE_0773, hugeEnum_VALUE_0774, hugeEnum_VALUE_0775,
+        hugeEnum_VALUE_0776, hugeEnum_VALUE_0777, hugeEnum_VALUE_0778,
+        hugeEnum_VALUE_0779, hugeEnum_VALUE_0780, hugeEnum_VALUE_0781,
+        hugeEnum_VALUE_0782, hugeEnum_VALUE_0783, hugeEnum_VALUE_0784,
+        hugeEnum_VALUE_0785, hugeEnum_VALUE_0786, hugeEnum_VALUE_0787,
+        hugeEnum_VALUE_0788, hugeEnum_VALUE_0789, hugeEnum_VALUE_0790,
+        hugeEnum_VALUE_0791, hugeEnum_VALUE_0792, hugeEnum_VALUE_0793,
+        hugeEnum_VALUE_0794, hugeEnum_VALUE_0795, hugeEnum_VALUE_0796,
+        hugeEnum_VALUE_0797, hugeEnum_VALUE_0798, hugeEnum_VALUE_0799,
+        hugeEnum_VALUE_0800, hugeEnum_VALUE_0801, hugeEnum_VALUE_0802,
+        hugeEnum_VALUE_0803, hugeEnum_VALUE_0804, hugeEnum_VALUE_0805,
+        hugeEnum_VALUE_0806, hugeEnum_VALUE_0807, hugeEnum_VALUE_0808,
+        hugeEnum_VALUE_0809, hugeEnum_VALUE_0810, hugeEnum_VALUE_0811,
+        hugeEnum_VALUE_0812, hugeEnum_VALUE_0813, hugeEnum_VALUE_0814,
+        hugeEnum_VALUE_0815, hugeEnum_VALUE_0816, hugeEnum_VALUE_0817,
+        hugeEnum_VALUE_0818, hugeEnum_VALUE_0819, hugeEnum_VALUE_0820,
+        hugeEnum_VALUE_0821, hugeEnum_VALUE_0822, hugeEnum_VALUE_0823,
+        hugeEnum_VALUE_0824, hugeEnum_VALUE_0825, hugeEnum_VALUE_0826,
+        hugeEnum_VALUE_0827, hugeEnum_VALUE_0828, hugeEnum_VALUE_0829,
+        hugeEnum_VALUE_0830, hugeEnum_VALUE_0831, hugeEnum_VALUE_0832,
+        hugeEnum_VALUE_0833, hugeEnum_VALUE_0834, hugeEnum_VALUE_0835,
+        hugeEnum_VALUE_0836, hugeEnum_VALUE_0837, hugeEnum_VALUE_0838,
+        hugeEnum_VALUE_0839, hugeEnum_VALUE_0840, hugeEnum_VALUE_0841,
+        hugeEnum_VALUE_0842, hugeEnum_VALUE_0843, hugeEnum_VALUE_0844,
+        hugeEnum_VALUE_0845, hugeEnum_VALUE_0846, hugeEnum_VALUE_0847,
+        hugeEnum_VALUE_0848, hugeEnum_VALUE_0849, hugeEnum_VALUE_0850,
+        hugeEnum_VALUE_0851, hugeEnum_VALUE_0852, hugeEnum_VALUE_0853,
+        hugeEnum_VALUE_0854, hugeEnum_VALUE_0855, hugeEnum_VALUE_0856,
+        hugeEnum_VALUE_0857, hugeEnum_VALUE_0858, hugeEnum_VALUE_0859,
+        hugeEnum_VALUE_0860, hugeEnum_VALUE_0861, hugeEnum_VALUE_0862,
+        hugeEnum_VALUE_0863, hugeEnum_VALUE_0864, hugeEnum_VALUE_0865,
+        hugeEnum_VALUE_0866, hugeEnum_VALUE_0867, hugeEnum_VALUE_0868,
+        hugeEnum_VALUE_0869, hugeEnum_VALUE_0870, hugeEnum_VALUE_0871,
+        hugeEnum_VALUE_0872, hugeEnum_VALUE_0873, hugeEnum_VALUE_0874,
+        hugeEnum_VALUE_0875, hugeEnum_VALUE_0876, hugeEnum_VALUE_0877,
+        hugeEnum_VALUE_0878, hugeEnum_VALUE_0879, hugeEnum_VALUE_0880,
+        hugeEnum_VALUE_0881, hugeEnum_VALUE_0882, hugeEnum_VALUE_0883,
+        hugeEnum_VALUE_0884, hugeEnum_VALUE_0885, hugeEnum_VALUE_0886,
+        hugeEnum_VALUE_0887, hugeEnum_VALUE_0888, hugeEnum_VALUE_0889,
+        hugeEnum_VALUE_0890, hugeEnum_VALUE_0891, hugeEnum_VALUE_0892,
+        hugeEnum_VALUE_0893, hugeEnum_VALUE_0894, hugeEnum_VALUE_0895,
+        hugeEnum_VALUE_0896, hugeEnum_VALUE_0897, hugeEnum_VALUE_0898,
+        hugeEnum_VALUE_0899, hugeEnum_VALUE_0900, hugeEnum_VALUE_0901,
+        hugeEnum_VALUE_0902, hugeEnum_VALUE_0903, hugeEnum_VALUE_0904,
+        hugeEnum_VALUE_0905, hugeEnum_VALUE_0906, hugeEnum_VALUE_0907,
+        hugeEnum_VALUE_0908, hugeEnum_VALUE_0909, hugeEnum_VALUE_0910,
+        hugeEnum_VALUE_0911, hugeEnum_VALUE_0912, hugeEnum_VALUE_0913,
+        hugeEnum_VALUE_0914, hugeEnum_VALUE_0915, hugeEnum_VALUE_0916,
+        hugeEnum_VALUE_0917, hugeEnum_VALUE_0918, hugeEnum_VALUE_0919,
+        hugeEnum_VALUE_0920, hugeEnum_VALUE_0921, hugeEnum_VALUE_0922,
+        hugeEnum_VALUE_0923, hugeEnum_VALUE_0924, hugeEnum_VALUE_0925,
+        hugeEnum_VALUE_0926, hugeEnum_VALUE_0927, hugeEnum_VALUE_0928,
+        hugeEnum_VALUE_0929, hugeEnum_VALUE_0930, hugeEnum_VALUE_0931,
+        hugeEnum_VALUE_0932, hugeEnum_VALUE_0933, hugeEnum_VALUE_0934,
+        hugeEnum_VALUE_0935, hugeEnum_VALUE_0936, hugeEnum_VALUE_0937,
+        hugeEnum_VALUE_0938, hugeEnum_VALUE_0939, hugeEnum_VALUE_0940,
+        hugeEnum_VALUE_0941, hugeEnum_VALUE_0942, hugeEnum_VALUE_0943,
+        hugeEnum_VALUE_0944, hugeEnum_VALUE_0945, hugeEnum_VALUE_0946,
+        hugeEnum_VALUE_0947, hugeEnum_VALUE_0948, hugeEnum_VALUE_0949,
+        hugeEnum_VALUE_0950, hugeEnum_VALUE_0951, hugeEnum_VALUE_0952,
+        hugeEnum_VALUE_0953, hugeEnum_VALUE_0954, hugeEnum_VALUE_0955,
+        hugeEnum_VALUE_0956, hugeEnum_VALUE_0957, hugeEnum_VALUE_0958,
+        hugeEnum_VALUE_0959, hugeEnum_VALUE_0960, hugeEnum_VALUE_0961,
+        hugeEnum_VALUE_0962, hugeEnum_VALUE_0963, hugeEnum_VALUE_0964,
+        hugeEnum_VALUE_0965, hugeEnum_VALUE_0966, hugeEnum_VALUE_0967,
+        hugeEnum_VALUE_0968, hugeEnum_VALUE_0969, hugeEnum_VALUE_0970,
+        hugeEnum_VALUE_0971, hugeEnum_VALUE_0972, hugeEnum_VALUE_0973,
+        hugeEnum_VALUE_0974, hugeEnum_VALUE_0975, hugeEnum_VALUE_0976,
+        hugeEnum_VALUE_0977, hugeEnum_VALUE_0978, hugeEnum_VALUE_0979,
+        hugeEnum_VALUE_0980, hugeEnum_VALUE_0981, hugeEnum_VALUE_0982,
+        hugeEnum_VALUE_0983, hugeEnum_VALUE_0984, hugeEnum_VALUE_0985,
+        hugeEnum_VALUE_0986, hugeEnum_VALUE_0987, hugeEnum_VALUE_0988,
+        hugeEnum_VALUE_0989, hugeEnum_VALUE_0990, hugeEnum_VALUE_0991,
+        hugeEnum_VALUE_0992, hugeEnum_VALUE_0993, hugeEnum_VALUE_0994,
+        hugeEnum_VALUE_0995, hugeEnum_VALUE_0996, hugeEnum_VALUE_0997,
+        hugeEnum_VALUE_0998, hugeEnum_VALUE_0999, hugeEnum_VALUE_1000,
+        hugeEnum_VALUE_1001)
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Data.Aeson as Aeson
+import qualified Data.Default as Default
+import qualified Data.Function as Function
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified GHC.Magic as GHC
+import qualified Prelude as Prelude
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Prelude ((.), (++), (>), (==))
+
+newtype HugeEnum = HugeEnum{unHugeEnum :: Int.Int32}
+                   deriving (Prelude.Eq, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable HugeEnum where
+  hashWithSalt __salt (HugeEnum __val)
+    = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON HugeEnum where
+  toJSON (HugeEnum __val) = Aeson.toJSON __val
+
+hugeEnum_VALUE_0001 :: HugeEnum
+hugeEnum_VALUE_0001 = HugeEnum 1
+
+hugeEnum_VALUE_0002 :: HugeEnum
+hugeEnum_VALUE_0002 = HugeEnum 2
+
+hugeEnum_VALUE_0003 :: HugeEnum
+hugeEnum_VALUE_0003 = HugeEnum 3
+
+hugeEnum_VALUE_0004 :: HugeEnum
+hugeEnum_VALUE_0004 = HugeEnum 4
+
+hugeEnum_VALUE_0005 :: HugeEnum
+hugeEnum_VALUE_0005 = HugeEnum 5
+
+hugeEnum_VALUE_0006 :: HugeEnum
+hugeEnum_VALUE_0006 = HugeEnum 6
+
+hugeEnum_VALUE_0007 :: HugeEnum
+hugeEnum_VALUE_0007 = HugeEnum 7
+
+hugeEnum_VALUE_0008 :: HugeEnum
+hugeEnum_VALUE_0008 = HugeEnum 8
+
+hugeEnum_VALUE_0009 :: HugeEnum
+hugeEnum_VALUE_0009 = HugeEnum 9
+
+hugeEnum_VALUE_0010 :: HugeEnum
+hugeEnum_VALUE_0010 = HugeEnum 10
+
+hugeEnum_VALUE_0011 :: HugeEnum
+hugeEnum_VALUE_0011 = HugeEnum 11
+
+hugeEnum_VALUE_0012 :: HugeEnum
+hugeEnum_VALUE_0012 = HugeEnum 12
+
+hugeEnum_VALUE_0013 :: HugeEnum
+hugeEnum_VALUE_0013 = HugeEnum 13
+
+hugeEnum_VALUE_0014 :: HugeEnum
+hugeEnum_VALUE_0014 = HugeEnum 14
+
+hugeEnum_VALUE_0015 :: HugeEnum
+hugeEnum_VALUE_0015 = HugeEnum 15
+
+hugeEnum_VALUE_0016 :: HugeEnum
+hugeEnum_VALUE_0016 = HugeEnum 16
+
+hugeEnum_VALUE_0017 :: HugeEnum
+hugeEnum_VALUE_0017 = HugeEnum 17
+
+hugeEnum_VALUE_0018 :: HugeEnum
+hugeEnum_VALUE_0018 = HugeEnum 18
+
+hugeEnum_VALUE_0019 :: HugeEnum
+hugeEnum_VALUE_0019 = HugeEnum 19
+
+hugeEnum_VALUE_0020 :: HugeEnum
+hugeEnum_VALUE_0020 = HugeEnum 20
+
+hugeEnum_VALUE_0021 :: HugeEnum
+hugeEnum_VALUE_0021 = HugeEnum 21
+
+hugeEnum_VALUE_0022 :: HugeEnum
+hugeEnum_VALUE_0022 = HugeEnum 22
+
+hugeEnum_VALUE_0023 :: HugeEnum
+hugeEnum_VALUE_0023 = HugeEnum 23
+
+hugeEnum_VALUE_0024 :: HugeEnum
+hugeEnum_VALUE_0024 = HugeEnum 24
+
+hugeEnum_VALUE_0025 :: HugeEnum
+hugeEnum_VALUE_0025 = HugeEnum 25
+
+hugeEnum_VALUE_0026 :: HugeEnum
+hugeEnum_VALUE_0026 = HugeEnum 26
+
+hugeEnum_VALUE_0027 :: HugeEnum
+hugeEnum_VALUE_0027 = HugeEnum 27
+
+hugeEnum_VALUE_0028 :: HugeEnum
+hugeEnum_VALUE_0028 = HugeEnum 28
+
+hugeEnum_VALUE_0029 :: HugeEnum
+hugeEnum_VALUE_0029 = HugeEnum 29
+
+hugeEnum_VALUE_0030 :: HugeEnum
+hugeEnum_VALUE_0030 = HugeEnum 30
+
+hugeEnum_VALUE_0031 :: HugeEnum
+hugeEnum_VALUE_0031 = HugeEnum 31
+
+hugeEnum_VALUE_0032 :: HugeEnum
+hugeEnum_VALUE_0032 = HugeEnum 32
+
+hugeEnum_VALUE_0033 :: HugeEnum
+hugeEnum_VALUE_0033 = HugeEnum 33
+
+hugeEnum_VALUE_0034 :: HugeEnum
+hugeEnum_VALUE_0034 = HugeEnum 34
+
+hugeEnum_VALUE_0035 :: HugeEnum
+hugeEnum_VALUE_0035 = HugeEnum 35
+
+hugeEnum_VALUE_0036 :: HugeEnum
+hugeEnum_VALUE_0036 = HugeEnum 36
+
+hugeEnum_VALUE_0037 :: HugeEnum
+hugeEnum_VALUE_0037 = HugeEnum 37
+
+hugeEnum_VALUE_0038 :: HugeEnum
+hugeEnum_VALUE_0038 = HugeEnum 38
+
+hugeEnum_VALUE_0039 :: HugeEnum
+hugeEnum_VALUE_0039 = HugeEnum 39
+
+hugeEnum_VALUE_0040 :: HugeEnum
+hugeEnum_VALUE_0040 = HugeEnum 40
+
+hugeEnum_VALUE_0041 :: HugeEnum
+hugeEnum_VALUE_0041 = HugeEnum 41
+
+hugeEnum_VALUE_0042 :: HugeEnum
+hugeEnum_VALUE_0042 = HugeEnum 42
+
+hugeEnum_VALUE_0043 :: HugeEnum
+hugeEnum_VALUE_0043 = HugeEnum 43
+
+hugeEnum_VALUE_0044 :: HugeEnum
+hugeEnum_VALUE_0044 = HugeEnum 44
+
+hugeEnum_VALUE_0045 :: HugeEnum
+hugeEnum_VALUE_0045 = HugeEnum 45
+
+hugeEnum_VALUE_0046 :: HugeEnum
+hugeEnum_VALUE_0046 = HugeEnum 46
+
+hugeEnum_VALUE_0047 :: HugeEnum
+hugeEnum_VALUE_0047 = HugeEnum 47
+
+hugeEnum_VALUE_0048 :: HugeEnum
+hugeEnum_VALUE_0048 = HugeEnum 48
+
+hugeEnum_VALUE_0049 :: HugeEnum
+hugeEnum_VALUE_0049 = HugeEnum 49
+
+hugeEnum_VALUE_0050 :: HugeEnum
+hugeEnum_VALUE_0050 = HugeEnum 50
+
+hugeEnum_VALUE_0051 :: HugeEnum
+hugeEnum_VALUE_0051 = HugeEnum 51
+
+hugeEnum_VALUE_0052 :: HugeEnum
+hugeEnum_VALUE_0052 = HugeEnum 52
+
+hugeEnum_VALUE_0053 :: HugeEnum
+hugeEnum_VALUE_0053 = HugeEnum 53
+
+hugeEnum_VALUE_0054 :: HugeEnum
+hugeEnum_VALUE_0054 = HugeEnum 54
+
+hugeEnum_VALUE_0055 :: HugeEnum
+hugeEnum_VALUE_0055 = HugeEnum 55
+
+hugeEnum_VALUE_0056 :: HugeEnum
+hugeEnum_VALUE_0056 = HugeEnum 56
+
+hugeEnum_VALUE_0057 :: HugeEnum
+hugeEnum_VALUE_0057 = HugeEnum 57
+
+hugeEnum_VALUE_0058 :: HugeEnum
+hugeEnum_VALUE_0058 = HugeEnum 58
+
+hugeEnum_VALUE_0059 :: HugeEnum
+hugeEnum_VALUE_0059 = HugeEnum 59
+
+hugeEnum_VALUE_0060 :: HugeEnum
+hugeEnum_VALUE_0060 = HugeEnum 60
+
+hugeEnum_VALUE_0061 :: HugeEnum
+hugeEnum_VALUE_0061 = HugeEnum 61
+
+hugeEnum_VALUE_0062 :: HugeEnum
+hugeEnum_VALUE_0062 = HugeEnum 62
+
+hugeEnum_VALUE_0063 :: HugeEnum
+hugeEnum_VALUE_0063 = HugeEnum 63
+
+hugeEnum_VALUE_0064 :: HugeEnum
+hugeEnum_VALUE_0064 = HugeEnum 64
+
+hugeEnum_VALUE_0065 :: HugeEnum
+hugeEnum_VALUE_0065 = HugeEnum 65
+
+hugeEnum_VALUE_0066 :: HugeEnum
+hugeEnum_VALUE_0066 = HugeEnum 66
+
+hugeEnum_VALUE_0067 :: HugeEnum
+hugeEnum_VALUE_0067 = HugeEnum 67
+
+hugeEnum_VALUE_0068 :: HugeEnum
+hugeEnum_VALUE_0068 = HugeEnum 68
+
+hugeEnum_VALUE_0069 :: HugeEnum
+hugeEnum_VALUE_0069 = HugeEnum 69
+
+hugeEnum_VALUE_0070 :: HugeEnum
+hugeEnum_VALUE_0070 = HugeEnum 70
+
+hugeEnum_VALUE_0071 :: HugeEnum
+hugeEnum_VALUE_0071 = HugeEnum 71
+
+hugeEnum_VALUE_0072 :: HugeEnum
+hugeEnum_VALUE_0072 = HugeEnum 72
+
+hugeEnum_VALUE_0073 :: HugeEnum
+hugeEnum_VALUE_0073 = HugeEnum 73
+
+hugeEnum_VALUE_0074 :: HugeEnum
+hugeEnum_VALUE_0074 = HugeEnum 74
+
+hugeEnum_VALUE_0075 :: HugeEnum
+hugeEnum_VALUE_0075 = HugeEnum 75
+
+hugeEnum_VALUE_0076 :: HugeEnum
+hugeEnum_VALUE_0076 = HugeEnum 76
+
+hugeEnum_VALUE_0077 :: HugeEnum
+hugeEnum_VALUE_0077 = HugeEnum 77
+
+hugeEnum_VALUE_0078 :: HugeEnum
+hugeEnum_VALUE_0078 = HugeEnum 78
+
+hugeEnum_VALUE_0079 :: HugeEnum
+hugeEnum_VALUE_0079 = HugeEnum 79
+
+hugeEnum_VALUE_0080 :: HugeEnum
+hugeEnum_VALUE_0080 = HugeEnum 80
+
+hugeEnum_VALUE_0081 :: HugeEnum
+hugeEnum_VALUE_0081 = HugeEnum 81
+
+hugeEnum_VALUE_0082 :: HugeEnum
+hugeEnum_VALUE_0082 = HugeEnum 82
+
+hugeEnum_VALUE_0083 :: HugeEnum
+hugeEnum_VALUE_0083 = HugeEnum 83
+
+hugeEnum_VALUE_0084 :: HugeEnum
+hugeEnum_VALUE_0084 = HugeEnum 84
+
+hugeEnum_VALUE_0085 :: HugeEnum
+hugeEnum_VALUE_0085 = HugeEnum 85
+
+hugeEnum_VALUE_0086 :: HugeEnum
+hugeEnum_VALUE_0086 = HugeEnum 86
+
+hugeEnum_VALUE_0087 :: HugeEnum
+hugeEnum_VALUE_0087 = HugeEnum 87
+
+hugeEnum_VALUE_0088 :: HugeEnum
+hugeEnum_VALUE_0088 = HugeEnum 88
+
+hugeEnum_VALUE_0089 :: HugeEnum
+hugeEnum_VALUE_0089 = HugeEnum 89
+
+hugeEnum_VALUE_0090 :: HugeEnum
+hugeEnum_VALUE_0090 = HugeEnum 90
+
+hugeEnum_VALUE_0091 :: HugeEnum
+hugeEnum_VALUE_0091 = HugeEnum 91
+
+hugeEnum_VALUE_0092 :: HugeEnum
+hugeEnum_VALUE_0092 = HugeEnum 92
+
+hugeEnum_VALUE_0093 :: HugeEnum
+hugeEnum_VALUE_0093 = HugeEnum 93
+
+hugeEnum_VALUE_0094 :: HugeEnum
+hugeEnum_VALUE_0094 = HugeEnum 94
+
+hugeEnum_VALUE_0095 :: HugeEnum
+hugeEnum_VALUE_0095 = HugeEnum 95
+
+hugeEnum_VALUE_0096 :: HugeEnum
+hugeEnum_VALUE_0096 = HugeEnum 96
+
+hugeEnum_VALUE_0097 :: HugeEnum
+hugeEnum_VALUE_0097 = HugeEnum 97
+
+hugeEnum_VALUE_0098 :: HugeEnum
+hugeEnum_VALUE_0098 = HugeEnum 98
+
+hugeEnum_VALUE_0099 :: HugeEnum
+hugeEnum_VALUE_0099 = HugeEnum 99
+
+hugeEnum_VALUE_0100 :: HugeEnum
+hugeEnum_VALUE_0100 = HugeEnum 100
+
+hugeEnum_VALUE_0101 :: HugeEnum
+hugeEnum_VALUE_0101 = HugeEnum 101
+
+hugeEnum_VALUE_0102 :: HugeEnum
+hugeEnum_VALUE_0102 = HugeEnum 102
+
+hugeEnum_VALUE_0103 :: HugeEnum
+hugeEnum_VALUE_0103 = HugeEnum 103
+
+hugeEnum_VALUE_0104 :: HugeEnum
+hugeEnum_VALUE_0104 = HugeEnum 104
+
+hugeEnum_VALUE_0105 :: HugeEnum
+hugeEnum_VALUE_0105 = HugeEnum 105
+
+hugeEnum_VALUE_0106 :: HugeEnum
+hugeEnum_VALUE_0106 = HugeEnum 106
+
+hugeEnum_VALUE_0107 :: HugeEnum
+hugeEnum_VALUE_0107 = HugeEnum 107
+
+hugeEnum_VALUE_0108 :: HugeEnum
+hugeEnum_VALUE_0108 = HugeEnum 108
+
+hugeEnum_VALUE_0109 :: HugeEnum
+hugeEnum_VALUE_0109 = HugeEnum 109
+
+hugeEnum_VALUE_0110 :: HugeEnum
+hugeEnum_VALUE_0110 = HugeEnum 110
+
+hugeEnum_VALUE_0111 :: HugeEnum
+hugeEnum_VALUE_0111 = HugeEnum 111
+
+hugeEnum_VALUE_0112 :: HugeEnum
+hugeEnum_VALUE_0112 = HugeEnum 112
+
+hugeEnum_VALUE_0113 :: HugeEnum
+hugeEnum_VALUE_0113 = HugeEnum 113
+
+hugeEnum_VALUE_0114 :: HugeEnum
+hugeEnum_VALUE_0114 = HugeEnum 114
+
+hugeEnum_VALUE_0115 :: HugeEnum
+hugeEnum_VALUE_0115 = HugeEnum 115
+
+hugeEnum_VALUE_0116 :: HugeEnum
+hugeEnum_VALUE_0116 = HugeEnum 116
+
+hugeEnum_VALUE_0117 :: HugeEnum
+hugeEnum_VALUE_0117 = HugeEnum 117
+
+hugeEnum_VALUE_0118 :: HugeEnum
+hugeEnum_VALUE_0118 = HugeEnum 118
+
+hugeEnum_VALUE_0119 :: HugeEnum
+hugeEnum_VALUE_0119 = HugeEnum 119
+
+hugeEnum_VALUE_0120 :: HugeEnum
+hugeEnum_VALUE_0120 = HugeEnum 120
+
+hugeEnum_VALUE_0121 :: HugeEnum
+hugeEnum_VALUE_0121 = HugeEnum 121
+
+hugeEnum_VALUE_0122 :: HugeEnum
+hugeEnum_VALUE_0122 = HugeEnum 122
+
+hugeEnum_VALUE_0123 :: HugeEnum
+hugeEnum_VALUE_0123 = HugeEnum 123
+
+hugeEnum_VALUE_0124 :: HugeEnum
+hugeEnum_VALUE_0124 = HugeEnum 124
+
+hugeEnum_VALUE_0125 :: HugeEnum
+hugeEnum_VALUE_0125 = HugeEnum 125
+
+hugeEnum_VALUE_0126 :: HugeEnum
+hugeEnum_VALUE_0126 = HugeEnum 126
+
+hugeEnum_VALUE_0127 :: HugeEnum
+hugeEnum_VALUE_0127 = HugeEnum 127
+
+hugeEnum_VALUE_0128 :: HugeEnum
+hugeEnum_VALUE_0128 = HugeEnum 128
+
+hugeEnum_VALUE_0129 :: HugeEnum
+hugeEnum_VALUE_0129 = HugeEnum 129
+
+hugeEnum_VALUE_0130 :: HugeEnum
+hugeEnum_VALUE_0130 = HugeEnum 130
+
+hugeEnum_VALUE_0131 :: HugeEnum
+hugeEnum_VALUE_0131 = HugeEnum 131
+
+hugeEnum_VALUE_0132 :: HugeEnum
+hugeEnum_VALUE_0132 = HugeEnum 132
+
+hugeEnum_VALUE_0133 :: HugeEnum
+hugeEnum_VALUE_0133 = HugeEnum 133
+
+hugeEnum_VALUE_0134 :: HugeEnum
+hugeEnum_VALUE_0134 = HugeEnum 134
+
+hugeEnum_VALUE_0135 :: HugeEnum
+hugeEnum_VALUE_0135 = HugeEnum 135
+
+hugeEnum_VALUE_0136 :: HugeEnum
+hugeEnum_VALUE_0136 = HugeEnum 136
+
+hugeEnum_VALUE_0137 :: HugeEnum
+hugeEnum_VALUE_0137 = HugeEnum 137
+
+hugeEnum_VALUE_0138 :: HugeEnum
+hugeEnum_VALUE_0138 = HugeEnum 138
+
+hugeEnum_VALUE_0139 :: HugeEnum
+hugeEnum_VALUE_0139 = HugeEnum 139
+
+hugeEnum_VALUE_0140 :: HugeEnum
+hugeEnum_VALUE_0140 = HugeEnum 140
+
+hugeEnum_VALUE_0141 :: HugeEnum
+hugeEnum_VALUE_0141 = HugeEnum 141
+
+hugeEnum_VALUE_0142 :: HugeEnum
+hugeEnum_VALUE_0142 = HugeEnum 142
+
+hugeEnum_VALUE_0143 :: HugeEnum
+hugeEnum_VALUE_0143 = HugeEnum 143
+
+hugeEnum_VALUE_0144 :: HugeEnum
+hugeEnum_VALUE_0144 = HugeEnum 144
+
+hugeEnum_VALUE_0145 :: HugeEnum
+hugeEnum_VALUE_0145 = HugeEnum 145
+
+hugeEnum_VALUE_0146 :: HugeEnum
+hugeEnum_VALUE_0146 = HugeEnum 146
+
+hugeEnum_VALUE_0147 :: HugeEnum
+hugeEnum_VALUE_0147 = HugeEnum 147
+
+hugeEnum_VALUE_0148 :: HugeEnum
+hugeEnum_VALUE_0148 = HugeEnum 148
+
+hugeEnum_VALUE_0149 :: HugeEnum
+hugeEnum_VALUE_0149 = HugeEnum 149
+
+hugeEnum_VALUE_0150 :: HugeEnum
+hugeEnum_VALUE_0150 = HugeEnum 150
+
+hugeEnum_VALUE_0151 :: HugeEnum
+hugeEnum_VALUE_0151 = HugeEnum 151
+
+hugeEnum_VALUE_0152 :: HugeEnum
+hugeEnum_VALUE_0152 = HugeEnum 152
+
+hugeEnum_VALUE_0153 :: HugeEnum
+hugeEnum_VALUE_0153 = HugeEnum 153
+
+hugeEnum_VALUE_0154 :: HugeEnum
+hugeEnum_VALUE_0154 = HugeEnum 154
+
+hugeEnum_VALUE_0155 :: HugeEnum
+hugeEnum_VALUE_0155 = HugeEnum 155
+
+hugeEnum_VALUE_0156 :: HugeEnum
+hugeEnum_VALUE_0156 = HugeEnum 156
+
+hugeEnum_VALUE_0157 :: HugeEnum
+hugeEnum_VALUE_0157 = HugeEnum 157
+
+hugeEnum_VALUE_0158 :: HugeEnum
+hugeEnum_VALUE_0158 = HugeEnum 158
+
+hugeEnum_VALUE_0159 :: HugeEnum
+hugeEnum_VALUE_0159 = HugeEnum 159
+
+hugeEnum_VALUE_0160 :: HugeEnum
+hugeEnum_VALUE_0160 = HugeEnum 160
+
+hugeEnum_VALUE_0161 :: HugeEnum
+hugeEnum_VALUE_0161 = HugeEnum 161
+
+hugeEnum_VALUE_0162 :: HugeEnum
+hugeEnum_VALUE_0162 = HugeEnum 162
+
+hugeEnum_VALUE_0163 :: HugeEnum
+hugeEnum_VALUE_0163 = HugeEnum 163
+
+hugeEnum_VALUE_0164 :: HugeEnum
+hugeEnum_VALUE_0164 = HugeEnum 164
+
+hugeEnum_VALUE_0165 :: HugeEnum
+hugeEnum_VALUE_0165 = HugeEnum 165
+
+hugeEnum_VALUE_0166 :: HugeEnum
+hugeEnum_VALUE_0166 = HugeEnum 166
+
+hugeEnum_VALUE_0167 :: HugeEnum
+hugeEnum_VALUE_0167 = HugeEnum 167
+
+hugeEnum_VALUE_0168 :: HugeEnum
+hugeEnum_VALUE_0168 = HugeEnum 168
+
+hugeEnum_VALUE_0169 :: HugeEnum
+hugeEnum_VALUE_0169 = HugeEnum 169
+
+hugeEnum_VALUE_0170 :: HugeEnum
+hugeEnum_VALUE_0170 = HugeEnum 170
+
+hugeEnum_VALUE_0171 :: HugeEnum
+hugeEnum_VALUE_0171 = HugeEnum 171
+
+hugeEnum_VALUE_0172 :: HugeEnum
+hugeEnum_VALUE_0172 = HugeEnum 172
+
+hugeEnum_VALUE_0173 :: HugeEnum
+hugeEnum_VALUE_0173 = HugeEnum 173
+
+hugeEnum_VALUE_0174 :: HugeEnum
+hugeEnum_VALUE_0174 = HugeEnum 174
+
+hugeEnum_VALUE_0175 :: HugeEnum
+hugeEnum_VALUE_0175 = HugeEnum 175
+
+hugeEnum_VALUE_0176 :: HugeEnum
+hugeEnum_VALUE_0176 = HugeEnum 176
+
+hugeEnum_VALUE_0177 :: HugeEnum
+hugeEnum_VALUE_0177 = HugeEnum 177
+
+hugeEnum_VALUE_0178 :: HugeEnum
+hugeEnum_VALUE_0178 = HugeEnum 178
+
+hugeEnum_VALUE_0179 :: HugeEnum
+hugeEnum_VALUE_0179 = HugeEnum 179
+
+hugeEnum_VALUE_0180 :: HugeEnum
+hugeEnum_VALUE_0180 = HugeEnum 180
+
+hugeEnum_VALUE_0181 :: HugeEnum
+hugeEnum_VALUE_0181 = HugeEnum 181
+
+hugeEnum_VALUE_0182 :: HugeEnum
+hugeEnum_VALUE_0182 = HugeEnum 182
+
+hugeEnum_VALUE_0183 :: HugeEnum
+hugeEnum_VALUE_0183 = HugeEnum 183
+
+hugeEnum_VALUE_0184 :: HugeEnum
+hugeEnum_VALUE_0184 = HugeEnum 184
+
+hugeEnum_VALUE_0185 :: HugeEnum
+hugeEnum_VALUE_0185 = HugeEnum 185
+
+hugeEnum_VALUE_0186 :: HugeEnum
+hugeEnum_VALUE_0186 = HugeEnum 186
+
+hugeEnum_VALUE_0187 :: HugeEnum
+hugeEnum_VALUE_0187 = HugeEnum 187
+
+hugeEnum_VALUE_0188 :: HugeEnum
+hugeEnum_VALUE_0188 = HugeEnum 188
+
+hugeEnum_VALUE_0189 :: HugeEnum
+hugeEnum_VALUE_0189 = HugeEnum 189
+
+hugeEnum_VALUE_0190 :: HugeEnum
+hugeEnum_VALUE_0190 = HugeEnum 190
+
+hugeEnum_VALUE_0191 :: HugeEnum
+hugeEnum_VALUE_0191 = HugeEnum 191
+
+hugeEnum_VALUE_0192 :: HugeEnum
+hugeEnum_VALUE_0192 = HugeEnum 192
+
+hugeEnum_VALUE_0193 :: HugeEnum
+hugeEnum_VALUE_0193 = HugeEnum 193
+
+hugeEnum_VALUE_0194 :: HugeEnum
+hugeEnum_VALUE_0194 = HugeEnum 194
+
+hugeEnum_VALUE_0195 :: HugeEnum
+hugeEnum_VALUE_0195 = HugeEnum 195
+
+hugeEnum_VALUE_0196 :: HugeEnum
+hugeEnum_VALUE_0196 = HugeEnum 196
+
+hugeEnum_VALUE_0197 :: HugeEnum
+hugeEnum_VALUE_0197 = HugeEnum 197
+
+hugeEnum_VALUE_0198 :: HugeEnum
+hugeEnum_VALUE_0198 = HugeEnum 198
+
+hugeEnum_VALUE_0199 :: HugeEnum
+hugeEnum_VALUE_0199 = HugeEnum 199
+
+hugeEnum_VALUE_0200 :: HugeEnum
+hugeEnum_VALUE_0200 = HugeEnum 200
+
+hugeEnum_VALUE_0201 :: HugeEnum
+hugeEnum_VALUE_0201 = HugeEnum 201
+
+hugeEnum_VALUE_0202 :: HugeEnum
+hugeEnum_VALUE_0202 = HugeEnum 202
+
+hugeEnum_VALUE_0203 :: HugeEnum
+hugeEnum_VALUE_0203 = HugeEnum 203
+
+hugeEnum_VALUE_0204 :: HugeEnum
+hugeEnum_VALUE_0204 = HugeEnum 204
+
+hugeEnum_VALUE_0205 :: HugeEnum
+hugeEnum_VALUE_0205 = HugeEnum 205
+
+hugeEnum_VALUE_0206 :: HugeEnum
+hugeEnum_VALUE_0206 = HugeEnum 206
+
+hugeEnum_VALUE_0207 :: HugeEnum
+hugeEnum_VALUE_0207 = HugeEnum 207
+
+hugeEnum_VALUE_0208 :: HugeEnum
+hugeEnum_VALUE_0208 = HugeEnum 208
+
+hugeEnum_VALUE_0209 :: HugeEnum
+hugeEnum_VALUE_0209 = HugeEnum 209
+
+hugeEnum_VALUE_0210 :: HugeEnum
+hugeEnum_VALUE_0210 = HugeEnum 210
+
+hugeEnum_VALUE_0211 :: HugeEnum
+hugeEnum_VALUE_0211 = HugeEnum 211
+
+hugeEnum_VALUE_0212 :: HugeEnum
+hugeEnum_VALUE_0212 = HugeEnum 212
+
+hugeEnum_VALUE_0213 :: HugeEnum
+hugeEnum_VALUE_0213 = HugeEnum 213
+
+hugeEnum_VALUE_0214 :: HugeEnum
+hugeEnum_VALUE_0214 = HugeEnum 214
+
+hugeEnum_VALUE_0215 :: HugeEnum
+hugeEnum_VALUE_0215 = HugeEnum 215
+
+hugeEnum_VALUE_0216 :: HugeEnum
+hugeEnum_VALUE_0216 = HugeEnum 216
+
+hugeEnum_VALUE_0217 :: HugeEnum
+hugeEnum_VALUE_0217 = HugeEnum 217
+
+hugeEnum_VALUE_0218 :: HugeEnum
+hugeEnum_VALUE_0218 = HugeEnum 218
+
+hugeEnum_VALUE_0219 :: HugeEnum
+hugeEnum_VALUE_0219 = HugeEnum 219
+
+hugeEnum_VALUE_0220 :: HugeEnum
+hugeEnum_VALUE_0220 = HugeEnum 220
+
+hugeEnum_VALUE_0221 :: HugeEnum
+hugeEnum_VALUE_0221 = HugeEnum 221
+
+hugeEnum_VALUE_0222 :: HugeEnum
+hugeEnum_VALUE_0222 = HugeEnum 222
+
+hugeEnum_VALUE_0223 :: HugeEnum
+hugeEnum_VALUE_0223 = HugeEnum 223
+
+hugeEnum_VALUE_0224 :: HugeEnum
+hugeEnum_VALUE_0224 = HugeEnum 224
+
+hugeEnum_VALUE_0225 :: HugeEnum
+hugeEnum_VALUE_0225 = HugeEnum 225
+
+hugeEnum_VALUE_0226 :: HugeEnum
+hugeEnum_VALUE_0226 = HugeEnum 226
+
+hugeEnum_VALUE_0227 :: HugeEnum
+hugeEnum_VALUE_0227 = HugeEnum 227
+
+hugeEnum_VALUE_0228 :: HugeEnum
+hugeEnum_VALUE_0228 = HugeEnum 228
+
+hugeEnum_VALUE_0229 :: HugeEnum
+hugeEnum_VALUE_0229 = HugeEnum 229
+
+hugeEnum_VALUE_0230 :: HugeEnum
+hugeEnum_VALUE_0230 = HugeEnum 230
+
+hugeEnum_VALUE_0231 :: HugeEnum
+hugeEnum_VALUE_0231 = HugeEnum 231
+
+hugeEnum_VALUE_0232 :: HugeEnum
+hugeEnum_VALUE_0232 = HugeEnum 232
+
+hugeEnum_VALUE_0233 :: HugeEnum
+hugeEnum_VALUE_0233 = HugeEnum 233
+
+hugeEnum_VALUE_0234 :: HugeEnum
+hugeEnum_VALUE_0234 = HugeEnum 234
+
+hugeEnum_VALUE_0235 :: HugeEnum
+hugeEnum_VALUE_0235 = HugeEnum 235
+
+hugeEnum_VALUE_0236 :: HugeEnum
+hugeEnum_VALUE_0236 = HugeEnum 236
+
+hugeEnum_VALUE_0237 :: HugeEnum
+hugeEnum_VALUE_0237 = HugeEnum 237
+
+hugeEnum_VALUE_0238 :: HugeEnum
+hugeEnum_VALUE_0238 = HugeEnum 238
+
+hugeEnum_VALUE_0239 :: HugeEnum
+hugeEnum_VALUE_0239 = HugeEnum 239
+
+hugeEnum_VALUE_0240 :: HugeEnum
+hugeEnum_VALUE_0240 = HugeEnum 240
+
+hugeEnum_VALUE_0241 :: HugeEnum
+hugeEnum_VALUE_0241 = HugeEnum 241
+
+hugeEnum_VALUE_0242 :: HugeEnum
+hugeEnum_VALUE_0242 = HugeEnum 242
+
+hugeEnum_VALUE_0243 :: HugeEnum
+hugeEnum_VALUE_0243 = HugeEnum 243
+
+hugeEnum_VALUE_0244 :: HugeEnum
+hugeEnum_VALUE_0244 = HugeEnum 244
+
+hugeEnum_VALUE_0245 :: HugeEnum
+hugeEnum_VALUE_0245 = HugeEnum 245
+
+hugeEnum_VALUE_0246 :: HugeEnum
+hugeEnum_VALUE_0246 = HugeEnum 246
+
+hugeEnum_VALUE_0247 :: HugeEnum
+hugeEnum_VALUE_0247 = HugeEnum 247
+
+hugeEnum_VALUE_0248 :: HugeEnum
+hugeEnum_VALUE_0248 = HugeEnum 248
+
+hugeEnum_VALUE_0249 :: HugeEnum
+hugeEnum_VALUE_0249 = HugeEnum 249
+
+hugeEnum_VALUE_0250 :: HugeEnum
+hugeEnum_VALUE_0250 = HugeEnum 250
+
+hugeEnum_VALUE_0251 :: HugeEnum
+hugeEnum_VALUE_0251 = HugeEnum 251
+
+hugeEnum_VALUE_0252 :: HugeEnum
+hugeEnum_VALUE_0252 = HugeEnum 252
+
+hugeEnum_VALUE_0253 :: HugeEnum
+hugeEnum_VALUE_0253 = HugeEnum 253
+
+hugeEnum_VALUE_0254 :: HugeEnum
+hugeEnum_VALUE_0254 = HugeEnum 254
+
+hugeEnum_VALUE_0255 :: HugeEnum
+hugeEnum_VALUE_0255 = HugeEnum 255
+
+hugeEnum_VALUE_0256 :: HugeEnum
+hugeEnum_VALUE_0256 = HugeEnum 256
+
+hugeEnum_VALUE_0257 :: HugeEnum
+hugeEnum_VALUE_0257 = HugeEnum 257
+
+hugeEnum_VALUE_0258 :: HugeEnum
+hugeEnum_VALUE_0258 = HugeEnum 258
+
+hugeEnum_VALUE_0259 :: HugeEnum
+hugeEnum_VALUE_0259 = HugeEnum 259
+
+hugeEnum_VALUE_0260 :: HugeEnum
+hugeEnum_VALUE_0260 = HugeEnum 260
+
+hugeEnum_VALUE_0261 :: HugeEnum
+hugeEnum_VALUE_0261 = HugeEnum 261
+
+hugeEnum_VALUE_0262 :: HugeEnum
+hugeEnum_VALUE_0262 = HugeEnum 262
+
+hugeEnum_VALUE_0263 :: HugeEnum
+hugeEnum_VALUE_0263 = HugeEnum 263
+
+hugeEnum_VALUE_0264 :: HugeEnum
+hugeEnum_VALUE_0264 = HugeEnum 264
+
+hugeEnum_VALUE_0265 :: HugeEnum
+hugeEnum_VALUE_0265 = HugeEnum 265
+
+hugeEnum_VALUE_0266 :: HugeEnum
+hugeEnum_VALUE_0266 = HugeEnum 266
+
+hugeEnum_VALUE_0267 :: HugeEnum
+hugeEnum_VALUE_0267 = HugeEnum 267
+
+hugeEnum_VALUE_0268 :: HugeEnum
+hugeEnum_VALUE_0268 = HugeEnum 268
+
+hugeEnum_VALUE_0269 :: HugeEnum
+hugeEnum_VALUE_0269 = HugeEnum 269
+
+hugeEnum_VALUE_0270 :: HugeEnum
+hugeEnum_VALUE_0270 = HugeEnum 270
+
+hugeEnum_VALUE_0271 :: HugeEnum
+hugeEnum_VALUE_0271 = HugeEnum 271
+
+hugeEnum_VALUE_0272 :: HugeEnum
+hugeEnum_VALUE_0272 = HugeEnum 272
+
+hugeEnum_VALUE_0273 :: HugeEnum
+hugeEnum_VALUE_0273 = HugeEnum 273
+
+hugeEnum_VALUE_0274 :: HugeEnum
+hugeEnum_VALUE_0274 = HugeEnum 274
+
+hugeEnum_VALUE_0275 :: HugeEnum
+hugeEnum_VALUE_0275 = HugeEnum 275
+
+hugeEnum_VALUE_0276 :: HugeEnum
+hugeEnum_VALUE_0276 = HugeEnum 276
+
+hugeEnum_VALUE_0277 :: HugeEnum
+hugeEnum_VALUE_0277 = HugeEnum 277
+
+hugeEnum_VALUE_0278 :: HugeEnum
+hugeEnum_VALUE_0278 = HugeEnum 278
+
+hugeEnum_VALUE_0279 :: HugeEnum
+hugeEnum_VALUE_0279 = HugeEnum 279
+
+hugeEnum_VALUE_0280 :: HugeEnum
+hugeEnum_VALUE_0280 = HugeEnum 280
+
+hugeEnum_VALUE_0281 :: HugeEnum
+hugeEnum_VALUE_0281 = HugeEnum 281
+
+hugeEnum_VALUE_0282 :: HugeEnum
+hugeEnum_VALUE_0282 = HugeEnum 282
+
+hugeEnum_VALUE_0283 :: HugeEnum
+hugeEnum_VALUE_0283 = HugeEnum 283
+
+hugeEnum_VALUE_0284 :: HugeEnum
+hugeEnum_VALUE_0284 = HugeEnum 284
+
+hugeEnum_VALUE_0285 :: HugeEnum
+hugeEnum_VALUE_0285 = HugeEnum 285
+
+hugeEnum_VALUE_0286 :: HugeEnum
+hugeEnum_VALUE_0286 = HugeEnum 286
+
+hugeEnum_VALUE_0287 :: HugeEnum
+hugeEnum_VALUE_0287 = HugeEnum 287
+
+hugeEnum_VALUE_0288 :: HugeEnum
+hugeEnum_VALUE_0288 = HugeEnum 288
+
+hugeEnum_VALUE_0289 :: HugeEnum
+hugeEnum_VALUE_0289 = HugeEnum 289
+
+hugeEnum_VALUE_0290 :: HugeEnum
+hugeEnum_VALUE_0290 = HugeEnum 290
+
+hugeEnum_VALUE_0291 :: HugeEnum
+hugeEnum_VALUE_0291 = HugeEnum 291
+
+hugeEnum_VALUE_0292 :: HugeEnum
+hugeEnum_VALUE_0292 = HugeEnum 292
+
+hugeEnum_VALUE_0293 :: HugeEnum
+hugeEnum_VALUE_0293 = HugeEnum 293
+
+hugeEnum_VALUE_0294 :: HugeEnum
+hugeEnum_VALUE_0294 = HugeEnum 294
+
+hugeEnum_VALUE_0295 :: HugeEnum
+hugeEnum_VALUE_0295 = HugeEnum 295
+
+hugeEnum_VALUE_0296 :: HugeEnum
+hugeEnum_VALUE_0296 = HugeEnum 296
+
+hugeEnum_VALUE_0297 :: HugeEnum
+hugeEnum_VALUE_0297 = HugeEnum 297
+
+hugeEnum_VALUE_0298 :: HugeEnum
+hugeEnum_VALUE_0298 = HugeEnum 298
+
+hugeEnum_VALUE_0299 :: HugeEnum
+hugeEnum_VALUE_0299 = HugeEnum 299
+
+hugeEnum_VALUE_0300 :: HugeEnum
+hugeEnum_VALUE_0300 = HugeEnum 300
+
+hugeEnum_VALUE_0301 :: HugeEnum
+hugeEnum_VALUE_0301 = HugeEnum 301
+
+hugeEnum_VALUE_0302 :: HugeEnum
+hugeEnum_VALUE_0302 = HugeEnum 302
+
+hugeEnum_VALUE_0303 :: HugeEnum
+hugeEnum_VALUE_0303 = HugeEnum 303
+
+hugeEnum_VALUE_0304 :: HugeEnum
+hugeEnum_VALUE_0304 = HugeEnum 304
+
+hugeEnum_VALUE_0305 :: HugeEnum
+hugeEnum_VALUE_0305 = HugeEnum 305
+
+hugeEnum_VALUE_0306 :: HugeEnum
+hugeEnum_VALUE_0306 = HugeEnum 306
+
+hugeEnum_VALUE_0307 :: HugeEnum
+hugeEnum_VALUE_0307 = HugeEnum 307
+
+hugeEnum_VALUE_0308 :: HugeEnum
+hugeEnum_VALUE_0308 = HugeEnum 308
+
+hugeEnum_VALUE_0309 :: HugeEnum
+hugeEnum_VALUE_0309 = HugeEnum 309
+
+hugeEnum_VALUE_0310 :: HugeEnum
+hugeEnum_VALUE_0310 = HugeEnum 310
+
+hugeEnum_VALUE_0311 :: HugeEnum
+hugeEnum_VALUE_0311 = HugeEnum 311
+
+hugeEnum_VALUE_0312 :: HugeEnum
+hugeEnum_VALUE_0312 = HugeEnum 312
+
+hugeEnum_VALUE_0313 :: HugeEnum
+hugeEnum_VALUE_0313 = HugeEnum 313
+
+hugeEnum_VALUE_0314 :: HugeEnum
+hugeEnum_VALUE_0314 = HugeEnum 314
+
+hugeEnum_VALUE_0315 :: HugeEnum
+hugeEnum_VALUE_0315 = HugeEnum 315
+
+hugeEnum_VALUE_0316 :: HugeEnum
+hugeEnum_VALUE_0316 = HugeEnum 316
+
+hugeEnum_VALUE_0317 :: HugeEnum
+hugeEnum_VALUE_0317 = HugeEnum 317
+
+hugeEnum_VALUE_0318 :: HugeEnum
+hugeEnum_VALUE_0318 = HugeEnum 318
+
+hugeEnum_VALUE_0319 :: HugeEnum
+hugeEnum_VALUE_0319 = HugeEnum 319
+
+hugeEnum_VALUE_0320 :: HugeEnum
+hugeEnum_VALUE_0320 = HugeEnum 320
+
+hugeEnum_VALUE_0321 :: HugeEnum
+hugeEnum_VALUE_0321 = HugeEnum 321
+
+hugeEnum_VALUE_0322 :: HugeEnum
+hugeEnum_VALUE_0322 = HugeEnum 322
+
+hugeEnum_VALUE_0323 :: HugeEnum
+hugeEnum_VALUE_0323 = HugeEnum 323
+
+hugeEnum_VALUE_0324 :: HugeEnum
+hugeEnum_VALUE_0324 = HugeEnum 324
+
+hugeEnum_VALUE_0325 :: HugeEnum
+hugeEnum_VALUE_0325 = HugeEnum 325
+
+hugeEnum_VALUE_0326 :: HugeEnum
+hugeEnum_VALUE_0326 = HugeEnum 326
+
+hugeEnum_VALUE_0327 :: HugeEnum
+hugeEnum_VALUE_0327 = HugeEnum 327
+
+hugeEnum_VALUE_0328 :: HugeEnum
+hugeEnum_VALUE_0328 = HugeEnum 328
+
+hugeEnum_VALUE_0329 :: HugeEnum
+hugeEnum_VALUE_0329 = HugeEnum 329
+
+hugeEnum_VALUE_0330 :: HugeEnum
+hugeEnum_VALUE_0330 = HugeEnum 330
+
+hugeEnum_VALUE_0331 :: HugeEnum
+hugeEnum_VALUE_0331 = HugeEnum 331
+
+hugeEnum_VALUE_0332 :: HugeEnum
+hugeEnum_VALUE_0332 = HugeEnum 332
+
+hugeEnum_VALUE_0333 :: HugeEnum
+hugeEnum_VALUE_0333 = HugeEnum 333
+
+hugeEnum_VALUE_0334 :: HugeEnum
+hugeEnum_VALUE_0334 = HugeEnum 334
+
+hugeEnum_VALUE_0335 :: HugeEnum
+hugeEnum_VALUE_0335 = HugeEnum 335
+
+hugeEnum_VALUE_0336 :: HugeEnum
+hugeEnum_VALUE_0336 = HugeEnum 336
+
+hugeEnum_VALUE_0337 :: HugeEnum
+hugeEnum_VALUE_0337 = HugeEnum 337
+
+hugeEnum_VALUE_0338 :: HugeEnum
+hugeEnum_VALUE_0338 = HugeEnum 338
+
+hugeEnum_VALUE_0339 :: HugeEnum
+hugeEnum_VALUE_0339 = HugeEnum 339
+
+hugeEnum_VALUE_0340 :: HugeEnum
+hugeEnum_VALUE_0340 = HugeEnum 340
+
+hugeEnum_VALUE_0341 :: HugeEnum
+hugeEnum_VALUE_0341 = HugeEnum 341
+
+hugeEnum_VALUE_0342 :: HugeEnum
+hugeEnum_VALUE_0342 = HugeEnum 342
+
+hugeEnum_VALUE_0343 :: HugeEnum
+hugeEnum_VALUE_0343 = HugeEnum 343
+
+hugeEnum_VALUE_0344 :: HugeEnum
+hugeEnum_VALUE_0344 = HugeEnum 344
+
+hugeEnum_VALUE_0345 :: HugeEnum
+hugeEnum_VALUE_0345 = HugeEnum 345
+
+hugeEnum_VALUE_0346 :: HugeEnum
+hugeEnum_VALUE_0346 = HugeEnum 346
+
+hugeEnum_VALUE_0347 :: HugeEnum
+hugeEnum_VALUE_0347 = HugeEnum 347
+
+hugeEnum_VALUE_0348 :: HugeEnum
+hugeEnum_VALUE_0348 = HugeEnum 348
+
+hugeEnum_VALUE_0349 :: HugeEnum
+hugeEnum_VALUE_0349 = HugeEnum 349
+
+hugeEnum_VALUE_0350 :: HugeEnum
+hugeEnum_VALUE_0350 = HugeEnum 350
+
+hugeEnum_VALUE_0351 :: HugeEnum
+hugeEnum_VALUE_0351 = HugeEnum 351
+
+hugeEnum_VALUE_0352 :: HugeEnum
+hugeEnum_VALUE_0352 = HugeEnum 352
+
+hugeEnum_VALUE_0353 :: HugeEnum
+hugeEnum_VALUE_0353 = HugeEnum 353
+
+hugeEnum_VALUE_0354 :: HugeEnum
+hugeEnum_VALUE_0354 = HugeEnum 354
+
+hugeEnum_VALUE_0355 :: HugeEnum
+hugeEnum_VALUE_0355 = HugeEnum 355
+
+hugeEnum_VALUE_0356 :: HugeEnum
+hugeEnum_VALUE_0356 = HugeEnum 356
+
+hugeEnum_VALUE_0357 :: HugeEnum
+hugeEnum_VALUE_0357 = HugeEnum 357
+
+hugeEnum_VALUE_0358 :: HugeEnum
+hugeEnum_VALUE_0358 = HugeEnum 358
+
+hugeEnum_VALUE_0359 :: HugeEnum
+hugeEnum_VALUE_0359 = HugeEnum 359
+
+hugeEnum_VALUE_0360 :: HugeEnum
+hugeEnum_VALUE_0360 = HugeEnum 360
+
+hugeEnum_VALUE_0361 :: HugeEnum
+hugeEnum_VALUE_0361 = HugeEnum 361
+
+hugeEnum_VALUE_0362 :: HugeEnum
+hugeEnum_VALUE_0362 = HugeEnum 362
+
+hugeEnum_VALUE_0363 :: HugeEnum
+hugeEnum_VALUE_0363 = HugeEnum 363
+
+hugeEnum_VALUE_0364 :: HugeEnum
+hugeEnum_VALUE_0364 = HugeEnum 364
+
+hugeEnum_VALUE_0365 :: HugeEnum
+hugeEnum_VALUE_0365 = HugeEnum 365
+
+hugeEnum_VALUE_0366 :: HugeEnum
+hugeEnum_VALUE_0366 = HugeEnum 366
+
+hugeEnum_VALUE_0367 :: HugeEnum
+hugeEnum_VALUE_0367 = HugeEnum 367
+
+hugeEnum_VALUE_0368 :: HugeEnum
+hugeEnum_VALUE_0368 = HugeEnum 368
+
+hugeEnum_VALUE_0369 :: HugeEnum
+hugeEnum_VALUE_0369 = HugeEnum 369
+
+hugeEnum_VALUE_0370 :: HugeEnum
+hugeEnum_VALUE_0370 = HugeEnum 370
+
+hugeEnum_VALUE_0371 :: HugeEnum
+hugeEnum_VALUE_0371 = HugeEnum 371
+
+hugeEnum_VALUE_0372 :: HugeEnum
+hugeEnum_VALUE_0372 = HugeEnum 372
+
+hugeEnum_VALUE_0373 :: HugeEnum
+hugeEnum_VALUE_0373 = HugeEnum 373
+
+hugeEnum_VALUE_0374 :: HugeEnum
+hugeEnum_VALUE_0374 = HugeEnum 374
+
+hugeEnum_VALUE_0375 :: HugeEnum
+hugeEnum_VALUE_0375 = HugeEnum 375
+
+hugeEnum_VALUE_0376 :: HugeEnum
+hugeEnum_VALUE_0376 = HugeEnum 376
+
+hugeEnum_VALUE_0377 :: HugeEnum
+hugeEnum_VALUE_0377 = HugeEnum 377
+
+hugeEnum_VALUE_0378 :: HugeEnum
+hugeEnum_VALUE_0378 = HugeEnum 378
+
+hugeEnum_VALUE_0379 :: HugeEnum
+hugeEnum_VALUE_0379 = HugeEnum 379
+
+hugeEnum_VALUE_0380 :: HugeEnum
+hugeEnum_VALUE_0380 = HugeEnum 380
+
+hugeEnum_VALUE_0381 :: HugeEnum
+hugeEnum_VALUE_0381 = HugeEnum 381
+
+hugeEnum_VALUE_0382 :: HugeEnum
+hugeEnum_VALUE_0382 = HugeEnum 382
+
+hugeEnum_VALUE_0383 :: HugeEnum
+hugeEnum_VALUE_0383 = HugeEnum 383
+
+hugeEnum_VALUE_0384 :: HugeEnum
+hugeEnum_VALUE_0384 = HugeEnum 384
+
+hugeEnum_VALUE_0385 :: HugeEnum
+hugeEnum_VALUE_0385 = HugeEnum 385
+
+hugeEnum_VALUE_0386 :: HugeEnum
+hugeEnum_VALUE_0386 = HugeEnum 386
+
+hugeEnum_VALUE_0387 :: HugeEnum
+hugeEnum_VALUE_0387 = HugeEnum 387
+
+hugeEnum_VALUE_0388 :: HugeEnum
+hugeEnum_VALUE_0388 = HugeEnum 388
+
+hugeEnum_VALUE_0389 :: HugeEnum
+hugeEnum_VALUE_0389 = HugeEnum 389
+
+hugeEnum_VALUE_0390 :: HugeEnum
+hugeEnum_VALUE_0390 = HugeEnum 390
+
+hugeEnum_VALUE_0391 :: HugeEnum
+hugeEnum_VALUE_0391 = HugeEnum 391
+
+hugeEnum_VALUE_0392 :: HugeEnum
+hugeEnum_VALUE_0392 = HugeEnum 392
+
+hugeEnum_VALUE_0393 :: HugeEnum
+hugeEnum_VALUE_0393 = HugeEnum 393
+
+hugeEnum_VALUE_0394 :: HugeEnum
+hugeEnum_VALUE_0394 = HugeEnum 394
+
+hugeEnum_VALUE_0395 :: HugeEnum
+hugeEnum_VALUE_0395 = HugeEnum 395
+
+hugeEnum_VALUE_0396 :: HugeEnum
+hugeEnum_VALUE_0396 = HugeEnum 396
+
+hugeEnum_VALUE_0397 :: HugeEnum
+hugeEnum_VALUE_0397 = HugeEnum 397
+
+hugeEnum_VALUE_0398 :: HugeEnum
+hugeEnum_VALUE_0398 = HugeEnum 398
+
+hugeEnum_VALUE_0399 :: HugeEnum
+hugeEnum_VALUE_0399 = HugeEnum 399
+
+hugeEnum_VALUE_0400 :: HugeEnum
+hugeEnum_VALUE_0400 = HugeEnum 400
+
+hugeEnum_VALUE_0401 :: HugeEnum
+hugeEnum_VALUE_0401 = HugeEnum 401
+
+hugeEnum_VALUE_0402 :: HugeEnum
+hugeEnum_VALUE_0402 = HugeEnum 402
+
+hugeEnum_VALUE_0403 :: HugeEnum
+hugeEnum_VALUE_0403 = HugeEnum 403
+
+hugeEnum_VALUE_0404 :: HugeEnum
+hugeEnum_VALUE_0404 = HugeEnum 404
+
+hugeEnum_VALUE_0405 :: HugeEnum
+hugeEnum_VALUE_0405 = HugeEnum 405
+
+hugeEnum_VALUE_0406 :: HugeEnum
+hugeEnum_VALUE_0406 = HugeEnum 406
+
+hugeEnum_VALUE_0407 :: HugeEnum
+hugeEnum_VALUE_0407 = HugeEnum 407
+
+hugeEnum_VALUE_0408 :: HugeEnum
+hugeEnum_VALUE_0408 = HugeEnum 408
+
+hugeEnum_VALUE_0409 :: HugeEnum
+hugeEnum_VALUE_0409 = HugeEnum 409
+
+hugeEnum_VALUE_0410 :: HugeEnum
+hugeEnum_VALUE_0410 = HugeEnum 410
+
+hugeEnum_VALUE_0411 :: HugeEnum
+hugeEnum_VALUE_0411 = HugeEnum 411
+
+hugeEnum_VALUE_0412 :: HugeEnum
+hugeEnum_VALUE_0412 = HugeEnum 412
+
+hugeEnum_VALUE_0413 :: HugeEnum
+hugeEnum_VALUE_0413 = HugeEnum 413
+
+hugeEnum_VALUE_0414 :: HugeEnum
+hugeEnum_VALUE_0414 = HugeEnum 414
+
+hugeEnum_VALUE_0415 :: HugeEnum
+hugeEnum_VALUE_0415 = HugeEnum 415
+
+hugeEnum_VALUE_0416 :: HugeEnum
+hugeEnum_VALUE_0416 = HugeEnum 416
+
+hugeEnum_VALUE_0417 :: HugeEnum
+hugeEnum_VALUE_0417 = HugeEnum 417
+
+hugeEnum_VALUE_0418 :: HugeEnum
+hugeEnum_VALUE_0418 = HugeEnum 418
+
+hugeEnum_VALUE_0419 :: HugeEnum
+hugeEnum_VALUE_0419 = HugeEnum 419
+
+hugeEnum_VALUE_0420 :: HugeEnum
+hugeEnum_VALUE_0420 = HugeEnum 420
+
+hugeEnum_VALUE_0421 :: HugeEnum
+hugeEnum_VALUE_0421 = HugeEnum 421
+
+hugeEnum_VALUE_0422 :: HugeEnum
+hugeEnum_VALUE_0422 = HugeEnum 422
+
+hugeEnum_VALUE_0423 :: HugeEnum
+hugeEnum_VALUE_0423 = HugeEnum 423
+
+hugeEnum_VALUE_0424 :: HugeEnum
+hugeEnum_VALUE_0424 = HugeEnum 424
+
+hugeEnum_VALUE_0425 :: HugeEnum
+hugeEnum_VALUE_0425 = HugeEnum 425
+
+hugeEnum_VALUE_0426 :: HugeEnum
+hugeEnum_VALUE_0426 = HugeEnum 426
+
+hugeEnum_VALUE_0427 :: HugeEnum
+hugeEnum_VALUE_0427 = HugeEnum 427
+
+hugeEnum_VALUE_0428 :: HugeEnum
+hugeEnum_VALUE_0428 = HugeEnum 428
+
+hugeEnum_VALUE_0429 :: HugeEnum
+hugeEnum_VALUE_0429 = HugeEnum 429
+
+hugeEnum_VALUE_0430 :: HugeEnum
+hugeEnum_VALUE_0430 = HugeEnum 430
+
+hugeEnum_VALUE_0431 :: HugeEnum
+hugeEnum_VALUE_0431 = HugeEnum 431
+
+hugeEnum_VALUE_0432 :: HugeEnum
+hugeEnum_VALUE_0432 = HugeEnum 432
+
+hugeEnum_VALUE_0433 :: HugeEnum
+hugeEnum_VALUE_0433 = HugeEnum 433
+
+hugeEnum_VALUE_0434 :: HugeEnum
+hugeEnum_VALUE_0434 = HugeEnum 434
+
+hugeEnum_VALUE_0435 :: HugeEnum
+hugeEnum_VALUE_0435 = HugeEnum 435
+
+hugeEnum_VALUE_0436 :: HugeEnum
+hugeEnum_VALUE_0436 = HugeEnum 436
+
+hugeEnum_VALUE_0437 :: HugeEnum
+hugeEnum_VALUE_0437 = HugeEnum 437
+
+hugeEnum_VALUE_0438 :: HugeEnum
+hugeEnum_VALUE_0438 = HugeEnum 438
+
+hugeEnum_VALUE_0439 :: HugeEnum
+hugeEnum_VALUE_0439 = HugeEnum 439
+
+hugeEnum_VALUE_0440 :: HugeEnum
+hugeEnum_VALUE_0440 = HugeEnum 440
+
+hugeEnum_VALUE_0441 :: HugeEnum
+hugeEnum_VALUE_0441 = HugeEnum 441
+
+hugeEnum_VALUE_0442 :: HugeEnum
+hugeEnum_VALUE_0442 = HugeEnum 442
+
+hugeEnum_VALUE_0443 :: HugeEnum
+hugeEnum_VALUE_0443 = HugeEnum 443
+
+hugeEnum_VALUE_0444 :: HugeEnum
+hugeEnum_VALUE_0444 = HugeEnum 444
+
+hugeEnum_VALUE_0445 :: HugeEnum
+hugeEnum_VALUE_0445 = HugeEnum 445
+
+hugeEnum_VALUE_0446 :: HugeEnum
+hugeEnum_VALUE_0446 = HugeEnum 446
+
+hugeEnum_VALUE_0447 :: HugeEnum
+hugeEnum_VALUE_0447 = HugeEnum 447
+
+hugeEnum_VALUE_0448 :: HugeEnum
+hugeEnum_VALUE_0448 = HugeEnum 448
+
+hugeEnum_VALUE_0449 :: HugeEnum
+hugeEnum_VALUE_0449 = HugeEnum 449
+
+hugeEnum_VALUE_0450 :: HugeEnum
+hugeEnum_VALUE_0450 = HugeEnum 450
+
+hugeEnum_VALUE_0451 :: HugeEnum
+hugeEnum_VALUE_0451 = HugeEnum 451
+
+hugeEnum_VALUE_0452 :: HugeEnum
+hugeEnum_VALUE_0452 = HugeEnum 452
+
+hugeEnum_VALUE_0453 :: HugeEnum
+hugeEnum_VALUE_0453 = HugeEnum 453
+
+hugeEnum_VALUE_0454 :: HugeEnum
+hugeEnum_VALUE_0454 = HugeEnum 454
+
+hugeEnum_VALUE_0455 :: HugeEnum
+hugeEnum_VALUE_0455 = HugeEnum 455
+
+hugeEnum_VALUE_0456 :: HugeEnum
+hugeEnum_VALUE_0456 = HugeEnum 456
+
+hugeEnum_VALUE_0457 :: HugeEnum
+hugeEnum_VALUE_0457 = HugeEnum 457
+
+hugeEnum_VALUE_0458 :: HugeEnum
+hugeEnum_VALUE_0458 = HugeEnum 458
+
+hugeEnum_VALUE_0459 :: HugeEnum
+hugeEnum_VALUE_0459 = HugeEnum 459
+
+hugeEnum_VALUE_0460 :: HugeEnum
+hugeEnum_VALUE_0460 = HugeEnum 460
+
+hugeEnum_VALUE_0461 :: HugeEnum
+hugeEnum_VALUE_0461 = HugeEnum 461
+
+hugeEnum_VALUE_0462 :: HugeEnum
+hugeEnum_VALUE_0462 = HugeEnum 462
+
+hugeEnum_VALUE_0463 :: HugeEnum
+hugeEnum_VALUE_0463 = HugeEnum 463
+
+hugeEnum_VALUE_0464 :: HugeEnum
+hugeEnum_VALUE_0464 = HugeEnum 464
+
+hugeEnum_VALUE_0465 :: HugeEnum
+hugeEnum_VALUE_0465 = HugeEnum 465
+
+hugeEnum_VALUE_0466 :: HugeEnum
+hugeEnum_VALUE_0466 = HugeEnum 466
+
+hugeEnum_VALUE_0467 :: HugeEnum
+hugeEnum_VALUE_0467 = HugeEnum 467
+
+hugeEnum_VALUE_0468 :: HugeEnum
+hugeEnum_VALUE_0468 = HugeEnum 468
+
+hugeEnum_VALUE_0469 :: HugeEnum
+hugeEnum_VALUE_0469 = HugeEnum 469
+
+hugeEnum_VALUE_0470 :: HugeEnum
+hugeEnum_VALUE_0470 = HugeEnum 470
+
+hugeEnum_VALUE_0471 :: HugeEnum
+hugeEnum_VALUE_0471 = HugeEnum 471
+
+hugeEnum_VALUE_0472 :: HugeEnum
+hugeEnum_VALUE_0472 = HugeEnum 472
+
+hugeEnum_VALUE_0473 :: HugeEnum
+hugeEnum_VALUE_0473 = HugeEnum 473
+
+hugeEnum_VALUE_0474 :: HugeEnum
+hugeEnum_VALUE_0474 = HugeEnum 474
+
+hugeEnum_VALUE_0475 :: HugeEnum
+hugeEnum_VALUE_0475 = HugeEnum 475
+
+hugeEnum_VALUE_0476 :: HugeEnum
+hugeEnum_VALUE_0476 = HugeEnum 476
+
+hugeEnum_VALUE_0477 :: HugeEnum
+hugeEnum_VALUE_0477 = HugeEnum 477
+
+hugeEnum_VALUE_0478 :: HugeEnum
+hugeEnum_VALUE_0478 = HugeEnum 478
+
+hugeEnum_VALUE_0479 :: HugeEnum
+hugeEnum_VALUE_0479 = HugeEnum 479
+
+hugeEnum_VALUE_0480 :: HugeEnum
+hugeEnum_VALUE_0480 = HugeEnum 480
+
+hugeEnum_VALUE_0481 :: HugeEnum
+hugeEnum_VALUE_0481 = HugeEnum 481
+
+hugeEnum_VALUE_0482 :: HugeEnum
+hugeEnum_VALUE_0482 = HugeEnum 482
+
+hugeEnum_VALUE_0483 :: HugeEnum
+hugeEnum_VALUE_0483 = HugeEnum 483
+
+hugeEnum_VALUE_0484 :: HugeEnum
+hugeEnum_VALUE_0484 = HugeEnum 484
+
+hugeEnum_VALUE_0485 :: HugeEnum
+hugeEnum_VALUE_0485 = HugeEnum 485
+
+hugeEnum_VALUE_0486 :: HugeEnum
+hugeEnum_VALUE_0486 = HugeEnum 486
+
+hugeEnum_VALUE_0487 :: HugeEnum
+hugeEnum_VALUE_0487 = HugeEnum 487
+
+hugeEnum_VALUE_0488 :: HugeEnum
+hugeEnum_VALUE_0488 = HugeEnum 488
+
+hugeEnum_VALUE_0489 :: HugeEnum
+hugeEnum_VALUE_0489 = HugeEnum 489
+
+hugeEnum_VALUE_0490 :: HugeEnum
+hugeEnum_VALUE_0490 = HugeEnum 490
+
+hugeEnum_VALUE_0491 :: HugeEnum
+hugeEnum_VALUE_0491 = HugeEnum 491
+
+hugeEnum_VALUE_0492 :: HugeEnum
+hugeEnum_VALUE_0492 = HugeEnum 492
+
+hugeEnum_VALUE_0493 :: HugeEnum
+hugeEnum_VALUE_0493 = HugeEnum 493
+
+hugeEnum_VALUE_0494 :: HugeEnum
+hugeEnum_VALUE_0494 = HugeEnum 494
+
+hugeEnum_VALUE_0495 :: HugeEnum
+hugeEnum_VALUE_0495 = HugeEnum 495
+
+hugeEnum_VALUE_0496 :: HugeEnum
+hugeEnum_VALUE_0496 = HugeEnum 496
+
+hugeEnum_VALUE_0497 :: HugeEnum
+hugeEnum_VALUE_0497 = HugeEnum 497
+
+hugeEnum_VALUE_0498 :: HugeEnum
+hugeEnum_VALUE_0498 = HugeEnum 498
+
+hugeEnum_VALUE_0499 :: HugeEnum
+hugeEnum_VALUE_0499 = HugeEnum 499
+
+hugeEnum_VALUE_0500 :: HugeEnum
+hugeEnum_VALUE_0500 = HugeEnum 500
+
+hugeEnum_VALUE_0501 :: HugeEnum
+hugeEnum_VALUE_0501 = HugeEnum 501
+
+hugeEnum_VALUE_0502 :: HugeEnum
+hugeEnum_VALUE_0502 = HugeEnum 502
+
+hugeEnum_VALUE_0503 :: HugeEnum
+hugeEnum_VALUE_0503 = HugeEnum 503
+
+hugeEnum_VALUE_0504 :: HugeEnum
+hugeEnum_VALUE_0504 = HugeEnum 504
+
+hugeEnum_VALUE_0505 :: HugeEnum
+hugeEnum_VALUE_0505 = HugeEnum 505
+
+hugeEnum_VALUE_0506 :: HugeEnum
+hugeEnum_VALUE_0506 = HugeEnum 506
+
+hugeEnum_VALUE_0507 :: HugeEnum
+hugeEnum_VALUE_0507 = HugeEnum 507
+
+hugeEnum_VALUE_0508 :: HugeEnum
+hugeEnum_VALUE_0508 = HugeEnum 508
+
+hugeEnum_VALUE_0509 :: HugeEnum
+hugeEnum_VALUE_0509 = HugeEnum 509
+
+hugeEnum_VALUE_0510 :: HugeEnum
+hugeEnum_VALUE_0510 = HugeEnum 510
+
+hugeEnum_VALUE_0511 :: HugeEnum
+hugeEnum_VALUE_0511 = HugeEnum 511
+
+hugeEnum_VALUE_0512 :: HugeEnum
+hugeEnum_VALUE_0512 = HugeEnum 512
+
+hugeEnum_VALUE_0513 :: HugeEnum
+hugeEnum_VALUE_0513 = HugeEnum 513
+
+hugeEnum_VALUE_0514 :: HugeEnum
+hugeEnum_VALUE_0514 = HugeEnum 514
+
+hugeEnum_VALUE_0515 :: HugeEnum
+hugeEnum_VALUE_0515 = HugeEnum 515
+
+hugeEnum_VALUE_0516 :: HugeEnum
+hugeEnum_VALUE_0516 = HugeEnum 516
+
+hugeEnum_VALUE_0517 :: HugeEnum
+hugeEnum_VALUE_0517 = HugeEnum 517
+
+hugeEnum_VALUE_0518 :: HugeEnum
+hugeEnum_VALUE_0518 = HugeEnum 518
+
+hugeEnum_VALUE_0519 :: HugeEnum
+hugeEnum_VALUE_0519 = HugeEnum 519
+
+hugeEnum_VALUE_0520 :: HugeEnum
+hugeEnum_VALUE_0520 = HugeEnum 520
+
+hugeEnum_VALUE_0521 :: HugeEnum
+hugeEnum_VALUE_0521 = HugeEnum 521
+
+hugeEnum_VALUE_0522 :: HugeEnum
+hugeEnum_VALUE_0522 = HugeEnum 522
+
+hugeEnum_VALUE_0523 :: HugeEnum
+hugeEnum_VALUE_0523 = HugeEnum 523
+
+hugeEnum_VALUE_0524 :: HugeEnum
+hugeEnum_VALUE_0524 = HugeEnum 524
+
+hugeEnum_VALUE_0525 :: HugeEnum
+hugeEnum_VALUE_0525 = HugeEnum 525
+
+hugeEnum_VALUE_0526 :: HugeEnum
+hugeEnum_VALUE_0526 = HugeEnum 526
+
+hugeEnum_VALUE_0527 :: HugeEnum
+hugeEnum_VALUE_0527 = HugeEnum 527
+
+hugeEnum_VALUE_0528 :: HugeEnum
+hugeEnum_VALUE_0528 = HugeEnum 528
+
+hugeEnum_VALUE_0529 :: HugeEnum
+hugeEnum_VALUE_0529 = HugeEnum 529
+
+hugeEnum_VALUE_0530 :: HugeEnum
+hugeEnum_VALUE_0530 = HugeEnum 530
+
+hugeEnum_VALUE_0531 :: HugeEnum
+hugeEnum_VALUE_0531 = HugeEnum 531
+
+hugeEnum_VALUE_0532 :: HugeEnum
+hugeEnum_VALUE_0532 = HugeEnum 532
+
+hugeEnum_VALUE_0533 :: HugeEnum
+hugeEnum_VALUE_0533 = HugeEnum 533
+
+hugeEnum_VALUE_0534 :: HugeEnum
+hugeEnum_VALUE_0534 = HugeEnum 534
+
+hugeEnum_VALUE_0535 :: HugeEnum
+hugeEnum_VALUE_0535 = HugeEnum 535
+
+hugeEnum_VALUE_0536 :: HugeEnum
+hugeEnum_VALUE_0536 = HugeEnum 536
+
+hugeEnum_VALUE_0537 :: HugeEnum
+hugeEnum_VALUE_0537 = HugeEnum 537
+
+hugeEnum_VALUE_0538 :: HugeEnum
+hugeEnum_VALUE_0538 = HugeEnum 538
+
+hugeEnum_VALUE_0539 :: HugeEnum
+hugeEnum_VALUE_0539 = HugeEnum 539
+
+hugeEnum_VALUE_0540 :: HugeEnum
+hugeEnum_VALUE_0540 = HugeEnum 540
+
+hugeEnum_VALUE_0541 :: HugeEnum
+hugeEnum_VALUE_0541 = HugeEnum 541
+
+hugeEnum_VALUE_0542 :: HugeEnum
+hugeEnum_VALUE_0542 = HugeEnum 542
+
+hugeEnum_VALUE_0543 :: HugeEnum
+hugeEnum_VALUE_0543 = HugeEnum 543
+
+hugeEnum_VALUE_0544 :: HugeEnum
+hugeEnum_VALUE_0544 = HugeEnum 544
+
+hugeEnum_VALUE_0545 :: HugeEnum
+hugeEnum_VALUE_0545 = HugeEnum 545
+
+hugeEnum_VALUE_0546 :: HugeEnum
+hugeEnum_VALUE_0546 = HugeEnum 546
+
+hugeEnum_VALUE_0547 :: HugeEnum
+hugeEnum_VALUE_0547 = HugeEnum 547
+
+hugeEnum_VALUE_0548 :: HugeEnum
+hugeEnum_VALUE_0548 = HugeEnum 548
+
+hugeEnum_VALUE_0549 :: HugeEnum
+hugeEnum_VALUE_0549 = HugeEnum 549
+
+hugeEnum_VALUE_0550 :: HugeEnum
+hugeEnum_VALUE_0550 = HugeEnum 550
+
+hugeEnum_VALUE_0551 :: HugeEnum
+hugeEnum_VALUE_0551 = HugeEnum 551
+
+hugeEnum_VALUE_0552 :: HugeEnum
+hugeEnum_VALUE_0552 = HugeEnum 552
+
+hugeEnum_VALUE_0553 :: HugeEnum
+hugeEnum_VALUE_0553 = HugeEnum 553
+
+hugeEnum_VALUE_0554 :: HugeEnum
+hugeEnum_VALUE_0554 = HugeEnum 554
+
+hugeEnum_VALUE_0555 :: HugeEnum
+hugeEnum_VALUE_0555 = HugeEnum 555
+
+hugeEnum_VALUE_0556 :: HugeEnum
+hugeEnum_VALUE_0556 = HugeEnum 556
+
+hugeEnum_VALUE_0557 :: HugeEnum
+hugeEnum_VALUE_0557 = HugeEnum 557
+
+hugeEnum_VALUE_0558 :: HugeEnum
+hugeEnum_VALUE_0558 = HugeEnum 558
+
+hugeEnum_VALUE_0559 :: HugeEnum
+hugeEnum_VALUE_0559 = HugeEnum 559
+
+hugeEnum_VALUE_0560 :: HugeEnum
+hugeEnum_VALUE_0560 = HugeEnum 560
+
+hugeEnum_VALUE_0561 :: HugeEnum
+hugeEnum_VALUE_0561 = HugeEnum 561
+
+hugeEnum_VALUE_0562 :: HugeEnum
+hugeEnum_VALUE_0562 = HugeEnum 562
+
+hugeEnum_VALUE_0563 :: HugeEnum
+hugeEnum_VALUE_0563 = HugeEnum 563
+
+hugeEnum_VALUE_0564 :: HugeEnum
+hugeEnum_VALUE_0564 = HugeEnum 564
+
+hugeEnum_VALUE_0565 :: HugeEnum
+hugeEnum_VALUE_0565 = HugeEnum 565
+
+hugeEnum_VALUE_0566 :: HugeEnum
+hugeEnum_VALUE_0566 = HugeEnum 566
+
+hugeEnum_VALUE_0567 :: HugeEnum
+hugeEnum_VALUE_0567 = HugeEnum 567
+
+hugeEnum_VALUE_0568 :: HugeEnum
+hugeEnum_VALUE_0568 = HugeEnum 568
+
+hugeEnum_VALUE_0569 :: HugeEnum
+hugeEnum_VALUE_0569 = HugeEnum 569
+
+hugeEnum_VALUE_0570 :: HugeEnum
+hugeEnum_VALUE_0570 = HugeEnum 570
+
+hugeEnum_VALUE_0571 :: HugeEnum
+hugeEnum_VALUE_0571 = HugeEnum 571
+
+hugeEnum_VALUE_0572 :: HugeEnum
+hugeEnum_VALUE_0572 = HugeEnum 572
+
+hugeEnum_VALUE_0573 :: HugeEnum
+hugeEnum_VALUE_0573 = HugeEnum 573
+
+hugeEnum_VALUE_0574 :: HugeEnum
+hugeEnum_VALUE_0574 = HugeEnum 574
+
+hugeEnum_VALUE_0575 :: HugeEnum
+hugeEnum_VALUE_0575 = HugeEnum 575
+
+hugeEnum_VALUE_0576 :: HugeEnum
+hugeEnum_VALUE_0576 = HugeEnum 576
+
+hugeEnum_VALUE_0577 :: HugeEnum
+hugeEnum_VALUE_0577 = HugeEnum 577
+
+hugeEnum_VALUE_0578 :: HugeEnum
+hugeEnum_VALUE_0578 = HugeEnum 578
+
+hugeEnum_VALUE_0579 :: HugeEnum
+hugeEnum_VALUE_0579 = HugeEnum 579
+
+hugeEnum_VALUE_0580 :: HugeEnum
+hugeEnum_VALUE_0580 = HugeEnum 580
+
+hugeEnum_VALUE_0581 :: HugeEnum
+hugeEnum_VALUE_0581 = HugeEnum 581
+
+hugeEnum_VALUE_0582 :: HugeEnum
+hugeEnum_VALUE_0582 = HugeEnum 582
+
+hugeEnum_VALUE_0583 :: HugeEnum
+hugeEnum_VALUE_0583 = HugeEnum 583
+
+hugeEnum_VALUE_0584 :: HugeEnum
+hugeEnum_VALUE_0584 = HugeEnum 584
+
+hugeEnum_VALUE_0585 :: HugeEnum
+hugeEnum_VALUE_0585 = HugeEnum 585
+
+hugeEnum_VALUE_0586 :: HugeEnum
+hugeEnum_VALUE_0586 = HugeEnum 586
+
+hugeEnum_VALUE_0587 :: HugeEnum
+hugeEnum_VALUE_0587 = HugeEnum 587
+
+hugeEnum_VALUE_0588 :: HugeEnum
+hugeEnum_VALUE_0588 = HugeEnum 588
+
+hugeEnum_VALUE_0589 :: HugeEnum
+hugeEnum_VALUE_0589 = HugeEnum 589
+
+hugeEnum_VALUE_0590 :: HugeEnum
+hugeEnum_VALUE_0590 = HugeEnum 590
+
+hugeEnum_VALUE_0591 :: HugeEnum
+hugeEnum_VALUE_0591 = HugeEnum 591
+
+hugeEnum_VALUE_0592 :: HugeEnum
+hugeEnum_VALUE_0592 = HugeEnum 592
+
+hugeEnum_VALUE_0593 :: HugeEnum
+hugeEnum_VALUE_0593 = HugeEnum 593
+
+hugeEnum_VALUE_0594 :: HugeEnum
+hugeEnum_VALUE_0594 = HugeEnum 594
+
+hugeEnum_VALUE_0595 :: HugeEnum
+hugeEnum_VALUE_0595 = HugeEnum 595
+
+hugeEnum_VALUE_0596 :: HugeEnum
+hugeEnum_VALUE_0596 = HugeEnum 596
+
+hugeEnum_VALUE_0597 :: HugeEnum
+hugeEnum_VALUE_0597 = HugeEnum 597
+
+hugeEnum_VALUE_0598 :: HugeEnum
+hugeEnum_VALUE_0598 = HugeEnum 598
+
+hugeEnum_VALUE_0599 :: HugeEnum
+hugeEnum_VALUE_0599 = HugeEnum 599
+
+hugeEnum_VALUE_0600 :: HugeEnum
+hugeEnum_VALUE_0600 = HugeEnum 600
+
+hugeEnum_VALUE_0601 :: HugeEnum
+hugeEnum_VALUE_0601 = HugeEnum 601
+
+hugeEnum_VALUE_0602 :: HugeEnum
+hugeEnum_VALUE_0602 = HugeEnum 602
+
+hugeEnum_VALUE_0603 :: HugeEnum
+hugeEnum_VALUE_0603 = HugeEnum 603
+
+hugeEnum_VALUE_0604 :: HugeEnum
+hugeEnum_VALUE_0604 = HugeEnum 604
+
+hugeEnum_VALUE_0605 :: HugeEnum
+hugeEnum_VALUE_0605 = HugeEnum 605
+
+hugeEnum_VALUE_0606 :: HugeEnum
+hugeEnum_VALUE_0606 = HugeEnum 606
+
+hugeEnum_VALUE_0607 :: HugeEnum
+hugeEnum_VALUE_0607 = HugeEnum 607
+
+hugeEnum_VALUE_0608 :: HugeEnum
+hugeEnum_VALUE_0608 = HugeEnum 608
+
+hugeEnum_VALUE_0609 :: HugeEnum
+hugeEnum_VALUE_0609 = HugeEnum 609
+
+hugeEnum_VALUE_0610 :: HugeEnum
+hugeEnum_VALUE_0610 = HugeEnum 610
+
+hugeEnum_VALUE_0611 :: HugeEnum
+hugeEnum_VALUE_0611 = HugeEnum 611
+
+hugeEnum_VALUE_0612 :: HugeEnum
+hugeEnum_VALUE_0612 = HugeEnum 612
+
+hugeEnum_VALUE_0613 :: HugeEnum
+hugeEnum_VALUE_0613 = HugeEnum 613
+
+hugeEnum_VALUE_0614 :: HugeEnum
+hugeEnum_VALUE_0614 = HugeEnum 614
+
+hugeEnum_VALUE_0615 :: HugeEnum
+hugeEnum_VALUE_0615 = HugeEnum 615
+
+hugeEnum_VALUE_0616 :: HugeEnum
+hugeEnum_VALUE_0616 = HugeEnum 616
+
+hugeEnum_VALUE_0617 :: HugeEnum
+hugeEnum_VALUE_0617 = HugeEnum 617
+
+hugeEnum_VALUE_0618 :: HugeEnum
+hugeEnum_VALUE_0618 = HugeEnum 618
+
+hugeEnum_VALUE_0619 :: HugeEnum
+hugeEnum_VALUE_0619 = HugeEnum 619
+
+hugeEnum_VALUE_0620 :: HugeEnum
+hugeEnum_VALUE_0620 = HugeEnum 620
+
+hugeEnum_VALUE_0621 :: HugeEnum
+hugeEnum_VALUE_0621 = HugeEnum 621
+
+hugeEnum_VALUE_0622 :: HugeEnum
+hugeEnum_VALUE_0622 = HugeEnum 622
+
+hugeEnum_VALUE_0623 :: HugeEnum
+hugeEnum_VALUE_0623 = HugeEnum 623
+
+hugeEnum_VALUE_0624 :: HugeEnum
+hugeEnum_VALUE_0624 = HugeEnum 624
+
+hugeEnum_VALUE_0625 :: HugeEnum
+hugeEnum_VALUE_0625 = HugeEnum 625
+
+hugeEnum_VALUE_0626 :: HugeEnum
+hugeEnum_VALUE_0626 = HugeEnum 626
+
+hugeEnum_VALUE_0627 :: HugeEnum
+hugeEnum_VALUE_0627 = HugeEnum 627
+
+hugeEnum_VALUE_0628 :: HugeEnum
+hugeEnum_VALUE_0628 = HugeEnum 628
+
+hugeEnum_VALUE_0629 :: HugeEnum
+hugeEnum_VALUE_0629 = HugeEnum 629
+
+hugeEnum_VALUE_0630 :: HugeEnum
+hugeEnum_VALUE_0630 = HugeEnum 630
+
+hugeEnum_VALUE_0631 :: HugeEnum
+hugeEnum_VALUE_0631 = HugeEnum 631
+
+hugeEnum_VALUE_0632 :: HugeEnum
+hugeEnum_VALUE_0632 = HugeEnum 632
+
+hugeEnum_VALUE_0633 :: HugeEnum
+hugeEnum_VALUE_0633 = HugeEnum 633
+
+hugeEnum_VALUE_0634 :: HugeEnum
+hugeEnum_VALUE_0634 = HugeEnum 634
+
+hugeEnum_VALUE_0635 :: HugeEnum
+hugeEnum_VALUE_0635 = HugeEnum 635
+
+hugeEnum_VALUE_0636 :: HugeEnum
+hugeEnum_VALUE_0636 = HugeEnum 636
+
+hugeEnum_VALUE_0637 :: HugeEnum
+hugeEnum_VALUE_0637 = HugeEnum 637
+
+hugeEnum_VALUE_0638 :: HugeEnum
+hugeEnum_VALUE_0638 = HugeEnum 638
+
+hugeEnum_VALUE_0639 :: HugeEnum
+hugeEnum_VALUE_0639 = HugeEnum 639
+
+hugeEnum_VALUE_0640 :: HugeEnum
+hugeEnum_VALUE_0640 = HugeEnum 640
+
+hugeEnum_VALUE_0641 :: HugeEnum
+hugeEnum_VALUE_0641 = HugeEnum 641
+
+hugeEnum_VALUE_0642 :: HugeEnum
+hugeEnum_VALUE_0642 = HugeEnum 642
+
+hugeEnum_VALUE_0643 :: HugeEnum
+hugeEnum_VALUE_0643 = HugeEnum 643
+
+hugeEnum_VALUE_0644 :: HugeEnum
+hugeEnum_VALUE_0644 = HugeEnum 644
+
+hugeEnum_VALUE_0645 :: HugeEnum
+hugeEnum_VALUE_0645 = HugeEnum 645
+
+hugeEnum_VALUE_0646 :: HugeEnum
+hugeEnum_VALUE_0646 = HugeEnum 646
+
+hugeEnum_VALUE_0647 :: HugeEnum
+hugeEnum_VALUE_0647 = HugeEnum 647
+
+hugeEnum_VALUE_0648 :: HugeEnum
+hugeEnum_VALUE_0648 = HugeEnum 648
+
+hugeEnum_VALUE_0649 :: HugeEnum
+hugeEnum_VALUE_0649 = HugeEnum 649
+
+hugeEnum_VALUE_0650 :: HugeEnum
+hugeEnum_VALUE_0650 = HugeEnum 650
+
+hugeEnum_VALUE_0651 :: HugeEnum
+hugeEnum_VALUE_0651 = HugeEnum 651
+
+hugeEnum_VALUE_0652 :: HugeEnum
+hugeEnum_VALUE_0652 = HugeEnum 652
+
+hugeEnum_VALUE_0653 :: HugeEnum
+hugeEnum_VALUE_0653 = HugeEnum 653
+
+hugeEnum_VALUE_0654 :: HugeEnum
+hugeEnum_VALUE_0654 = HugeEnum 654
+
+hugeEnum_VALUE_0655 :: HugeEnum
+hugeEnum_VALUE_0655 = HugeEnum 655
+
+hugeEnum_VALUE_0656 :: HugeEnum
+hugeEnum_VALUE_0656 = HugeEnum 656
+
+hugeEnum_VALUE_0657 :: HugeEnum
+hugeEnum_VALUE_0657 = HugeEnum 657
+
+hugeEnum_VALUE_0658 :: HugeEnum
+hugeEnum_VALUE_0658 = HugeEnum 658
+
+hugeEnum_VALUE_0659 :: HugeEnum
+hugeEnum_VALUE_0659 = HugeEnum 659
+
+hugeEnum_VALUE_0660 :: HugeEnum
+hugeEnum_VALUE_0660 = HugeEnum 660
+
+hugeEnum_VALUE_0661 :: HugeEnum
+hugeEnum_VALUE_0661 = HugeEnum 661
+
+hugeEnum_VALUE_0662 :: HugeEnum
+hugeEnum_VALUE_0662 = HugeEnum 662
+
+hugeEnum_VALUE_0663 :: HugeEnum
+hugeEnum_VALUE_0663 = HugeEnum 663
+
+hugeEnum_VALUE_0664 :: HugeEnum
+hugeEnum_VALUE_0664 = HugeEnum 664
+
+hugeEnum_VALUE_0665 :: HugeEnum
+hugeEnum_VALUE_0665 = HugeEnum 665
+
+hugeEnum_VALUE_0666 :: HugeEnum
+hugeEnum_VALUE_0666 = HugeEnum 666
+
+hugeEnum_VALUE_0667 :: HugeEnum
+hugeEnum_VALUE_0667 = HugeEnum 667
+
+hugeEnum_VALUE_0668 :: HugeEnum
+hugeEnum_VALUE_0668 = HugeEnum 668
+
+hugeEnum_VALUE_0669 :: HugeEnum
+hugeEnum_VALUE_0669 = HugeEnum 669
+
+hugeEnum_VALUE_0670 :: HugeEnum
+hugeEnum_VALUE_0670 = HugeEnum 670
+
+hugeEnum_VALUE_0671 :: HugeEnum
+hugeEnum_VALUE_0671 = HugeEnum 671
+
+hugeEnum_VALUE_0672 :: HugeEnum
+hugeEnum_VALUE_0672 = HugeEnum 672
+
+hugeEnum_VALUE_0673 :: HugeEnum
+hugeEnum_VALUE_0673 = HugeEnum 673
+
+hugeEnum_VALUE_0674 :: HugeEnum
+hugeEnum_VALUE_0674 = HugeEnum 674
+
+hugeEnum_VALUE_0675 :: HugeEnum
+hugeEnum_VALUE_0675 = HugeEnum 675
+
+hugeEnum_VALUE_0676 :: HugeEnum
+hugeEnum_VALUE_0676 = HugeEnum 676
+
+hugeEnum_VALUE_0677 :: HugeEnum
+hugeEnum_VALUE_0677 = HugeEnum 677
+
+hugeEnum_VALUE_0678 :: HugeEnum
+hugeEnum_VALUE_0678 = HugeEnum 678
+
+hugeEnum_VALUE_0679 :: HugeEnum
+hugeEnum_VALUE_0679 = HugeEnum 679
+
+hugeEnum_VALUE_0680 :: HugeEnum
+hugeEnum_VALUE_0680 = HugeEnum 680
+
+hugeEnum_VALUE_0681 :: HugeEnum
+hugeEnum_VALUE_0681 = HugeEnum 681
+
+hugeEnum_VALUE_0682 :: HugeEnum
+hugeEnum_VALUE_0682 = HugeEnum 682
+
+hugeEnum_VALUE_0683 :: HugeEnum
+hugeEnum_VALUE_0683 = HugeEnum 683
+
+hugeEnum_VALUE_0684 :: HugeEnum
+hugeEnum_VALUE_0684 = HugeEnum 684
+
+hugeEnum_VALUE_0685 :: HugeEnum
+hugeEnum_VALUE_0685 = HugeEnum 685
+
+hugeEnum_VALUE_0686 :: HugeEnum
+hugeEnum_VALUE_0686 = HugeEnum 686
+
+hugeEnum_VALUE_0687 :: HugeEnum
+hugeEnum_VALUE_0687 = HugeEnum 687
+
+hugeEnum_VALUE_0688 :: HugeEnum
+hugeEnum_VALUE_0688 = HugeEnum 688
+
+hugeEnum_VALUE_0689 :: HugeEnum
+hugeEnum_VALUE_0689 = HugeEnum 689
+
+hugeEnum_VALUE_0690 :: HugeEnum
+hugeEnum_VALUE_0690 = HugeEnum 690
+
+hugeEnum_VALUE_0691 :: HugeEnum
+hugeEnum_VALUE_0691 = HugeEnum 691
+
+hugeEnum_VALUE_0692 :: HugeEnum
+hugeEnum_VALUE_0692 = HugeEnum 692
+
+hugeEnum_VALUE_0693 :: HugeEnum
+hugeEnum_VALUE_0693 = HugeEnum 693
+
+hugeEnum_VALUE_0694 :: HugeEnum
+hugeEnum_VALUE_0694 = HugeEnum 694
+
+hugeEnum_VALUE_0695 :: HugeEnum
+hugeEnum_VALUE_0695 = HugeEnum 695
+
+hugeEnum_VALUE_0696 :: HugeEnum
+hugeEnum_VALUE_0696 = HugeEnum 696
+
+hugeEnum_VALUE_0697 :: HugeEnum
+hugeEnum_VALUE_0697 = HugeEnum 697
+
+hugeEnum_VALUE_0698 :: HugeEnum
+hugeEnum_VALUE_0698 = HugeEnum 698
+
+hugeEnum_VALUE_0699 :: HugeEnum
+hugeEnum_VALUE_0699 = HugeEnum 699
+
+hugeEnum_VALUE_0700 :: HugeEnum
+hugeEnum_VALUE_0700 = HugeEnum 700
+
+hugeEnum_VALUE_0701 :: HugeEnum
+hugeEnum_VALUE_0701 = HugeEnum 701
+
+hugeEnum_VALUE_0702 :: HugeEnum
+hugeEnum_VALUE_0702 = HugeEnum 702
+
+hugeEnum_VALUE_0703 :: HugeEnum
+hugeEnum_VALUE_0703 = HugeEnum 703
+
+hugeEnum_VALUE_0704 :: HugeEnum
+hugeEnum_VALUE_0704 = HugeEnum 704
+
+hugeEnum_VALUE_0705 :: HugeEnum
+hugeEnum_VALUE_0705 = HugeEnum 705
+
+hugeEnum_VALUE_0706 :: HugeEnum
+hugeEnum_VALUE_0706 = HugeEnum 706
+
+hugeEnum_VALUE_0707 :: HugeEnum
+hugeEnum_VALUE_0707 = HugeEnum 707
+
+hugeEnum_VALUE_0708 :: HugeEnum
+hugeEnum_VALUE_0708 = HugeEnum 708
+
+hugeEnum_VALUE_0709 :: HugeEnum
+hugeEnum_VALUE_0709 = HugeEnum 709
+
+hugeEnum_VALUE_0710 :: HugeEnum
+hugeEnum_VALUE_0710 = HugeEnum 710
+
+hugeEnum_VALUE_0711 :: HugeEnum
+hugeEnum_VALUE_0711 = HugeEnum 711
+
+hugeEnum_VALUE_0712 :: HugeEnum
+hugeEnum_VALUE_0712 = HugeEnum 712
+
+hugeEnum_VALUE_0713 :: HugeEnum
+hugeEnum_VALUE_0713 = HugeEnum 713
+
+hugeEnum_VALUE_0714 :: HugeEnum
+hugeEnum_VALUE_0714 = HugeEnum 714
+
+hugeEnum_VALUE_0715 :: HugeEnum
+hugeEnum_VALUE_0715 = HugeEnum 715
+
+hugeEnum_VALUE_0716 :: HugeEnum
+hugeEnum_VALUE_0716 = HugeEnum 716
+
+hugeEnum_VALUE_0717 :: HugeEnum
+hugeEnum_VALUE_0717 = HugeEnum 717
+
+hugeEnum_VALUE_0718 :: HugeEnum
+hugeEnum_VALUE_0718 = HugeEnum 718
+
+hugeEnum_VALUE_0719 :: HugeEnum
+hugeEnum_VALUE_0719 = HugeEnum 719
+
+hugeEnum_VALUE_0720 :: HugeEnum
+hugeEnum_VALUE_0720 = HugeEnum 720
+
+hugeEnum_VALUE_0721 :: HugeEnum
+hugeEnum_VALUE_0721 = HugeEnum 721
+
+hugeEnum_VALUE_0722 :: HugeEnum
+hugeEnum_VALUE_0722 = HugeEnum 722
+
+hugeEnum_VALUE_0723 :: HugeEnum
+hugeEnum_VALUE_0723 = HugeEnum 723
+
+hugeEnum_VALUE_0724 :: HugeEnum
+hugeEnum_VALUE_0724 = HugeEnum 724
+
+hugeEnum_VALUE_0725 :: HugeEnum
+hugeEnum_VALUE_0725 = HugeEnum 725
+
+hugeEnum_VALUE_0726 :: HugeEnum
+hugeEnum_VALUE_0726 = HugeEnum 726
+
+hugeEnum_VALUE_0727 :: HugeEnum
+hugeEnum_VALUE_0727 = HugeEnum 727
+
+hugeEnum_VALUE_0728 :: HugeEnum
+hugeEnum_VALUE_0728 = HugeEnum 728
+
+hugeEnum_VALUE_0729 :: HugeEnum
+hugeEnum_VALUE_0729 = HugeEnum 729
+
+hugeEnum_VALUE_0730 :: HugeEnum
+hugeEnum_VALUE_0730 = HugeEnum 730
+
+hugeEnum_VALUE_0731 :: HugeEnum
+hugeEnum_VALUE_0731 = HugeEnum 731
+
+hugeEnum_VALUE_0732 :: HugeEnum
+hugeEnum_VALUE_0732 = HugeEnum 732
+
+hugeEnum_VALUE_0733 :: HugeEnum
+hugeEnum_VALUE_0733 = HugeEnum 733
+
+hugeEnum_VALUE_0734 :: HugeEnum
+hugeEnum_VALUE_0734 = HugeEnum 734
+
+hugeEnum_VALUE_0735 :: HugeEnum
+hugeEnum_VALUE_0735 = HugeEnum 735
+
+hugeEnum_VALUE_0736 :: HugeEnum
+hugeEnum_VALUE_0736 = HugeEnum 736
+
+hugeEnum_VALUE_0737 :: HugeEnum
+hugeEnum_VALUE_0737 = HugeEnum 737
+
+hugeEnum_VALUE_0738 :: HugeEnum
+hugeEnum_VALUE_0738 = HugeEnum 738
+
+hugeEnum_VALUE_0739 :: HugeEnum
+hugeEnum_VALUE_0739 = HugeEnum 739
+
+hugeEnum_VALUE_0740 :: HugeEnum
+hugeEnum_VALUE_0740 = HugeEnum 740
+
+hugeEnum_VALUE_0741 :: HugeEnum
+hugeEnum_VALUE_0741 = HugeEnum 741
+
+hugeEnum_VALUE_0742 :: HugeEnum
+hugeEnum_VALUE_0742 = HugeEnum 742
+
+hugeEnum_VALUE_0743 :: HugeEnum
+hugeEnum_VALUE_0743 = HugeEnum 743
+
+hugeEnum_VALUE_0744 :: HugeEnum
+hugeEnum_VALUE_0744 = HugeEnum 744
+
+hugeEnum_VALUE_0745 :: HugeEnum
+hugeEnum_VALUE_0745 = HugeEnum 745
+
+hugeEnum_VALUE_0746 :: HugeEnum
+hugeEnum_VALUE_0746 = HugeEnum 746
+
+hugeEnum_VALUE_0747 :: HugeEnum
+hugeEnum_VALUE_0747 = HugeEnum 747
+
+hugeEnum_VALUE_0748 :: HugeEnum
+hugeEnum_VALUE_0748 = HugeEnum 748
+
+hugeEnum_VALUE_0749 :: HugeEnum
+hugeEnum_VALUE_0749 = HugeEnum 749
+
+hugeEnum_VALUE_0750 :: HugeEnum
+hugeEnum_VALUE_0750 = HugeEnum 750
+
+hugeEnum_VALUE_0751 :: HugeEnum
+hugeEnum_VALUE_0751 = HugeEnum 751
+
+hugeEnum_VALUE_0752 :: HugeEnum
+hugeEnum_VALUE_0752 = HugeEnum 752
+
+hugeEnum_VALUE_0753 :: HugeEnum
+hugeEnum_VALUE_0753 = HugeEnum 753
+
+hugeEnum_VALUE_0754 :: HugeEnum
+hugeEnum_VALUE_0754 = HugeEnum 754
+
+hugeEnum_VALUE_0755 :: HugeEnum
+hugeEnum_VALUE_0755 = HugeEnum 755
+
+hugeEnum_VALUE_0756 :: HugeEnum
+hugeEnum_VALUE_0756 = HugeEnum 756
+
+hugeEnum_VALUE_0757 :: HugeEnum
+hugeEnum_VALUE_0757 = HugeEnum 757
+
+hugeEnum_VALUE_0758 :: HugeEnum
+hugeEnum_VALUE_0758 = HugeEnum 758
+
+hugeEnum_VALUE_0759 :: HugeEnum
+hugeEnum_VALUE_0759 = HugeEnum 759
+
+hugeEnum_VALUE_0760 :: HugeEnum
+hugeEnum_VALUE_0760 = HugeEnum 760
+
+hugeEnum_VALUE_0761 :: HugeEnum
+hugeEnum_VALUE_0761 = HugeEnum 761
+
+hugeEnum_VALUE_0762 :: HugeEnum
+hugeEnum_VALUE_0762 = HugeEnum 762
+
+hugeEnum_VALUE_0763 :: HugeEnum
+hugeEnum_VALUE_0763 = HugeEnum 763
+
+hugeEnum_VALUE_0764 :: HugeEnum
+hugeEnum_VALUE_0764 = HugeEnum 764
+
+hugeEnum_VALUE_0765 :: HugeEnum
+hugeEnum_VALUE_0765 = HugeEnum 765
+
+hugeEnum_VALUE_0766 :: HugeEnum
+hugeEnum_VALUE_0766 = HugeEnum 766
+
+hugeEnum_VALUE_0767 :: HugeEnum
+hugeEnum_VALUE_0767 = HugeEnum 767
+
+hugeEnum_VALUE_0768 :: HugeEnum
+hugeEnum_VALUE_0768 = HugeEnum 768
+
+hugeEnum_VALUE_0769 :: HugeEnum
+hugeEnum_VALUE_0769 = HugeEnum 769
+
+hugeEnum_VALUE_0770 :: HugeEnum
+hugeEnum_VALUE_0770 = HugeEnum 770
+
+hugeEnum_VALUE_0771 :: HugeEnum
+hugeEnum_VALUE_0771 = HugeEnum 771
+
+hugeEnum_VALUE_0772 :: HugeEnum
+hugeEnum_VALUE_0772 = HugeEnum 772
+
+hugeEnum_VALUE_0773 :: HugeEnum
+hugeEnum_VALUE_0773 = HugeEnum 773
+
+hugeEnum_VALUE_0774 :: HugeEnum
+hugeEnum_VALUE_0774 = HugeEnum 774
+
+hugeEnum_VALUE_0775 :: HugeEnum
+hugeEnum_VALUE_0775 = HugeEnum 775
+
+hugeEnum_VALUE_0776 :: HugeEnum
+hugeEnum_VALUE_0776 = HugeEnum 776
+
+hugeEnum_VALUE_0777 :: HugeEnum
+hugeEnum_VALUE_0777 = HugeEnum 777
+
+hugeEnum_VALUE_0778 :: HugeEnum
+hugeEnum_VALUE_0778 = HugeEnum 778
+
+hugeEnum_VALUE_0779 :: HugeEnum
+hugeEnum_VALUE_0779 = HugeEnum 779
+
+hugeEnum_VALUE_0780 :: HugeEnum
+hugeEnum_VALUE_0780 = HugeEnum 780
+
+hugeEnum_VALUE_0781 :: HugeEnum
+hugeEnum_VALUE_0781 = HugeEnum 781
+
+hugeEnum_VALUE_0782 :: HugeEnum
+hugeEnum_VALUE_0782 = HugeEnum 782
+
+hugeEnum_VALUE_0783 :: HugeEnum
+hugeEnum_VALUE_0783 = HugeEnum 783
+
+hugeEnum_VALUE_0784 :: HugeEnum
+hugeEnum_VALUE_0784 = HugeEnum 784
+
+hugeEnum_VALUE_0785 :: HugeEnum
+hugeEnum_VALUE_0785 = HugeEnum 785
+
+hugeEnum_VALUE_0786 :: HugeEnum
+hugeEnum_VALUE_0786 = HugeEnum 786
+
+hugeEnum_VALUE_0787 :: HugeEnum
+hugeEnum_VALUE_0787 = HugeEnum 787
+
+hugeEnum_VALUE_0788 :: HugeEnum
+hugeEnum_VALUE_0788 = HugeEnum 788
+
+hugeEnum_VALUE_0789 :: HugeEnum
+hugeEnum_VALUE_0789 = HugeEnum 789
+
+hugeEnum_VALUE_0790 :: HugeEnum
+hugeEnum_VALUE_0790 = HugeEnum 790
+
+hugeEnum_VALUE_0791 :: HugeEnum
+hugeEnum_VALUE_0791 = HugeEnum 791
+
+hugeEnum_VALUE_0792 :: HugeEnum
+hugeEnum_VALUE_0792 = HugeEnum 792
+
+hugeEnum_VALUE_0793 :: HugeEnum
+hugeEnum_VALUE_0793 = HugeEnum 793
+
+hugeEnum_VALUE_0794 :: HugeEnum
+hugeEnum_VALUE_0794 = HugeEnum 794
+
+hugeEnum_VALUE_0795 :: HugeEnum
+hugeEnum_VALUE_0795 = HugeEnum 795
+
+hugeEnum_VALUE_0796 :: HugeEnum
+hugeEnum_VALUE_0796 = HugeEnum 796
+
+hugeEnum_VALUE_0797 :: HugeEnum
+hugeEnum_VALUE_0797 = HugeEnum 797
+
+hugeEnum_VALUE_0798 :: HugeEnum
+hugeEnum_VALUE_0798 = HugeEnum 798
+
+hugeEnum_VALUE_0799 :: HugeEnum
+hugeEnum_VALUE_0799 = HugeEnum 799
+
+hugeEnum_VALUE_0800 :: HugeEnum
+hugeEnum_VALUE_0800 = HugeEnum 800
+
+hugeEnum_VALUE_0801 :: HugeEnum
+hugeEnum_VALUE_0801 = HugeEnum 801
+
+hugeEnum_VALUE_0802 :: HugeEnum
+hugeEnum_VALUE_0802 = HugeEnum 802
+
+hugeEnum_VALUE_0803 :: HugeEnum
+hugeEnum_VALUE_0803 = HugeEnum 803
+
+hugeEnum_VALUE_0804 :: HugeEnum
+hugeEnum_VALUE_0804 = HugeEnum 804
+
+hugeEnum_VALUE_0805 :: HugeEnum
+hugeEnum_VALUE_0805 = HugeEnum 805
+
+hugeEnum_VALUE_0806 :: HugeEnum
+hugeEnum_VALUE_0806 = HugeEnum 806
+
+hugeEnum_VALUE_0807 :: HugeEnum
+hugeEnum_VALUE_0807 = HugeEnum 807
+
+hugeEnum_VALUE_0808 :: HugeEnum
+hugeEnum_VALUE_0808 = HugeEnum 808
+
+hugeEnum_VALUE_0809 :: HugeEnum
+hugeEnum_VALUE_0809 = HugeEnum 809
+
+hugeEnum_VALUE_0810 :: HugeEnum
+hugeEnum_VALUE_0810 = HugeEnum 810
+
+hugeEnum_VALUE_0811 :: HugeEnum
+hugeEnum_VALUE_0811 = HugeEnum 811
+
+hugeEnum_VALUE_0812 :: HugeEnum
+hugeEnum_VALUE_0812 = HugeEnum 812
+
+hugeEnum_VALUE_0813 :: HugeEnum
+hugeEnum_VALUE_0813 = HugeEnum 813
+
+hugeEnum_VALUE_0814 :: HugeEnum
+hugeEnum_VALUE_0814 = HugeEnum 814
+
+hugeEnum_VALUE_0815 :: HugeEnum
+hugeEnum_VALUE_0815 = HugeEnum 815
+
+hugeEnum_VALUE_0816 :: HugeEnum
+hugeEnum_VALUE_0816 = HugeEnum 816
+
+hugeEnum_VALUE_0817 :: HugeEnum
+hugeEnum_VALUE_0817 = HugeEnum 817
+
+hugeEnum_VALUE_0818 :: HugeEnum
+hugeEnum_VALUE_0818 = HugeEnum 818
+
+hugeEnum_VALUE_0819 :: HugeEnum
+hugeEnum_VALUE_0819 = HugeEnum 819
+
+hugeEnum_VALUE_0820 :: HugeEnum
+hugeEnum_VALUE_0820 = HugeEnum 820
+
+hugeEnum_VALUE_0821 :: HugeEnum
+hugeEnum_VALUE_0821 = HugeEnum 821
+
+hugeEnum_VALUE_0822 :: HugeEnum
+hugeEnum_VALUE_0822 = HugeEnum 822
+
+hugeEnum_VALUE_0823 :: HugeEnum
+hugeEnum_VALUE_0823 = HugeEnum 823
+
+hugeEnum_VALUE_0824 :: HugeEnum
+hugeEnum_VALUE_0824 = HugeEnum 824
+
+hugeEnum_VALUE_0825 :: HugeEnum
+hugeEnum_VALUE_0825 = HugeEnum 825
+
+hugeEnum_VALUE_0826 :: HugeEnum
+hugeEnum_VALUE_0826 = HugeEnum 826
+
+hugeEnum_VALUE_0827 :: HugeEnum
+hugeEnum_VALUE_0827 = HugeEnum 827
+
+hugeEnum_VALUE_0828 :: HugeEnum
+hugeEnum_VALUE_0828 = HugeEnum 828
+
+hugeEnum_VALUE_0829 :: HugeEnum
+hugeEnum_VALUE_0829 = HugeEnum 829
+
+hugeEnum_VALUE_0830 :: HugeEnum
+hugeEnum_VALUE_0830 = HugeEnum 830
+
+hugeEnum_VALUE_0831 :: HugeEnum
+hugeEnum_VALUE_0831 = HugeEnum 831
+
+hugeEnum_VALUE_0832 :: HugeEnum
+hugeEnum_VALUE_0832 = HugeEnum 832
+
+hugeEnum_VALUE_0833 :: HugeEnum
+hugeEnum_VALUE_0833 = HugeEnum 833
+
+hugeEnum_VALUE_0834 :: HugeEnum
+hugeEnum_VALUE_0834 = HugeEnum 834
+
+hugeEnum_VALUE_0835 :: HugeEnum
+hugeEnum_VALUE_0835 = HugeEnum 835
+
+hugeEnum_VALUE_0836 :: HugeEnum
+hugeEnum_VALUE_0836 = HugeEnum 836
+
+hugeEnum_VALUE_0837 :: HugeEnum
+hugeEnum_VALUE_0837 = HugeEnum 837
+
+hugeEnum_VALUE_0838 :: HugeEnum
+hugeEnum_VALUE_0838 = HugeEnum 838
+
+hugeEnum_VALUE_0839 :: HugeEnum
+hugeEnum_VALUE_0839 = HugeEnum 839
+
+hugeEnum_VALUE_0840 :: HugeEnum
+hugeEnum_VALUE_0840 = HugeEnum 840
+
+hugeEnum_VALUE_0841 :: HugeEnum
+hugeEnum_VALUE_0841 = HugeEnum 841
+
+hugeEnum_VALUE_0842 :: HugeEnum
+hugeEnum_VALUE_0842 = HugeEnum 842
+
+hugeEnum_VALUE_0843 :: HugeEnum
+hugeEnum_VALUE_0843 = HugeEnum 843
+
+hugeEnum_VALUE_0844 :: HugeEnum
+hugeEnum_VALUE_0844 = HugeEnum 844
+
+hugeEnum_VALUE_0845 :: HugeEnum
+hugeEnum_VALUE_0845 = HugeEnum 845
+
+hugeEnum_VALUE_0846 :: HugeEnum
+hugeEnum_VALUE_0846 = HugeEnum 846
+
+hugeEnum_VALUE_0847 :: HugeEnum
+hugeEnum_VALUE_0847 = HugeEnum 847
+
+hugeEnum_VALUE_0848 :: HugeEnum
+hugeEnum_VALUE_0848 = HugeEnum 848
+
+hugeEnum_VALUE_0849 :: HugeEnum
+hugeEnum_VALUE_0849 = HugeEnum 849
+
+hugeEnum_VALUE_0850 :: HugeEnum
+hugeEnum_VALUE_0850 = HugeEnum 850
+
+hugeEnum_VALUE_0851 :: HugeEnum
+hugeEnum_VALUE_0851 = HugeEnum 851
+
+hugeEnum_VALUE_0852 :: HugeEnum
+hugeEnum_VALUE_0852 = HugeEnum 852
+
+hugeEnum_VALUE_0853 :: HugeEnum
+hugeEnum_VALUE_0853 = HugeEnum 853
+
+hugeEnum_VALUE_0854 :: HugeEnum
+hugeEnum_VALUE_0854 = HugeEnum 854
+
+hugeEnum_VALUE_0855 :: HugeEnum
+hugeEnum_VALUE_0855 = HugeEnum 855
+
+hugeEnum_VALUE_0856 :: HugeEnum
+hugeEnum_VALUE_0856 = HugeEnum 856
+
+hugeEnum_VALUE_0857 :: HugeEnum
+hugeEnum_VALUE_0857 = HugeEnum 857
+
+hugeEnum_VALUE_0858 :: HugeEnum
+hugeEnum_VALUE_0858 = HugeEnum 858
+
+hugeEnum_VALUE_0859 :: HugeEnum
+hugeEnum_VALUE_0859 = HugeEnum 859
+
+hugeEnum_VALUE_0860 :: HugeEnum
+hugeEnum_VALUE_0860 = HugeEnum 860
+
+hugeEnum_VALUE_0861 :: HugeEnum
+hugeEnum_VALUE_0861 = HugeEnum 861
+
+hugeEnum_VALUE_0862 :: HugeEnum
+hugeEnum_VALUE_0862 = HugeEnum 862
+
+hugeEnum_VALUE_0863 :: HugeEnum
+hugeEnum_VALUE_0863 = HugeEnum 863
+
+hugeEnum_VALUE_0864 :: HugeEnum
+hugeEnum_VALUE_0864 = HugeEnum 864
+
+hugeEnum_VALUE_0865 :: HugeEnum
+hugeEnum_VALUE_0865 = HugeEnum 865
+
+hugeEnum_VALUE_0866 :: HugeEnum
+hugeEnum_VALUE_0866 = HugeEnum 866
+
+hugeEnum_VALUE_0867 :: HugeEnum
+hugeEnum_VALUE_0867 = HugeEnum 867
+
+hugeEnum_VALUE_0868 :: HugeEnum
+hugeEnum_VALUE_0868 = HugeEnum 868
+
+hugeEnum_VALUE_0869 :: HugeEnum
+hugeEnum_VALUE_0869 = HugeEnum 869
+
+hugeEnum_VALUE_0870 :: HugeEnum
+hugeEnum_VALUE_0870 = HugeEnum 870
+
+hugeEnum_VALUE_0871 :: HugeEnum
+hugeEnum_VALUE_0871 = HugeEnum 871
+
+hugeEnum_VALUE_0872 :: HugeEnum
+hugeEnum_VALUE_0872 = HugeEnum 872
+
+hugeEnum_VALUE_0873 :: HugeEnum
+hugeEnum_VALUE_0873 = HugeEnum 873
+
+hugeEnum_VALUE_0874 :: HugeEnum
+hugeEnum_VALUE_0874 = HugeEnum 874
+
+hugeEnum_VALUE_0875 :: HugeEnum
+hugeEnum_VALUE_0875 = HugeEnum 875
+
+hugeEnum_VALUE_0876 :: HugeEnum
+hugeEnum_VALUE_0876 = HugeEnum 876
+
+hugeEnum_VALUE_0877 :: HugeEnum
+hugeEnum_VALUE_0877 = HugeEnum 877
+
+hugeEnum_VALUE_0878 :: HugeEnum
+hugeEnum_VALUE_0878 = HugeEnum 878
+
+hugeEnum_VALUE_0879 :: HugeEnum
+hugeEnum_VALUE_0879 = HugeEnum 879
+
+hugeEnum_VALUE_0880 :: HugeEnum
+hugeEnum_VALUE_0880 = HugeEnum 880
+
+hugeEnum_VALUE_0881 :: HugeEnum
+hugeEnum_VALUE_0881 = HugeEnum 881
+
+hugeEnum_VALUE_0882 :: HugeEnum
+hugeEnum_VALUE_0882 = HugeEnum 882
+
+hugeEnum_VALUE_0883 :: HugeEnum
+hugeEnum_VALUE_0883 = HugeEnum 883
+
+hugeEnum_VALUE_0884 :: HugeEnum
+hugeEnum_VALUE_0884 = HugeEnum 884
+
+hugeEnum_VALUE_0885 :: HugeEnum
+hugeEnum_VALUE_0885 = HugeEnum 885
+
+hugeEnum_VALUE_0886 :: HugeEnum
+hugeEnum_VALUE_0886 = HugeEnum 886
+
+hugeEnum_VALUE_0887 :: HugeEnum
+hugeEnum_VALUE_0887 = HugeEnum 887
+
+hugeEnum_VALUE_0888 :: HugeEnum
+hugeEnum_VALUE_0888 = HugeEnum 888
+
+hugeEnum_VALUE_0889 :: HugeEnum
+hugeEnum_VALUE_0889 = HugeEnum 889
+
+hugeEnum_VALUE_0890 :: HugeEnum
+hugeEnum_VALUE_0890 = HugeEnum 890
+
+hugeEnum_VALUE_0891 :: HugeEnum
+hugeEnum_VALUE_0891 = HugeEnum 891
+
+hugeEnum_VALUE_0892 :: HugeEnum
+hugeEnum_VALUE_0892 = HugeEnum 892
+
+hugeEnum_VALUE_0893 :: HugeEnum
+hugeEnum_VALUE_0893 = HugeEnum 893
+
+hugeEnum_VALUE_0894 :: HugeEnum
+hugeEnum_VALUE_0894 = HugeEnum 894
+
+hugeEnum_VALUE_0895 :: HugeEnum
+hugeEnum_VALUE_0895 = HugeEnum 895
+
+hugeEnum_VALUE_0896 :: HugeEnum
+hugeEnum_VALUE_0896 = HugeEnum 896
+
+hugeEnum_VALUE_0897 :: HugeEnum
+hugeEnum_VALUE_0897 = HugeEnum 897
+
+hugeEnum_VALUE_0898 :: HugeEnum
+hugeEnum_VALUE_0898 = HugeEnum 898
+
+hugeEnum_VALUE_0899 :: HugeEnum
+hugeEnum_VALUE_0899 = HugeEnum 899
+
+hugeEnum_VALUE_0900 :: HugeEnum
+hugeEnum_VALUE_0900 = HugeEnum 900
+
+hugeEnum_VALUE_0901 :: HugeEnum
+hugeEnum_VALUE_0901 = HugeEnum 901
+
+hugeEnum_VALUE_0902 :: HugeEnum
+hugeEnum_VALUE_0902 = HugeEnum 902
+
+hugeEnum_VALUE_0903 :: HugeEnum
+hugeEnum_VALUE_0903 = HugeEnum 903
+
+hugeEnum_VALUE_0904 :: HugeEnum
+hugeEnum_VALUE_0904 = HugeEnum 904
+
+hugeEnum_VALUE_0905 :: HugeEnum
+hugeEnum_VALUE_0905 = HugeEnum 905
+
+hugeEnum_VALUE_0906 :: HugeEnum
+hugeEnum_VALUE_0906 = HugeEnum 906
+
+hugeEnum_VALUE_0907 :: HugeEnum
+hugeEnum_VALUE_0907 = HugeEnum 907
+
+hugeEnum_VALUE_0908 :: HugeEnum
+hugeEnum_VALUE_0908 = HugeEnum 908
+
+hugeEnum_VALUE_0909 :: HugeEnum
+hugeEnum_VALUE_0909 = HugeEnum 909
+
+hugeEnum_VALUE_0910 :: HugeEnum
+hugeEnum_VALUE_0910 = HugeEnum 910
+
+hugeEnum_VALUE_0911 :: HugeEnum
+hugeEnum_VALUE_0911 = HugeEnum 911
+
+hugeEnum_VALUE_0912 :: HugeEnum
+hugeEnum_VALUE_0912 = HugeEnum 912
+
+hugeEnum_VALUE_0913 :: HugeEnum
+hugeEnum_VALUE_0913 = HugeEnum 913
+
+hugeEnum_VALUE_0914 :: HugeEnum
+hugeEnum_VALUE_0914 = HugeEnum 914
+
+hugeEnum_VALUE_0915 :: HugeEnum
+hugeEnum_VALUE_0915 = HugeEnum 915
+
+hugeEnum_VALUE_0916 :: HugeEnum
+hugeEnum_VALUE_0916 = HugeEnum 916
+
+hugeEnum_VALUE_0917 :: HugeEnum
+hugeEnum_VALUE_0917 = HugeEnum 917
+
+hugeEnum_VALUE_0918 :: HugeEnum
+hugeEnum_VALUE_0918 = HugeEnum 918
+
+hugeEnum_VALUE_0919 :: HugeEnum
+hugeEnum_VALUE_0919 = HugeEnum 919
+
+hugeEnum_VALUE_0920 :: HugeEnum
+hugeEnum_VALUE_0920 = HugeEnum 920
+
+hugeEnum_VALUE_0921 :: HugeEnum
+hugeEnum_VALUE_0921 = HugeEnum 921
+
+hugeEnum_VALUE_0922 :: HugeEnum
+hugeEnum_VALUE_0922 = HugeEnum 922
+
+hugeEnum_VALUE_0923 :: HugeEnum
+hugeEnum_VALUE_0923 = HugeEnum 923
+
+hugeEnum_VALUE_0924 :: HugeEnum
+hugeEnum_VALUE_0924 = HugeEnum 924
+
+hugeEnum_VALUE_0925 :: HugeEnum
+hugeEnum_VALUE_0925 = HugeEnum 925
+
+hugeEnum_VALUE_0926 :: HugeEnum
+hugeEnum_VALUE_0926 = HugeEnum 926
+
+hugeEnum_VALUE_0927 :: HugeEnum
+hugeEnum_VALUE_0927 = HugeEnum 927
+
+hugeEnum_VALUE_0928 :: HugeEnum
+hugeEnum_VALUE_0928 = HugeEnum 928
+
+hugeEnum_VALUE_0929 :: HugeEnum
+hugeEnum_VALUE_0929 = HugeEnum 929
+
+hugeEnum_VALUE_0930 :: HugeEnum
+hugeEnum_VALUE_0930 = HugeEnum 930
+
+hugeEnum_VALUE_0931 :: HugeEnum
+hugeEnum_VALUE_0931 = HugeEnum 931
+
+hugeEnum_VALUE_0932 :: HugeEnum
+hugeEnum_VALUE_0932 = HugeEnum 932
+
+hugeEnum_VALUE_0933 :: HugeEnum
+hugeEnum_VALUE_0933 = HugeEnum 933
+
+hugeEnum_VALUE_0934 :: HugeEnum
+hugeEnum_VALUE_0934 = HugeEnum 934
+
+hugeEnum_VALUE_0935 :: HugeEnum
+hugeEnum_VALUE_0935 = HugeEnum 935
+
+hugeEnum_VALUE_0936 :: HugeEnum
+hugeEnum_VALUE_0936 = HugeEnum 936
+
+hugeEnum_VALUE_0937 :: HugeEnum
+hugeEnum_VALUE_0937 = HugeEnum 937
+
+hugeEnum_VALUE_0938 :: HugeEnum
+hugeEnum_VALUE_0938 = HugeEnum 938
+
+hugeEnum_VALUE_0939 :: HugeEnum
+hugeEnum_VALUE_0939 = HugeEnum 939
+
+hugeEnum_VALUE_0940 :: HugeEnum
+hugeEnum_VALUE_0940 = HugeEnum 940
+
+hugeEnum_VALUE_0941 :: HugeEnum
+hugeEnum_VALUE_0941 = HugeEnum 941
+
+hugeEnum_VALUE_0942 :: HugeEnum
+hugeEnum_VALUE_0942 = HugeEnum 942
+
+hugeEnum_VALUE_0943 :: HugeEnum
+hugeEnum_VALUE_0943 = HugeEnum 943
+
+hugeEnum_VALUE_0944 :: HugeEnum
+hugeEnum_VALUE_0944 = HugeEnum 944
+
+hugeEnum_VALUE_0945 :: HugeEnum
+hugeEnum_VALUE_0945 = HugeEnum 945
+
+hugeEnum_VALUE_0946 :: HugeEnum
+hugeEnum_VALUE_0946 = HugeEnum 946
+
+hugeEnum_VALUE_0947 :: HugeEnum
+hugeEnum_VALUE_0947 = HugeEnum 947
+
+hugeEnum_VALUE_0948 :: HugeEnum
+hugeEnum_VALUE_0948 = HugeEnum 948
+
+hugeEnum_VALUE_0949 :: HugeEnum
+hugeEnum_VALUE_0949 = HugeEnum 949
+
+hugeEnum_VALUE_0950 :: HugeEnum
+hugeEnum_VALUE_0950 = HugeEnum 950
+
+hugeEnum_VALUE_0951 :: HugeEnum
+hugeEnum_VALUE_0951 = HugeEnum 951
+
+hugeEnum_VALUE_0952 :: HugeEnum
+hugeEnum_VALUE_0952 = HugeEnum 952
+
+hugeEnum_VALUE_0953 :: HugeEnum
+hugeEnum_VALUE_0953 = HugeEnum 953
+
+hugeEnum_VALUE_0954 :: HugeEnum
+hugeEnum_VALUE_0954 = HugeEnum 954
+
+hugeEnum_VALUE_0955 :: HugeEnum
+hugeEnum_VALUE_0955 = HugeEnum 955
+
+hugeEnum_VALUE_0956 :: HugeEnum
+hugeEnum_VALUE_0956 = HugeEnum 956
+
+hugeEnum_VALUE_0957 :: HugeEnum
+hugeEnum_VALUE_0957 = HugeEnum 957
+
+hugeEnum_VALUE_0958 :: HugeEnum
+hugeEnum_VALUE_0958 = HugeEnum 958
+
+hugeEnum_VALUE_0959 :: HugeEnum
+hugeEnum_VALUE_0959 = HugeEnum 959
+
+hugeEnum_VALUE_0960 :: HugeEnum
+hugeEnum_VALUE_0960 = HugeEnum 960
+
+hugeEnum_VALUE_0961 :: HugeEnum
+hugeEnum_VALUE_0961 = HugeEnum 961
+
+hugeEnum_VALUE_0962 :: HugeEnum
+hugeEnum_VALUE_0962 = HugeEnum 962
+
+hugeEnum_VALUE_0963 :: HugeEnum
+hugeEnum_VALUE_0963 = HugeEnum 963
+
+hugeEnum_VALUE_0964 :: HugeEnum
+hugeEnum_VALUE_0964 = HugeEnum 964
+
+hugeEnum_VALUE_0965 :: HugeEnum
+hugeEnum_VALUE_0965 = HugeEnum 965
+
+hugeEnum_VALUE_0966 :: HugeEnum
+hugeEnum_VALUE_0966 = HugeEnum 966
+
+hugeEnum_VALUE_0967 :: HugeEnum
+hugeEnum_VALUE_0967 = HugeEnum 967
+
+hugeEnum_VALUE_0968 :: HugeEnum
+hugeEnum_VALUE_0968 = HugeEnum 968
+
+hugeEnum_VALUE_0969 :: HugeEnum
+hugeEnum_VALUE_0969 = HugeEnum 969
+
+hugeEnum_VALUE_0970 :: HugeEnum
+hugeEnum_VALUE_0970 = HugeEnum 970
+
+hugeEnum_VALUE_0971 :: HugeEnum
+hugeEnum_VALUE_0971 = HugeEnum 971
+
+hugeEnum_VALUE_0972 :: HugeEnum
+hugeEnum_VALUE_0972 = HugeEnum 972
+
+hugeEnum_VALUE_0973 :: HugeEnum
+hugeEnum_VALUE_0973 = HugeEnum 973
+
+hugeEnum_VALUE_0974 :: HugeEnum
+hugeEnum_VALUE_0974 = HugeEnum 974
+
+hugeEnum_VALUE_0975 :: HugeEnum
+hugeEnum_VALUE_0975 = HugeEnum 975
+
+hugeEnum_VALUE_0976 :: HugeEnum
+hugeEnum_VALUE_0976 = HugeEnum 976
+
+hugeEnum_VALUE_0977 :: HugeEnum
+hugeEnum_VALUE_0977 = HugeEnum 977
+
+hugeEnum_VALUE_0978 :: HugeEnum
+hugeEnum_VALUE_0978 = HugeEnum 978
+
+hugeEnum_VALUE_0979 :: HugeEnum
+hugeEnum_VALUE_0979 = HugeEnum 979
+
+hugeEnum_VALUE_0980 :: HugeEnum
+hugeEnum_VALUE_0980 = HugeEnum 980
+
+hugeEnum_VALUE_0981 :: HugeEnum
+hugeEnum_VALUE_0981 = HugeEnum 981
+
+hugeEnum_VALUE_0982 :: HugeEnum
+hugeEnum_VALUE_0982 = HugeEnum 982
+
+hugeEnum_VALUE_0983 :: HugeEnum
+hugeEnum_VALUE_0983 = HugeEnum 983
+
+hugeEnum_VALUE_0984 :: HugeEnum
+hugeEnum_VALUE_0984 = HugeEnum 984
+
+hugeEnum_VALUE_0985 :: HugeEnum
+hugeEnum_VALUE_0985 = HugeEnum 985
+
+hugeEnum_VALUE_0986 :: HugeEnum
+hugeEnum_VALUE_0986 = HugeEnum 986
+
+hugeEnum_VALUE_0987 :: HugeEnum
+hugeEnum_VALUE_0987 = HugeEnum 987
+
+hugeEnum_VALUE_0988 :: HugeEnum
+hugeEnum_VALUE_0988 = HugeEnum 988
+
+hugeEnum_VALUE_0989 :: HugeEnum
+hugeEnum_VALUE_0989 = HugeEnum 989
+
+hugeEnum_VALUE_0990 :: HugeEnum
+hugeEnum_VALUE_0990 = HugeEnum 990
+
+hugeEnum_VALUE_0991 :: HugeEnum
+hugeEnum_VALUE_0991 = HugeEnum 991
+
+hugeEnum_VALUE_0992 :: HugeEnum
+hugeEnum_VALUE_0992 = HugeEnum 992
+
+hugeEnum_VALUE_0993 :: HugeEnum
+hugeEnum_VALUE_0993 = HugeEnum 993
+
+hugeEnum_VALUE_0994 :: HugeEnum
+hugeEnum_VALUE_0994 = HugeEnum 994
+
+hugeEnum_VALUE_0995 :: HugeEnum
+hugeEnum_VALUE_0995 = HugeEnum 995
+
+hugeEnum_VALUE_0996 :: HugeEnum
+hugeEnum_VALUE_0996 = HugeEnum 996
+
+hugeEnum_VALUE_0997 :: HugeEnum
+hugeEnum_VALUE_0997 = HugeEnum 997
+
+hugeEnum_VALUE_0998 :: HugeEnum
+hugeEnum_VALUE_0998 = HugeEnum 998
+
+hugeEnum_VALUE_0999 :: HugeEnum
+hugeEnum_VALUE_0999 = HugeEnum 999
+
+hugeEnum_VALUE_1000 :: HugeEnum
+hugeEnum_VALUE_1000 = HugeEnum 1000
+
+hugeEnum_VALUE_1001 :: HugeEnum
+hugeEnum_VALUE_1001 = HugeEnum 1001
+
+instance Default.Default HugeEnum where
+  def = hugeEnum_VALUE_0001
+
+instance Prelude.Show HugeEnum where
+  showsPrec __d (HugeEnum __val)
+    = case HashMap.lookup __val __m of
+        Prelude.Just __s -> Prelude.showString __s
+        Prelude.Nothing -> Prelude.showParen (__d > 10)
+                             (Prelude.showString "HugeEnum__UNKNOWN " .
+                                Prelude.showsPrec 11 __val)
+    where
+      __m
+        = HashMap.fromList
+            (Prelude.concat
+               [GHC.noinline Prelude.id
+                  [(1, "HugeEnum_VALUE_0001"), (2, "HugeEnum_VALUE_0002"),
+                   (3, "HugeEnum_VALUE_0003"), (4, "HugeEnum_VALUE_0004"),
+                   (5, "HugeEnum_VALUE_0005"), (6, "HugeEnum_VALUE_0006"),
+                   (7, "HugeEnum_VALUE_0007"), (8, "HugeEnum_VALUE_0008"),
+                   (9, "HugeEnum_VALUE_0009"), (10, "HugeEnum_VALUE_0010"),
+                   (11, "HugeEnum_VALUE_0011"), (12, "HugeEnum_VALUE_0012"),
+                   (13, "HugeEnum_VALUE_0013"), (14, "HugeEnum_VALUE_0014"),
+                   (15, "HugeEnum_VALUE_0015"), (16, "HugeEnum_VALUE_0016"),
+                   (17, "HugeEnum_VALUE_0017"), (18, "HugeEnum_VALUE_0018"),
+                   (19, "HugeEnum_VALUE_0019"), (20, "HugeEnum_VALUE_0020"),
+                   (21, "HugeEnum_VALUE_0021"), (22, "HugeEnum_VALUE_0022"),
+                   (23, "HugeEnum_VALUE_0023"), (24, "HugeEnum_VALUE_0024"),
+                   (25, "HugeEnum_VALUE_0025"), (26, "HugeEnum_VALUE_0026"),
+                   (27, "HugeEnum_VALUE_0027"), (28, "HugeEnum_VALUE_0028"),
+                   (29, "HugeEnum_VALUE_0029"), (30, "HugeEnum_VALUE_0030"),
+                   (31, "HugeEnum_VALUE_0031"), (32, "HugeEnum_VALUE_0032"),
+                   (33, "HugeEnum_VALUE_0033"), (34, "HugeEnum_VALUE_0034"),
+                   (35, "HugeEnum_VALUE_0035"), (36, "HugeEnum_VALUE_0036"),
+                   (37, "HugeEnum_VALUE_0037"), (38, "HugeEnum_VALUE_0038"),
+                   (39, "HugeEnum_VALUE_0039"), (40, "HugeEnum_VALUE_0040"),
+                   (41, "HugeEnum_VALUE_0041"), (42, "HugeEnum_VALUE_0042"),
+                   (43, "HugeEnum_VALUE_0043"), (44, "HugeEnum_VALUE_0044"),
+                   (45, "HugeEnum_VALUE_0045"), (46, "HugeEnum_VALUE_0046"),
+                   (47, "HugeEnum_VALUE_0047"), (48, "HugeEnum_VALUE_0048"),
+                   (49, "HugeEnum_VALUE_0049"), (50, "HugeEnum_VALUE_0050"),
+                   (51, "HugeEnum_VALUE_0051"), (52, "HugeEnum_VALUE_0052"),
+                   (53, "HugeEnum_VALUE_0053"), (54, "HugeEnum_VALUE_0054"),
+                   (55, "HugeEnum_VALUE_0055"), (56, "HugeEnum_VALUE_0056"),
+                   (57, "HugeEnum_VALUE_0057"), (58, "HugeEnum_VALUE_0058"),
+                   (59, "HugeEnum_VALUE_0059"), (60, "HugeEnum_VALUE_0060"),
+                   (61, "HugeEnum_VALUE_0061"), (62, "HugeEnum_VALUE_0062"),
+                   (63, "HugeEnum_VALUE_0063"), (64, "HugeEnum_VALUE_0064"),
+                   (65, "HugeEnum_VALUE_0065"), (66, "HugeEnum_VALUE_0066"),
+                   (67, "HugeEnum_VALUE_0067"), (68, "HugeEnum_VALUE_0068"),
+                   (69, "HugeEnum_VALUE_0069"), (70, "HugeEnum_VALUE_0070"),
+                   (71, "HugeEnum_VALUE_0071"), (72, "HugeEnum_VALUE_0072"),
+                   (73, "HugeEnum_VALUE_0073"), (74, "HugeEnum_VALUE_0074"),
+                   (75, "HugeEnum_VALUE_0075"), (76, "HugeEnum_VALUE_0076"),
+                   (77, "HugeEnum_VALUE_0077"), (78, "HugeEnum_VALUE_0078"),
+                   (79, "HugeEnum_VALUE_0079"), (80, "HugeEnum_VALUE_0080"),
+                   (81, "HugeEnum_VALUE_0081"), (82, "HugeEnum_VALUE_0082"),
+                   (83, "HugeEnum_VALUE_0083"), (84, "HugeEnum_VALUE_0084"),
+                   (85, "HugeEnum_VALUE_0085"), (86, "HugeEnum_VALUE_0086"),
+                   (87, "HugeEnum_VALUE_0087"), (88, "HugeEnum_VALUE_0088"),
+                   (89, "HugeEnum_VALUE_0089"), (90, "HugeEnum_VALUE_0090"),
+                   (91, "HugeEnum_VALUE_0091"), (92, "HugeEnum_VALUE_0092"),
+                   (93, "HugeEnum_VALUE_0093"), (94, "HugeEnum_VALUE_0094"),
+                   (95, "HugeEnum_VALUE_0095"), (96, "HugeEnum_VALUE_0096"),
+                   (97, "HugeEnum_VALUE_0097"), (98, "HugeEnum_VALUE_0098"),
+                   (99, "HugeEnum_VALUE_0099"), (100, "HugeEnum_VALUE_0100"),
+                   (101, "HugeEnum_VALUE_0101"), (102, "HugeEnum_VALUE_0102"),
+                   (103, "HugeEnum_VALUE_0103"), (104, "HugeEnum_VALUE_0104"),
+                   (105, "HugeEnum_VALUE_0105"), (106, "HugeEnum_VALUE_0106"),
+                   (107, "HugeEnum_VALUE_0107"), (108, "HugeEnum_VALUE_0108"),
+                   (109, "HugeEnum_VALUE_0109"), (110, "HugeEnum_VALUE_0110"),
+                   (111, "HugeEnum_VALUE_0111"), (112, "HugeEnum_VALUE_0112"),
+                   (113, "HugeEnum_VALUE_0113"), (114, "HugeEnum_VALUE_0114"),
+                   (115, "HugeEnum_VALUE_0115"), (116, "HugeEnum_VALUE_0116"),
+                   (117, "HugeEnum_VALUE_0117"), (118, "HugeEnum_VALUE_0118"),
+                   (119, "HugeEnum_VALUE_0119"), (120, "HugeEnum_VALUE_0120"),
+                   (121, "HugeEnum_VALUE_0121"), (122, "HugeEnum_VALUE_0122"),
+                   (123, "HugeEnum_VALUE_0123"), (124, "HugeEnum_VALUE_0124"),
+                   (125, "HugeEnum_VALUE_0125"), (126, "HugeEnum_VALUE_0126"),
+                   (127, "HugeEnum_VALUE_0127"), (128, "HugeEnum_VALUE_0128"),
+                   (129, "HugeEnum_VALUE_0129"), (130, "HugeEnum_VALUE_0130"),
+                   (131, "HugeEnum_VALUE_0131"), (132, "HugeEnum_VALUE_0132"),
+                   (133, "HugeEnum_VALUE_0133"), (134, "HugeEnum_VALUE_0134"),
+                   (135, "HugeEnum_VALUE_0135"), (136, "HugeEnum_VALUE_0136"),
+                   (137, "HugeEnum_VALUE_0137"), (138, "HugeEnum_VALUE_0138"),
+                   (139, "HugeEnum_VALUE_0139"), (140, "HugeEnum_VALUE_0140"),
+                   (141, "HugeEnum_VALUE_0141"), (142, "HugeEnum_VALUE_0142"),
+                   (143, "HugeEnum_VALUE_0143"), (144, "HugeEnum_VALUE_0144"),
+                   (145, "HugeEnum_VALUE_0145"), (146, "HugeEnum_VALUE_0146"),
+                   (147, "HugeEnum_VALUE_0147"), (148, "HugeEnum_VALUE_0148"),
+                   (149, "HugeEnum_VALUE_0149"), (150, "HugeEnum_VALUE_0150"),
+                   (151, "HugeEnum_VALUE_0151"), (152, "HugeEnum_VALUE_0152"),
+                   (153, "HugeEnum_VALUE_0153"), (154, "HugeEnum_VALUE_0154"),
+                   (155, "HugeEnum_VALUE_0155"), (156, "HugeEnum_VALUE_0156"),
+                   (157, "HugeEnum_VALUE_0157"), (158, "HugeEnum_VALUE_0158"),
+                   (159, "HugeEnum_VALUE_0159"), (160, "HugeEnum_VALUE_0160"),
+                   (161, "HugeEnum_VALUE_0161"), (162, "HugeEnum_VALUE_0162"),
+                   (163, "HugeEnum_VALUE_0163"), (164, "HugeEnum_VALUE_0164"),
+                   (165, "HugeEnum_VALUE_0165"), (166, "HugeEnum_VALUE_0166"),
+                   (167, "HugeEnum_VALUE_0167"), (168, "HugeEnum_VALUE_0168"),
+                   (169, "HugeEnum_VALUE_0169"), (170, "HugeEnum_VALUE_0170"),
+                   (171, "HugeEnum_VALUE_0171"), (172, "HugeEnum_VALUE_0172"),
+                   (173, "HugeEnum_VALUE_0173"), (174, "HugeEnum_VALUE_0174"),
+                   (175, "HugeEnum_VALUE_0175"), (176, "HugeEnum_VALUE_0176"),
+                   (177, "HugeEnum_VALUE_0177"), (178, "HugeEnum_VALUE_0178"),
+                   (179, "HugeEnum_VALUE_0179"), (180, "HugeEnum_VALUE_0180"),
+                   (181, "HugeEnum_VALUE_0181"), (182, "HugeEnum_VALUE_0182"),
+                   (183, "HugeEnum_VALUE_0183"), (184, "HugeEnum_VALUE_0184"),
+                   (185, "HugeEnum_VALUE_0185"), (186, "HugeEnum_VALUE_0186"),
+                   (187, "HugeEnum_VALUE_0187"), (188, "HugeEnum_VALUE_0188"),
+                   (189, "HugeEnum_VALUE_0189"), (190, "HugeEnum_VALUE_0190"),
+                   (191, "HugeEnum_VALUE_0191"), (192, "HugeEnum_VALUE_0192"),
+                   (193, "HugeEnum_VALUE_0193"), (194, "HugeEnum_VALUE_0194"),
+                   (195, "HugeEnum_VALUE_0195"), (196, "HugeEnum_VALUE_0196"),
+                   (197, "HugeEnum_VALUE_0197"), (198, "HugeEnum_VALUE_0198"),
+                   (199, "HugeEnum_VALUE_0199"), (200, "HugeEnum_VALUE_0200"),
+                   (201, "HugeEnum_VALUE_0201"), (202, "HugeEnum_VALUE_0202"),
+                   (203, "HugeEnum_VALUE_0203"), (204, "HugeEnum_VALUE_0204"),
+                   (205, "HugeEnum_VALUE_0205"), (206, "HugeEnum_VALUE_0206"),
+                   (207, "HugeEnum_VALUE_0207"), (208, "HugeEnum_VALUE_0208"),
+                   (209, "HugeEnum_VALUE_0209"), (210, "HugeEnum_VALUE_0210"),
+                   (211, "HugeEnum_VALUE_0211"), (212, "HugeEnum_VALUE_0212"),
+                   (213, "HugeEnum_VALUE_0213"), (214, "HugeEnum_VALUE_0214"),
+                   (215, "HugeEnum_VALUE_0215"), (216, "HugeEnum_VALUE_0216"),
+                   (217, "HugeEnum_VALUE_0217"), (218, "HugeEnum_VALUE_0218"),
+                   (219, "HugeEnum_VALUE_0219"), (220, "HugeEnum_VALUE_0220"),
+                   (221, "HugeEnum_VALUE_0221"), (222, "HugeEnum_VALUE_0222"),
+                   (223, "HugeEnum_VALUE_0223"), (224, "HugeEnum_VALUE_0224"),
+                   (225, "HugeEnum_VALUE_0225"), (226, "HugeEnum_VALUE_0226"),
+                   (227, "HugeEnum_VALUE_0227"), (228, "HugeEnum_VALUE_0228"),
+                   (229, "HugeEnum_VALUE_0229"), (230, "HugeEnum_VALUE_0230"),
+                   (231, "HugeEnum_VALUE_0231"), (232, "HugeEnum_VALUE_0232"),
+                   (233, "HugeEnum_VALUE_0233"), (234, "HugeEnum_VALUE_0234"),
+                   (235, "HugeEnum_VALUE_0235"), (236, "HugeEnum_VALUE_0236"),
+                   (237, "HugeEnum_VALUE_0237"), (238, "HugeEnum_VALUE_0238"),
+                   (239, "HugeEnum_VALUE_0239"), (240, "HugeEnum_VALUE_0240"),
+                   (241, "HugeEnum_VALUE_0241"), (242, "HugeEnum_VALUE_0242"),
+                   (243, "HugeEnum_VALUE_0243"), (244, "HugeEnum_VALUE_0244"),
+                   (245, "HugeEnum_VALUE_0245"), (246, "HugeEnum_VALUE_0246"),
+                   (247, "HugeEnum_VALUE_0247"), (248, "HugeEnum_VALUE_0248"),
+                   (249, "HugeEnum_VALUE_0249"), (250, "HugeEnum_VALUE_0250"),
+                   (251, "HugeEnum_VALUE_0251"), (252, "HugeEnum_VALUE_0252"),
+                   (253, "HugeEnum_VALUE_0253"), (254, "HugeEnum_VALUE_0254"),
+                   (255, "HugeEnum_VALUE_0255"), (256, "HugeEnum_VALUE_0256"),
+                   (257, "HugeEnum_VALUE_0257"), (258, "HugeEnum_VALUE_0258"),
+                   (259, "HugeEnum_VALUE_0259"), (260, "HugeEnum_VALUE_0260"),
+                   (261, "HugeEnum_VALUE_0261"), (262, "HugeEnum_VALUE_0262"),
+                   (263, "HugeEnum_VALUE_0263"), (264, "HugeEnum_VALUE_0264"),
+                   (265, "HugeEnum_VALUE_0265"), (266, "HugeEnum_VALUE_0266"),
+                   (267, "HugeEnum_VALUE_0267"), (268, "HugeEnum_VALUE_0268"),
+                   (269, "HugeEnum_VALUE_0269"), (270, "HugeEnum_VALUE_0270"),
+                   (271, "HugeEnum_VALUE_0271"), (272, "HugeEnum_VALUE_0272"),
+                   (273, "HugeEnum_VALUE_0273"), (274, "HugeEnum_VALUE_0274"),
+                   (275, "HugeEnum_VALUE_0275"), (276, "HugeEnum_VALUE_0276"),
+                   (277, "HugeEnum_VALUE_0277"), (278, "HugeEnum_VALUE_0278"),
+                   (279, "HugeEnum_VALUE_0279"), (280, "HugeEnum_VALUE_0280"),
+                   (281, "HugeEnum_VALUE_0281"), (282, "HugeEnum_VALUE_0282"),
+                   (283, "HugeEnum_VALUE_0283"), (284, "HugeEnum_VALUE_0284"),
+                   (285, "HugeEnum_VALUE_0285"), (286, "HugeEnum_VALUE_0286"),
+                   (287, "HugeEnum_VALUE_0287"), (288, "HugeEnum_VALUE_0288"),
+                   (289, "HugeEnum_VALUE_0289"), (290, "HugeEnum_VALUE_0290"),
+                   (291, "HugeEnum_VALUE_0291"), (292, "HugeEnum_VALUE_0292"),
+                   (293, "HugeEnum_VALUE_0293"), (294, "HugeEnum_VALUE_0294"),
+                   (295, "HugeEnum_VALUE_0295"), (296, "HugeEnum_VALUE_0296"),
+                   (297, "HugeEnum_VALUE_0297"), (298, "HugeEnum_VALUE_0298"),
+                   (299, "HugeEnum_VALUE_0299"), (300, "HugeEnum_VALUE_0300"),
+                   (301, "HugeEnum_VALUE_0301"), (302, "HugeEnum_VALUE_0302"),
+                   (303, "HugeEnum_VALUE_0303"), (304, "HugeEnum_VALUE_0304"),
+                   (305, "HugeEnum_VALUE_0305"), (306, "HugeEnum_VALUE_0306"),
+                   (307, "HugeEnum_VALUE_0307"), (308, "HugeEnum_VALUE_0308"),
+                   (309, "HugeEnum_VALUE_0309"), (310, "HugeEnum_VALUE_0310"),
+                   (311, "HugeEnum_VALUE_0311"), (312, "HugeEnum_VALUE_0312"),
+                   (313, "HugeEnum_VALUE_0313"), (314, "HugeEnum_VALUE_0314"),
+                   (315, "HugeEnum_VALUE_0315"), (316, "HugeEnum_VALUE_0316"),
+                   (317, "HugeEnum_VALUE_0317"), (318, "HugeEnum_VALUE_0318"),
+                   (319, "HugeEnum_VALUE_0319"), (320, "HugeEnum_VALUE_0320"),
+                   (321, "HugeEnum_VALUE_0321"), (322, "HugeEnum_VALUE_0322"),
+                   (323, "HugeEnum_VALUE_0323"), (324, "HugeEnum_VALUE_0324"),
+                   (325, "HugeEnum_VALUE_0325"), (326, "HugeEnum_VALUE_0326"),
+                   (327, "HugeEnum_VALUE_0327"), (328, "HugeEnum_VALUE_0328"),
+                   (329, "HugeEnum_VALUE_0329"), (330, "HugeEnum_VALUE_0330"),
+                   (331, "HugeEnum_VALUE_0331"), (332, "HugeEnum_VALUE_0332"),
+                   (333, "HugeEnum_VALUE_0333"), (334, "HugeEnum_VALUE_0334"),
+                   (335, "HugeEnum_VALUE_0335"), (336, "HugeEnum_VALUE_0336"),
+                   (337, "HugeEnum_VALUE_0337"), (338, "HugeEnum_VALUE_0338"),
+                   (339, "HugeEnum_VALUE_0339"), (340, "HugeEnum_VALUE_0340"),
+                   (341, "HugeEnum_VALUE_0341"), (342, "HugeEnum_VALUE_0342"),
+                   (343, "HugeEnum_VALUE_0343"), (344, "HugeEnum_VALUE_0344"),
+                   (345, "HugeEnum_VALUE_0345"), (346, "HugeEnum_VALUE_0346"),
+                   (347, "HugeEnum_VALUE_0347"), (348, "HugeEnum_VALUE_0348"),
+                   (349, "HugeEnum_VALUE_0349"), (350, "HugeEnum_VALUE_0350"),
+                   (351, "HugeEnum_VALUE_0351"), (352, "HugeEnum_VALUE_0352"),
+                   (353, "HugeEnum_VALUE_0353"), (354, "HugeEnum_VALUE_0354"),
+                   (355, "HugeEnum_VALUE_0355"), (356, "HugeEnum_VALUE_0356"),
+                   (357, "HugeEnum_VALUE_0357"), (358, "HugeEnum_VALUE_0358"),
+                   (359, "HugeEnum_VALUE_0359"), (360, "HugeEnum_VALUE_0360"),
+                   (361, "HugeEnum_VALUE_0361"), (362, "HugeEnum_VALUE_0362"),
+                   (363, "HugeEnum_VALUE_0363"), (364, "HugeEnum_VALUE_0364"),
+                   (365, "HugeEnum_VALUE_0365"), (366, "HugeEnum_VALUE_0366"),
+                   (367, "HugeEnum_VALUE_0367"), (368, "HugeEnum_VALUE_0368"),
+                   (369, "HugeEnum_VALUE_0369"), (370, "HugeEnum_VALUE_0370"),
+                   (371, "HugeEnum_VALUE_0371"), (372, "HugeEnum_VALUE_0372"),
+                   (373, "HugeEnum_VALUE_0373"), (374, "HugeEnum_VALUE_0374"),
+                   (375, "HugeEnum_VALUE_0375"), (376, "HugeEnum_VALUE_0376"),
+                   (377, "HugeEnum_VALUE_0377"), (378, "HugeEnum_VALUE_0378"),
+                   (379, "HugeEnum_VALUE_0379"), (380, "HugeEnum_VALUE_0380"),
+                   (381, "HugeEnum_VALUE_0381"), (382, "HugeEnum_VALUE_0382"),
+                   (383, "HugeEnum_VALUE_0383"), (384, "HugeEnum_VALUE_0384"),
+                   (385, "HugeEnum_VALUE_0385"), (386, "HugeEnum_VALUE_0386"),
+                   (387, "HugeEnum_VALUE_0387"), (388, "HugeEnum_VALUE_0388"),
+                   (389, "HugeEnum_VALUE_0389"), (390, "HugeEnum_VALUE_0390"),
+                   (391, "HugeEnum_VALUE_0391"), (392, "HugeEnum_VALUE_0392"),
+                   (393, "HugeEnum_VALUE_0393"), (394, "HugeEnum_VALUE_0394"),
+                   (395, "HugeEnum_VALUE_0395"), (396, "HugeEnum_VALUE_0396"),
+                   (397, "HugeEnum_VALUE_0397"), (398, "HugeEnum_VALUE_0398"),
+                   (399, "HugeEnum_VALUE_0399"), (400, "HugeEnum_VALUE_0400"),
+                   (401, "HugeEnum_VALUE_0401"), (402, "HugeEnum_VALUE_0402"),
+                   (403, "HugeEnum_VALUE_0403"), (404, "HugeEnum_VALUE_0404"),
+                   (405, "HugeEnum_VALUE_0405"), (406, "HugeEnum_VALUE_0406"),
+                   (407, "HugeEnum_VALUE_0407"), (408, "HugeEnum_VALUE_0408"),
+                   (409, "HugeEnum_VALUE_0409"), (410, "HugeEnum_VALUE_0410"),
+                   (411, "HugeEnum_VALUE_0411"), (412, "HugeEnum_VALUE_0412"),
+                   (413, "HugeEnum_VALUE_0413"), (414, "HugeEnum_VALUE_0414"),
+                   (415, "HugeEnum_VALUE_0415"), (416, "HugeEnum_VALUE_0416"),
+                   (417, "HugeEnum_VALUE_0417"), (418, "HugeEnum_VALUE_0418"),
+                   (419, "HugeEnum_VALUE_0419"), (420, "HugeEnum_VALUE_0420"),
+                   (421, "HugeEnum_VALUE_0421"), (422, "HugeEnum_VALUE_0422"),
+                   (423, "HugeEnum_VALUE_0423"), (424, "HugeEnum_VALUE_0424"),
+                   (425, "HugeEnum_VALUE_0425"), (426, "HugeEnum_VALUE_0426"),
+                   (427, "HugeEnum_VALUE_0427"), (428, "HugeEnum_VALUE_0428"),
+                   (429, "HugeEnum_VALUE_0429"), (430, "HugeEnum_VALUE_0430"),
+                   (431, "HugeEnum_VALUE_0431"), (432, "HugeEnum_VALUE_0432"),
+                   (433, "HugeEnum_VALUE_0433"), (434, "HugeEnum_VALUE_0434"),
+                   (435, "HugeEnum_VALUE_0435"), (436, "HugeEnum_VALUE_0436"),
+                   (437, "HugeEnum_VALUE_0437"), (438, "HugeEnum_VALUE_0438"),
+                   (439, "HugeEnum_VALUE_0439"), (440, "HugeEnum_VALUE_0440"),
+                   (441, "HugeEnum_VALUE_0441"), (442, "HugeEnum_VALUE_0442"),
+                   (443, "HugeEnum_VALUE_0443"), (444, "HugeEnum_VALUE_0444"),
+                   (445, "HugeEnum_VALUE_0445"), (446, "HugeEnum_VALUE_0446"),
+                   (447, "HugeEnum_VALUE_0447"), (448, "HugeEnum_VALUE_0448"),
+                   (449, "HugeEnum_VALUE_0449"), (450, "HugeEnum_VALUE_0450"),
+                   (451, "HugeEnum_VALUE_0451"), (452, "HugeEnum_VALUE_0452"),
+                   (453, "HugeEnum_VALUE_0453"), (454, "HugeEnum_VALUE_0454"),
+                   (455, "HugeEnum_VALUE_0455"), (456, "HugeEnum_VALUE_0456"),
+                   (457, "HugeEnum_VALUE_0457"), (458, "HugeEnum_VALUE_0458"),
+                   (459, "HugeEnum_VALUE_0459"), (460, "HugeEnum_VALUE_0460"),
+                   (461, "HugeEnum_VALUE_0461"), (462, "HugeEnum_VALUE_0462"),
+                   (463, "HugeEnum_VALUE_0463"), (464, "HugeEnum_VALUE_0464"),
+                   (465, "HugeEnum_VALUE_0465"), (466, "HugeEnum_VALUE_0466"),
+                   (467, "HugeEnum_VALUE_0467"), (468, "HugeEnum_VALUE_0468"),
+                   (469, "HugeEnum_VALUE_0469"), (470, "HugeEnum_VALUE_0470"),
+                   (471, "HugeEnum_VALUE_0471"), (472, "HugeEnum_VALUE_0472"),
+                   (473, "HugeEnum_VALUE_0473"), (474, "HugeEnum_VALUE_0474"),
+                   (475, "HugeEnum_VALUE_0475"), (476, "HugeEnum_VALUE_0476"),
+                   (477, "HugeEnum_VALUE_0477"), (478, "HugeEnum_VALUE_0478"),
+                   (479, "HugeEnum_VALUE_0479"), (480, "HugeEnum_VALUE_0480"),
+                   (481, "HugeEnum_VALUE_0481"), (482, "HugeEnum_VALUE_0482"),
+                   (483, "HugeEnum_VALUE_0483"), (484, "HugeEnum_VALUE_0484"),
+                   (485, "HugeEnum_VALUE_0485"), (486, "HugeEnum_VALUE_0486"),
+                   (487, "HugeEnum_VALUE_0487"), (488, "HugeEnum_VALUE_0488"),
+                   (489, "HugeEnum_VALUE_0489"), (490, "HugeEnum_VALUE_0490"),
+                   (491, "HugeEnum_VALUE_0491"), (492, "HugeEnum_VALUE_0492"),
+                   (493, "HugeEnum_VALUE_0493"), (494, "HugeEnum_VALUE_0494"),
+                   (495, "HugeEnum_VALUE_0495"), (496, "HugeEnum_VALUE_0496"),
+                   (497, "HugeEnum_VALUE_0497"), (498, "HugeEnum_VALUE_0498"),
+                   (499, "HugeEnum_VALUE_0499"), (500, "HugeEnum_VALUE_0500"),
+                   (501, "HugeEnum_VALUE_0501"), (502, "HugeEnum_VALUE_0502"),
+                   (503, "HugeEnum_VALUE_0503"), (504, "HugeEnum_VALUE_0504"),
+                   (505, "HugeEnum_VALUE_0505"), (506, "HugeEnum_VALUE_0506"),
+                   (507, "HugeEnum_VALUE_0507"), (508, "HugeEnum_VALUE_0508"),
+                   (509, "HugeEnum_VALUE_0509"), (510, "HugeEnum_VALUE_0510"),
+                   (511, "HugeEnum_VALUE_0511"), (512, "HugeEnum_VALUE_0512"),
+                   (513, "HugeEnum_VALUE_0513"), (514, "HugeEnum_VALUE_0514"),
+                   (515, "HugeEnum_VALUE_0515"), (516, "HugeEnum_VALUE_0516"),
+                   (517, "HugeEnum_VALUE_0517"), (518, "HugeEnum_VALUE_0518"),
+                   (519, "HugeEnum_VALUE_0519"), (520, "HugeEnum_VALUE_0520"),
+                   (521, "HugeEnum_VALUE_0521"), (522, "HugeEnum_VALUE_0522"),
+                   (523, "HugeEnum_VALUE_0523"), (524, "HugeEnum_VALUE_0524"),
+                   (525, "HugeEnum_VALUE_0525"), (526, "HugeEnum_VALUE_0526"),
+                   (527, "HugeEnum_VALUE_0527"), (528, "HugeEnum_VALUE_0528"),
+                   (529, "HugeEnum_VALUE_0529"), (530, "HugeEnum_VALUE_0530"),
+                   (531, "HugeEnum_VALUE_0531"), (532, "HugeEnum_VALUE_0532"),
+                   (533, "HugeEnum_VALUE_0533"), (534, "HugeEnum_VALUE_0534"),
+                   (535, "HugeEnum_VALUE_0535"), (536, "HugeEnum_VALUE_0536"),
+                   (537, "HugeEnum_VALUE_0537"), (538, "HugeEnum_VALUE_0538"),
+                   (539, "HugeEnum_VALUE_0539"), (540, "HugeEnum_VALUE_0540"),
+                   (541, "HugeEnum_VALUE_0541"), (542, "HugeEnum_VALUE_0542"),
+                   (543, "HugeEnum_VALUE_0543"), (544, "HugeEnum_VALUE_0544"),
+                   (545, "HugeEnum_VALUE_0545"), (546, "HugeEnum_VALUE_0546"),
+                   (547, "HugeEnum_VALUE_0547"), (548, "HugeEnum_VALUE_0548"),
+                   (549, "HugeEnum_VALUE_0549"), (550, "HugeEnum_VALUE_0550"),
+                   (551, "HugeEnum_VALUE_0551"), (552, "HugeEnum_VALUE_0552"),
+                   (553, "HugeEnum_VALUE_0553"), (554, "HugeEnum_VALUE_0554"),
+                   (555, "HugeEnum_VALUE_0555"), (556, "HugeEnum_VALUE_0556"),
+                   (557, "HugeEnum_VALUE_0557"), (558, "HugeEnum_VALUE_0558"),
+                   (559, "HugeEnum_VALUE_0559"), (560, "HugeEnum_VALUE_0560"),
+                   (561, "HugeEnum_VALUE_0561"), (562, "HugeEnum_VALUE_0562"),
+                   (563, "HugeEnum_VALUE_0563"), (564, "HugeEnum_VALUE_0564"),
+                   (565, "HugeEnum_VALUE_0565"), (566, "HugeEnum_VALUE_0566"),
+                   (567, "HugeEnum_VALUE_0567"), (568, "HugeEnum_VALUE_0568"),
+                   (569, "HugeEnum_VALUE_0569"), (570, "HugeEnum_VALUE_0570"),
+                   (571, "HugeEnum_VALUE_0571"), (572, "HugeEnum_VALUE_0572"),
+                   (573, "HugeEnum_VALUE_0573"), (574, "HugeEnum_VALUE_0574"),
+                   (575, "HugeEnum_VALUE_0575"), (576, "HugeEnum_VALUE_0576"),
+                   (577, "HugeEnum_VALUE_0577"), (578, "HugeEnum_VALUE_0578"),
+                   (579, "HugeEnum_VALUE_0579"), (580, "HugeEnum_VALUE_0580"),
+                   (581, "HugeEnum_VALUE_0581"), (582, "HugeEnum_VALUE_0582"),
+                   (583, "HugeEnum_VALUE_0583"), (584, "HugeEnum_VALUE_0584"),
+                   (585, "HugeEnum_VALUE_0585"), (586, "HugeEnum_VALUE_0586"),
+                   (587, "HugeEnum_VALUE_0587"), (588, "HugeEnum_VALUE_0588"),
+                   (589, "HugeEnum_VALUE_0589"), (590, "HugeEnum_VALUE_0590"),
+                   (591, "HugeEnum_VALUE_0591"), (592, "HugeEnum_VALUE_0592"),
+                   (593, "HugeEnum_VALUE_0593"), (594, "HugeEnum_VALUE_0594"),
+                   (595, "HugeEnum_VALUE_0595"), (596, "HugeEnum_VALUE_0596"),
+                   (597, "HugeEnum_VALUE_0597"), (598, "HugeEnum_VALUE_0598"),
+                   (599, "HugeEnum_VALUE_0599"), (600, "HugeEnum_VALUE_0600"),
+                   (601, "HugeEnum_VALUE_0601"), (602, "HugeEnum_VALUE_0602"),
+                   (603, "HugeEnum_VALUE_0603"), (604, "HugeEnum_VALUE_0604"),
+                   (605, "HugeEnum_VALUE_0605"), (606, "HugeEnum_VALUE_0606"),
+                   (607, "HugeEnum_VALUE_0607"), (608, "HugeEnum_VALUE_0608"),
+                   (609, "HugeEnum_VALUE_0609"), (610, "HugeEnum_VALUE_0610"),
+                   (611, "HugeEnum_VALUE_0611"), (612, "HugeEnum_VALUE_0612"),
+                   (613, "HugeEnum_VALUE_0613"), (614, "HugeEnum_VALUE_0614"),
+                   (615, "HugeEnum_VALUE_0615"), (616, "HugeEnum_VALUE_0616"),
+                   (617, "HugeEnum_VALUE_0617"), (618, "HugeEnum_VALUE_0618"),
+                   (619, "HugeEnum_VALUE_0619"), (620, "HugeEnum_VALUE_0620"),
+                   (621, "HugeEnum_VALUE_0621"), (622, "HugeEnum_VALUE_0622"),
+                   (623, "HugeEnum_VALUE_0623"), (624, "HugeEnum_VALUE_0624"),
+                   (625, "HugeEnum_VALUE_0625"), (626, "HugeEnum_VALUE_0626"),
+                   (627, "HugeEnum_VALUE_0627"), (628, "HugeEnum_VALUE_0628"),
+                   (629, "HugeEnum_VALUE_0629"), (630, "HugeEnum_VALUE_0630"),
+                   (631, "HugeEnum_VALUE_0631"), (632, "HugeEnum_VALUE_0632"),
+                   (633, "HugeEnum_VALUE_0633"), (634, "HugeEnum_VALUE_0634"),
+                   (635, "HugeEnum_VALUE_0635"), (636, "HugeEnum_VALUE_0636"),
+                   (637, "HugeEnum_VALUE_0637"), (638, "HugeEnum_VALUE_0638"),
+                   (639, "HugeEnum_VALUE_0639"), (640, "HugeEnum_VALUE_0640"),
+                   (641, "HugeEnum_VALUE_0641"), (642, "HugeEnum_VALUE_0642"),
+                   (643, "HugeEnum_VALUE_0643"), (644, "HugeEnum_VALUE_0644"),
+                   (645, "HugeEnum_VALUE_0645"), (646, "HugeEnum_VALUE_0646"),
+                   (647, "HugeEnum_VALUE_0647"), (648, "HugeEnum_VALUE_0648"),
+                   (649, "HugeEnum_VALUE_0649"), (650, "HugeEnum_VALUE_0650"),
+                   (651, "HugeEnum_VALUE_0651"), (652, "HugeEnum_VALUE_0652"),
+                   (653, "HugeEnum_VALUE_0653"), (654, "HugeEnum_VALUE_0654"),
+                   (655, "HugeEnum_VALUE_0655"), (656, "HugeEnum_VALUE_0656"),
+                   (657, "HugeEnum_VALUE_0657"), (658, "HugeEnum_VALUE_0658"),
+                   (659, "HugeEnum_VALUE_0659"), (660, "HugeEnum_VALUE_0660"),
+                   (661, "HugeEnum_VALUE_0661"), (662, "HugeEnum_VALUE_0662"),
+                   (663, "HugeEnum_VALUE_0663"), (664, "HugeEnum_VALUE_0664"),
+                   (665, "HugeEnum_VALUE_0665"), (666, "HugeEnum_VALUE_0666"),
+                   (667, "HugeEnum_VALUE_0667"), (668, "HugeEnum_VALUE_0668"),
+                   (669, "HugeEnum_VALUE_0669"), (670, "HugeEnum_VALUE_0670"),
+                   (671, "HugeEnum_VALUE_0671"), (672, "HugeEnum_VALUE_0672"),
+                   (673, "HugeEnum_VALUE_0673"), (674, "HugeEnum_VALUE_0674"),
+                   (675, "HugeEnum_VALUE_0675"), (676, "HugeEnum_VALUE_0676"),
+                   (677, "HugeEnum_VALUE_0677"), (678, "HugeEnum_VALUE_0678"),
+                   (679, "HugeEnum_VALUE_0679"), (680, "HugeEnum_VALUE_0680"),
+                   (681, "HugeEnum_VALUE_0681"), (682, "HugeEnum_VALUE_0682"),
+                   (683, "HugeEnum_VALUE_0683"), (684, "HugeEnum_VALUE_0684"),
+                   (685, "HugeEnum_VALUE_0685"), (686, "HugeEnum_VALUE_0686"),
+                   (687, "HugeEnum_VALUE_0687"), (688, "HugeEnum_VALUE_0688"),
+                   (689, "HugeEnum_VALUE_0689"), (690, "HugeEnum_VALUE_0690"),
+                   (691, "HugeEnum_VALUE_0691"), (692, "HugeEnum_VALUE_0692"),
+                   (693, "HugeEnum_VALUE_0693"), (694, "HugeEnum_VALUE_0694"),
+                   (695, "HugeEnum_VALUE_0695"), (696, "HugeEnum_VALUE_0696"),
+                   (697, "HugeEnum_VALUE_0697"), (698, "HugeEnum_VALUE_0698"),
+                   (699, "HugeEnum_VALUE_0699"), (700, "HugeEnum_VALUE_0700"),
+                   (701, "HugeEnum_VALUE_0701"), (702, "HugeEnum_VALUE_0702"),
+                   (703, "HugeEnum_VALUE_0703"), (704, "HugeEnum_VALUE_0704"),
+                   (705, "HugeEnum_VALUE_0705"), (706, "HugeEnum_VALUE_0706"),
+                   (707, "HugeEnum_VALUE_0707"), (708, "HugeEnum_VALUE_0708"),
+                   (709, "HugeEnum_VALUE_0709"), (710, "HugeEnum_VALUE_0710"),
+                   (711, "HugeEnum_VALUE_0711"), (712, "HugeEnum_VALUE_0712"),
+                   (713, "HugeEnum_VALUE_0713"), (714, "HugeEnum_VALUE_0714"),
+                   (715, "HugeEnum_VALUE_0715"), (716, "HugeEnum_VALUE_0716"),
+                   (717, "HugeEnum_VALUE_0717"), (718, "HugeEnum_VALUE_0718"),
+                   (719, "HugeEnum_VALUE_0719"), (720, "HugeEnum_VALUE_0720"),
+                   (721, "HugeEnum_VALUE_0721"), (722, "HugeEnum_VALUE_0722"),
+                   (723, "HugeEnum_VALUE_0723"), (724, "HugeEnum_VALUE_0724"),
+                   (725, "HugeEnum_VALUE_0725"), (726, "HugeEnum_VALUE_0726"),
+                   (727, "HugeEnum_VALUE_0727"), (728, "HugeEnum_VALUE_0728"),
+                   (729, "HugeEnum_VALUE_0729"), (730, "HugeEnum_VALUE_0730"),
+                   (731, "HugeEnum_VALUE_0731"), (732, "HugeEnum_VALUE_0732"),
+                   (733, "HugeEnum_VALUE_0733"), (734, "HugeEnum_VALUE_0734"),
+                   (735, "HugeEnum_VALUE_0735"), (736, "HugeEnum_VALUE_0736"),
+                   (737, "HugeEnum_VALUE_0737"), (738, "HugeEnum_VALUE_0738"),
+                   (739, "HugeEnum_VALUE_0739"), (740, "HugeEnum_VALUE_0740"),
+                   (741, "HugeEnum_VALUE_0741"), (742, "HugeEnum_VALUE_0742"),
+                   (743, "HugeEnum_VALUE_0743"), (744, "HugeEnum_VALUE_0744"),
+                   (745, "HugeEnum_VALUE_0745"), (746, "HugeEnum_VALUE_0746"),
+                   (747, "HugeEnum_VALUE_0747"), (748, "HugeEnum_VALUE_0748"),
+                   (749, "HugeEnum_VALUE_0749"), (750, "HugeEnum_VALUE_0750"),
+                   (751, "HugeEnum_VALUE_0751"), (752, "HugeEnum_VALUE_0752"),
+                   (753, "HugeEnum_VALUE_0753"), (754, "HugeEnum_VALUE_0754"),
+                   (755, "HugeEnum_VALUE_0755"), (756, "HugeEnum_VALUE_0756"),
+                   (757, "HugeEnum_VALUE_0757"), (758, "HugeEnum_VALUE_0758"),
+                   (759, "HugeEnum_VALUE_0759"), (760, "HugeEnum_VALUE_0760"),
+                   (761, "HugeEnum_VALUE_0761"), (762, "HugeEnum_VALUE_0762"),
+                   (763, "HugeEnum_VALUE_0763"), (764, "HugeEnum_VALUE_0764"),
+                   (765, "HugeEnum_VALUE_0765"), (766, "HugeEnum_VALUE_0766"),
+                   (767, "HugeEnum_VALUE_0767"), (768, "HugeEnum_VALUE_0768"),
+                   (769, "HugeEnum_VALUE_0769"), (770, "HugeEnum_VALUE_0770"),
+                   (771, "HugeEnum_VALUE_0771"), (772, "HugeEnum_VALUE_0772"),
+                   (773, "HugeEnum_VALUE_0773"), (774, "HugeEnum_VALUE_0774"),
+                   (775, "HugeEnum_VALUE_0775"), (776, "HugeEnum_VALUE_0776"),
+                   (777, "HugeEnum_VALUE_0777"), (778, "HugeEnum_VALUE_0778"),
+                   (779, "HugeEnum_VALUE_0779"), (780, "HugeEnum_VALUE_0780"),
+                   (781, "HugeEnum_VALUE_0781"), (782, "HugeEnum_VALUE_0782"),
+                   (783, "HugeEnum_VALUE_0783"), (784, "HugeEnum_VALUE_0784"),
+                   (785, "HugeEnum_VALUE_0785"), (786, "HugeEnum_VALUE_0786"),
+                   (787, "HugeEnum_VALUE_0787"), (788, "HugeEnum_VALUE_0788"),
+                   (789, "HugeEnum_VALUE_0789"), (790, "HugeEnum_VALUE_0790"),
+                   (791, "HugeEnum_VALUE_0791"), (792, "HugeEnum_VALUE_0792"),
+                   (793, "HugeEnum_VALUE_0793"), (794, "HugeEnum_VALUE_0794"),
+                   (795, "HugeEnum_VALUE_0795"), (796, "HugeEnum_VALUE_0796"),
+                   (797, "HugeEnum_VALUE_0797"), (798, "HugeEnum_VALUE_0798"),
+                   (799, "HugeEnum_VALUE_0799"), (800, "HugeEnum_VALUE_0800"),
+                   (801, "HugeEnum_VALUE_0801"), (802, "HugeEnum_VALUE_0802"),
+                   (803, "HugeEnum_VALUE_0803"), (804, "HugeEnum_VALUE_0804"),
+                   (805, "HugeEnum_VALUE_0805"), (806, "HugeEnum_VALUE_0806"),
+                   (807, "HugeEnum_VALUE_0807"), (808, "HugeEnum_VALUE_0808"),
+                   (809, "HugeEnum_VALUE_0809"), (810, "HugeEnum_VALUE_0810"),
+                   (811, "HugeEnum_VALUE_0811"), (812, "HugeEnum_VALUE_0812"),
+                   (813, "HugeEnum_VALUE_0813"), (814, "HugeEnum_VALUE_0814"),
+                   (815, "HugeEnum_VALUE_0815"), (816, "HugeEnum_VALUE_0816"),
+                   (817, "HugeEnum_VALUE_0817"), (818, "HugeEnum_VALUE_0818"),
+                   (819, "HugeEnum_VALUE_0819"), (820, "HugeEnum_VALUE_0820"),
+                   (821, "HugeEnum_VALUE_0821"), (822, "HugeEnum_VALUE_0822"),
+                   (823, "HugeEnum_VALUE_0823"), (824, "HugeEnum_VALUE_0824"),
+                   (825, "HugeEnum_VALUE_0825"), (826, "HugeEnum_VALUE_0826"),
+                   (827, "HugeEnum_VALUE_0827"), (828, "HugeEnum_VALUE_0828"),
+                   (829, "HugeEnum_VALUE_0829"), (830, "HugeEnum_VALUE_0830"),
+                   (831, "HugeEnum_VALUE_0831"), (832, "HugeEnum_VALUE_0832"),
+                   (833, "HugeEnum_VALUE_0833"), (834, "HugeEnum_VALUE_0834"),
+                   (835, "HugeEnum_VALUE_0835"), (836, "HugeEnum_VALUE_0836"),
+                   (837, "HugeEnum_VALUE_0837"), (838, "HugeEnum_VALUE_0838"),
+                   (839, "HugeEnum_VALUE_0839"), (840, "HugeEnum_VALUE_0840"),
+                   (841, "HugeEnum_VALUE_0841"), (842, "HugeEnum_VALUE_0842"),
+                   (843, "HugeEnum_VALUE_0843"), (844, "HugeEnum_VALUE_0844"),
+                   (845, "HugeEnum_VALUE_0845"), (846, "HugeEnum_VALUE_0846"),
+                   (847, "HugeEnum_VALUE_0847"), (848, "HugeEnum_VALUE_0848"),
+                   (849, "HugeEnum_VALUE_0849"), (850, "HugeEnum_VALUE_0850"),
+                   (851, "HugeEnum_VALUE_0851"), (852, "HugeEnum_VALUE_0852"),
+                   (853, "HugeEnum_VALUE_0853"), (854, "HugeEnum_VALUE_0854"),
+                   (855, "HugeEnum_VALUE_0855"), (856, "HugeEnum_VALUE_0856"),
+                   (857, "HugeEnum_VALUE_0857"), (858, "HugeEnum_VALUE_0858"),
+                   (859, "HugeEnum_VALUE_0859"), (860, "HugeEnum_VALUE_0860"),
+                   (861, "HugeEnum_VALUE_0861"), (862, "HugeEnum_VALUE_0862"),
+                   (863, "HugeEnum_VALUE_0863"), (864, "HugeEnum_VALUE_0864"),
+                   (865, "HugeEnum_VALUE_0865"), (866, "HugeEnum_VALUE_0866"),
+                   (867, "HugeEnum_VALUE_0867"), (868, "HugeEnum_VALUE_0868"),
+                   (869, "HugeEnum_VALUE_0869"), (870, "HugeEnum_VALUE_0870"),
+                   (871, "HugeEnum_VALUE_0871"), (872, "HugeEnum_VALUE_0872"),
+                   (873, "HugeEnum_VALUE_0873"), (874, "HugeEnum_VALUE_0874"),
+                   (875, "HugeEnum_VALUE_0875"), (876, "HugeEnum_VALUE_0876"),
+                   (877, "HugeEnum_VALUE_0877"), (878, "HugeEnum_VALUE_0878"),
+                   (879, "HugeEnum_VALUE_0879"), (880, "HugeEnum_VALUE_0880"),
+                   (881, "HugeEnum_VALUE_0881"), (882, "HugeEnum_VALUE_0882"),
+                   (883, "HugeEnum_VALUE_0883"), (884, "HugeEnum_VALUE_0884"),
+                   (885, "HugeEnum_VALUE_0885"), (886, "HugeEnum_VALUE_0886"),
+                   (887, "HugeEnum_VALUE_0887"), (888, "HugeEnum_VALUE_0888"),
+                   (889, "HugeEnum_VALUE_0889"), (890, "HugeEnum_VALUE_0890"),
+                   (891, "HugeEnum_VALUE_0891"), (892, "HugeEnum_VALUE_0892"),
+                   (893, "HugeEnum_VALUE_0893"), (894, "HugeEnum_VALUE_0894"),
+                   (895, "HugeEnum_VALUE_0895"), (896, "HugeEnum_VALUE_0896"),
+                   (897, "HugeEnum_VALUE_0897"), (898, "HugeEnum_VALUE_0898"),
+                   (899, "HugeEnum_VALUE_0899"), (900, "HugeEnum_VALUE_0900"),
+                   (901, "HugeEnum_VALUE_0901"), (902, "HugeEnum_VALUE_0902"),
+                   (903, "HugeEnum_VALUE_0903"), (904, "HugeEnum_VALUE_0904"),
+                   (905, "HugeEnum_VALUE_0905"), (906, "HugeEnum_VALUE_0906"),
+                   (907, "HugeEnum_VALUE_0907"), (908, "HugeEnum_VALUE_0908"),
+                   (909, "HugeEnum_VALUE_0909"), (910, "HugeEnum_VALUE_0910"),
+                   (911, "HugeEnum_VALUE_0911"), (912, "HugeEnum_VALUE_0912"),
+                   (913, "HugeEnum_VALUE_0913"), (914, "HugeEnum_VALUE_0914"),
+                   (915, "HugeEnum_VALUE_0915"), (916, "HugeEnum_VALUE_0916"),
+                   (917, "HugeEnum_VALUE_0917"), (918, "HugeEnum_VALUE_0918"),
+                   (919, "HugeEnum_VALUE_0919"), (920, "HugeEnum_VALUE_0920"),
+                   (921, "HugeEnum_VALUE_0921"), (922, "HugeEnum_VALUE_0922"),
+                   (923, "HugeEnum_VALUE_0923"), (924, "HugeEnum_VALUE_0924"),
+                   (925, "HugeEnum_VALUE_0925"), (926, "HugeEnum_VALUE_0926"),
+                   (927, "HugeEnum_VALUE_0927"), (928, "HugeEnum_VALUE_0928"),
+                   (929, "HugeEnum_VALUE_0929"), (930, "HugeEnum_VALUE_0930"),
+                   (931, "HugeEnum_VALUE_0931"), (932, "HugeEnum_VALUE_0932"),
+                   (933, "HugeEnum_VALUE_0933"), (934, "HugeEnum_VALUE_0934"),
+                   (935, "HugeEnum_VALUE_0935"), (936, "HugeEnum_VALUE_0936"),
+                   (937, "HugeEnum_VALUE_0937"), (938, "HugeEnum_VALUE_0938"),
+                   (939, "HugeEnum_VALUE_0939"), (940, "HugeEnum_VALUE_0940"),
+                   (941, "HugeEnum_VALUE_0941"), (942, "HugeEnum_VALUE_0942"),
+                   (943, "HugeEnum_VALUE_0943"), (944, "HugeEnum_VALUE_0944"),
+                   (945, "HugeEnum_VALUE_0945"), (946, "HugeEnum_VALUE_0946"),
+                   (947, "HugeEnum_VALUE_0947"), (948, "HugeEnum_VALUE_0948"),
+                   (949, "HugeEnum_VALUE_0949"), (950, "HugeEnum_VALUE_0950"),
+                   (951, "HugeEnum_VALUE_0951"), (952, "HugeEnum_VALUE_0952"),
+                   (953, "HugeEnum_VALUE_0953"), (954, "HugeEnum_VALUE_0954"),
+                   (955, "HugeEnum_VALUE_0955"), (956, "HugeEnum_VALUE_0956"),
+                   (957, "HugeEnum_VALUE_0957"), (958, "HugeEnum_VALUE_0958"),
+                   (959, "HugeEnum_VALUE_0959"), (960, "HugeEnum_VALUE_0960"),
+                   (961, "HugeEnum_VALUE_0961"), (962, "HugeEnum_VALUE_0962"),
+                   (963, "HugeEnum_VALUE_0963"), (964, "HugeEnum_VALUE_0964"),
+                   (965, "HugeEnum_VALUE_0965"), (966, "HugeEnum_VALUE_0966"),
+                   (967, "HugeEnum_VALUE_0967"), (968, "HugeEnum_VALUE_0968"),
+                   (969, "HugeEnum_VALUE_0969"), (970, "HugeEnum_VALUE_0970"),
+                   (971, "HugeEnum_VALUE_0971"), (972, "HugeEnum_VALUE_0972"),
+                   (973, "HugeEnum_VALUE_0973"), (974, "HugeEnum_VALUE_0974"),
+                   (975, "HugeEnum_VALUE_0975"), (976, "HugeEnum_VALUE_0976"),
+                   (977, "HugeEnum_VALUE_0977"), (978, "HugeEnum_VALUE_0978"),
+                   (979, "HugeEnum_VALUE_0979"), (980, "HugeEnum_VALUE_0980"),
+                   (981, "HugeEnum_VALUE_0981"), (982, "HugeEnum_VALUE_0982"),
+                   (983, "HugeEnum_VALUE_0983"), (984, "HugeEnum_VALUE_0984"),
+                   (985, "HugeEnum_VALUE_0985"), (986, "HugeEnum_VALUE_0986"),
+                   (987, "HugeEnum_VALUE_0987"), (988, "HugeEnum_VALUE_0988"),
+                   (989, "HugeEnum_VALUE_0989"), (990, "HugeEnum_VALUE_0990"),
+                   (991, "HugeEnum_VALUE_0991"), (992, "HugeEnum_VALUE_0992"),
+                   (993, "HugeEnum_VALUE_0993"), (994, "HugeEnum_VALUE_0994"),
+                   (995, "HugeEnum_VALUE_0995"), (996, "HugeEnum_VALUE_0996"),
+                   (997, "HugeEnum_VALUE_0997"), (998, "HugeEnum_VALUE_0998"),
+                   (999, "HugeEnum_VALUE_0999"), (1000, "HugeEnum_VALUE_1000")],
+                GHC.noinline Prelude.id [(1001, "HugeEnum_VALUE_1001")]])
+
+instance Thrift.ThriftEnum HugeEnum where
+  toThriftEnum __val = HugeEnum (Prelude.fromIntegral __val)
+  fromThriftEnum (HugeEnum __val) = Prelude.fromIntegral __val
+  allThriftEnumValues
+    = [hugeEnum_VALUE_0001, hugeEnum_VALUE_0002, hugeEnum_VALUE_0003,
+       hugeEnum_VALUE_0004, hugeEnum_VALUE_0005, hugeEnum_VALUE_0006,
+       hugeEnum_VALUE_0007, hugeEnum_VALUE_0008, hugeEnum_VALUE_0009,
+       hugeEnum_VALUE_0010, hugeEnum_VALUE_0011, hugeEnum_VALUE_0012,
+       hugeEnum_VALUE_0013, hugeEnum_VALUE_0014, hugeEnum_VALUE_0015,
+       hugeEnum_VALUE_0016, hugeEnum_VALUE_0017, hugeEnum_VALUE_0018,
+       hugeEnum_VALUE_0019, hugeEnum_VALUE_0020, hugeEnum_VALUE_0021,
+       hugeEnum_VALUE_0022, hugeEnum_VALUE_0023, hugeEnum_VALUE_0024,
+       hugeEnum_VALUE_0025, hugeEnum_VALUE_0026, hugeEnum_VALUE_0027,
+       hugeEnum_VALUE_0028, hugeEnum_VALUE_0029, hugeEnum_VALUE_0030,
+       hugeEnum_VALUE_0031, hugeEnum_VALUE_0032, hugeEnum_VALUE_0033,
+       hugeEnum_VALUE_0034, hugeEnum_VALUE_0035, hugeEnum_VALUE_0036,
+       hugeEnum_VALUE_0037, hugeEnum_VALUE_0038, hugeEnum_VALUE_0039,
+       hugeEnum_VALUE_0040, hugeEnum_VALUE_0041, hugeEnum_VALUE_0042,
+       hugeEnum_VALUE_0043, hugeEnum_VALUE_0044, hugeEnum_VALUE_0045,
+       hugeEnum_VALUE_0046, hugeEnum_VALUE_0047, hugeEnum_VALUE_0048,
+       hugeEnum_VALUE_0049, hugeEnum_VALUE_0050, hugeEnum_VALUE_0051,
+       hugeEnum_VALUE_0052, hugeEnum_VALUE_0053, hugeEnum_VALUE_0054,
+       hugeEnum_VALUE_0055, hugeEnum_VALUE_0056, hugeEnum_VALUE_0057,
+       hugeEnum_VALUE_0058, hugeEnum_VALUE_0059, hugeEnum_VALUE_0060,
+       hugeEnum_VALUE_0061, hugeEnum_VALUE_0062, hugeEnum_VALUE_0063,
+       hugeEnum_VALUE_0064, hugeEnum_VALUE_0065, hugeEnum_VALUE_0066,
+       hugeEnum_VALUE_0067, hugeEnum_VALUE_0068, hugeEnum_VALUE_0069,
+       hugeEnum_VALUE_0070, hugeEnum_VALUE_0071, hugeEnum_VALUE_0072,
+       hugeEnum_VALUE_0073, hugeEnum_VALUE_0074, hugeEnum_VALUE_0075,
+       hugeEnum_VALUE_0076, hugeEnum_VALUE_0077, hugeEnum_VALUE_0078,
+       hugeEnum_VALUE_0079, hugeEnum_VALUE_0080, hugeEnum_VALUE_0081,
+       hugeEnum_VALUE_0082, hugeEnum_VALUE_0083, hugeEnum_VALUE_0084,
+       hugeEnum_VALUE_0085, hugeEnum_VALUE_0086, hugeEnum_VALUE_0087,
+       hugeEnum_VALUE_0088, hugeEnum_VALUE_0089, hugeEnum_VALUE_0090,
+       hugeEnum_VALUE_0091, hugeEnum_VALUE_0092, hugeEnum_VALUE_0093,
+       hugeEnum_VALUE_0094, hugeEnum_VALUE_0095, hugeEnum_VALUE_0096,
+       hugeEnum_VALUE_0097, hugeEnum_VALUE_0098, hugeEnum_VALUE_0099,
+       hugeEnum_VALUE_0100, hugeEnum_VALUE_0101, hugeEnum_VALUE_0102,
+       hugeEnum_VALUE_0103, hugeEnum_VALUE_0104, hugeEnum_VALUE_0105,
+       hugeEnum_VALUE_0106, hugeEnum_VALUE_0107, hugeEnum_VALUE_0108,
+       hugeEnum_VALUE_0109, hugeEnum_VALUE_0110, hugeEnum_VALUE_0111,
+       hugeEnum_VALUE_0112, hugeEnum_VALUE_0113, hugeEnum_VALUE_0114,
+       hugeEnum_VALUE_0115, hugeEnum_VALUE_0116, hugeEnum_VALUE_0117,
+       hugeEnum_VALUE_0118, hugeEnum_VALUE_0119, hugeEnum_VALUE_0120,
+       hugeEnum_VALUE_0121, hugeEnum_VALUE_0122, hugeEnum_VALUE_0123,
+       hugeEnum_VALUE_0124, hugeEnum_VALUE_0125, hugeEnum_VALUE_0126,
+       hugeEnum_VALUE_0127, hugeEnum_VALUE_0128, hugeEnum_VALUE_0129,
+       hugeEnum_VALUE_0130, hugeEnum_VALUE_0131, hugeEnum_VALUE_0132,
+       hugeEnum_VALUE_0133, hugeEnum_VALUE_0134, hugeEnum_VALUE_0135,
+       hugeEnum_VALUE_0136, hugeEnum_VALUE_0137, hugeEnum_VALUE_0138,
+       hugeEnum_VALUE_0139, hugeEnum_VALUE_0140, hugeEnum_VALUE_0141,
+       hugeEnum_VALUE_0142, hugeEnum_VALUE_0143, hugeEnum_VALUE_0144,
+       hugeEnum_VALUE_0145, hugeEnum_VALUE_0146, hugeEnum_VALUE_0147,
+       hugeEnum_VALUE_0148, hugeEnum_VALUE_0149, hugeEnum_VALUE_0150,
+       hugeEnum_VALUE_0151, hugeEnum_VALUE_0152, hugeEnum_VALUE_0153,
+       hugeEnum_VALUE_0154, hugeEnum_VALUE_0155, hugeEnum_VALUE_0156,
+       hugeEnum_VALUE_0157, hugeEnum_VALUE_0158, hugeEnum_VALUE_0159,
+       hugeEnum_VALUE_0160, hugeEnum_VALUE_0161, hugeEnum_VALUE_0162,
+       hugeEnum_VALUE_0163, hugeEnum_VALUE_0164, hugeEnum_VALUE_0165,
+       hugeEnum_VALUE_0166, hugeEnum_VALUE_0167, hugeEnum_VALUE_0168,
+       hugeEnum_VALUE_0169, hugeEnum_VALUE_0170, hugeEnum_VALUE_0171,
+       hugeEnum_VALUE_0172, hugeEnum_VALUE_0173, hugeEnum_VALUE_0174,
+       hugeEnum_VALUE_0175, hugeEnum_VALUE_0176, hugeEnum_VALUE_0177,
+       hugeEnum_VALUE_0178, hugeEnum_VALUE_0179, hugeEnum_VALUE_0180,
+       hugeEnum_VALUE_0181, hugeEnum_VALUE_0182, hugeEnum_VALUE_0183,
+       hugeEnum_VALUE_0184, hugeEnum_VALUE_0185, hugeEnum_VALUE_0186,
+       hugeEnum_VALUE_0187, hugeEnum_VALUE_0188, hugeEnum_VALUE_0189,
+       hugeEnum_VALUE_0190, hugeEnum_VALUE_0191, hugeEnum_VALUE_0192,
+       hugeEnum_VALUE_0193, hugeEnum_VALUE_0194, hugeEnum_VALUE_0195,
+       hugeEnum_VALUE_0196, hugeEnum_VALUE_0197, hugeEnum_VALUE_0198,
+       hugeEnum_VALUE_0199, hugeEnum_VALUE_0200, hugeEnum_VALUE_0201,
+       hugeEnum_VALUE_0202, hugeEnum_VALUE_0203, hugeEnum_VALUE_0204,
+       hugeEnum_VALUE_0205, hugeEnum_VALUE_0206, hugeEnum_VALUE_0207,
+       hugeEnum_VALUE_0208, hugeEnum_VALUE_0209, hugeEnum_VALUE_0210,
+       hugeEnum_VALUE_0211, hugeEnum_VALUE_0212, hugeEnum_VALUE_0213,
+       hugeEnum_VALUE_0214, hugeEnum_VALUE_0215, hugeEnum_VALUE_0216,
+       hugeEnum_VALUE_0217, hugeEnum_VALUE_0218, hugeEnum_VALUE_0219,
+       hugeEnum_VALUE_0220, hugeEnum_VALUE_0221, hugeEnum_VALUE_0222,
+       hugeEnum_VALUE_0223, hugeEnum_VALUE_0224, hugeEnum_VALUE_0225,
+       hugeEnum_VALUE_0226, hugeEnum_VALUE_0227, hugeEnum_VALUE_0228,
+       hugeEnum_VALUE_0229, hugeEnum_VALUE_0230, hugeEnum_VALUE_0231,
+       hugeEnum_VALUE_0232, hugeEnum_VALUE_0233, hugeEnum_VALUE_0234,
+       hugeEnum_VALUE_0235, hugeEnum_VALUE_0236, hugeEnum_VALUE_0237,
+       hugeEnum_VALUE_0238, hugeEnum_VALUE_0239, hugeEnum_VALUE_0240,
+       hugeEnum_VALUE_0241, hugeEnum_VALUE_0242, hugeEnum_VALUE_0243,
+       hugeEnum_VALUE_0244, hugeEnum_VALUE_0245, hugeEnum_VALUE_0246,
+       hugeEnum_VALUE_0247, hugeEnum_VALUE_0248, hugeEnum_VALUE_0249,
+       hugeEnum_VALUE_0250, hugeEnum_VALUE_0251, hugeEnum_VALUE_0252,
+       hugeEnum_VALUE_0253, hugeEnum_VALUE_0254, hugeEnum_VALUE_0255,
+       hugeEnum_VALUE_0256, hugeEnum_VALUE_0257, hugeEnum_VALUE_0258,
+       hugeEnum_VALUE_0259, hugeEnum_VALUE_0260, hugeEnum_VALUE_0261,
+       hugeEnum_VALUE_0262, hugeEnum_VALUE_0263, hugeEnum_VALUE_0264,
+       hugeEnum_VALUE_0265, hugeEnum_VALUE_0266, hugeEnum_VALUE_0267,
+       hugeEnum_VALUE_0268, hugeEnum_VALUE_0269, hugeEnum_VALUE_0270,
+       hugeEnum_VALUE_0271, hugeEnum_VALUE_0272, hugeEnum_VALUE_0273,
+       hugeEnum_VALUE_0274, hugeEnum_VALUE_0275, hugeEnum_VALUE_0276,
+       hugeEnum_VALUE_0277, hugeEnum_VALUE_0278, hugeEnum_VALUE_0279,
+       hugeEnum_VALUE_0280, hugeEnum_VALUE_0281, hugeEnum_VALUE_0282,
+       hugeEnum_VALUE_0283, hugeEnum_VALUE_0284, hugeEnum_VALUE_0285,
+       hugeEnum_VALUE_0286, hugeEnum_VALUE_0287, hugeEnum_VALUE_0288,
+       hugeEnum_VALUE_0289, hugeEnum_VALUE_0290, hugeEnum_VALUE_0291,
+       hugeEnum_VALUE_0292, hugeEnum_VALUE_0293, hugeEnum_VALUE_0294,
+       hugeEnum_VALUE_0295, hugeEnum_VALUE_0296, hugeEnum_VALUE_0297,
+       hugeEnum_VALUE_0298, hugeEnum_VALUE_0299, hugeEnum_VALUE_0300,
+       hugeEnum_VALUE_0301, hugeEnum_VALUE_0302, hugeEnum_VALUE_0303,
+       hugeEnum_VALUE_0304, hugeEnum_VALUE_0305, hugeEnum_VALUE_0306,
+       hugeEnum_VALUE_0307, hugeEnum_VALUE_0308, hugeEnum_VALUE_0309,
+       hugeEnum_VALUE_0310, hugeEnum_VALUE_0311, hugeEnum_VALUE_0312,
+       hugeEnum_VALUE_0313, hugeEnum_VALUE_0314, hugeEnum_VALUE_0315,
+       hugeEnum_VALUE_0316, hugeEnum_VALUE_0317, hugeEnum_VALUE_0318,
+       hugeEnum_VALUE_0319, hugeEnum_VALUE_0320, hugeEnum_VALUE_0321,
+       hugeEnum_VALUE_0322, hugeEnum_VALUE_0323, hugeEnum_VALUE_0324,
+       hugeEnum_VALUE_0325, hugeEnum_VALUE_0326, hugeEnum_VALUE_0327,
+       hugeEnum_VALUE_0328, hugeEnum_VALUE_0329, hugeEnum_VALUE_0330,
+       hugeEnum_VALUE_0331, hugeEnum_VALUE_0332, hugeEnum_VALUE_0333,
+       hugeEnum_VALUE_0334, hugeEnum_VALUE_0335, hugeEnum_VALUE_0336,
+       hugeEnum_VALUE_0337, hugeEnum_VALUE_0338, hugeEnum_VALUE_0339,
+       hugeEnum_VALUE_0340, hugeEnum_VALUE_0341, hugeEnum_VALUE_0342,
+       hugeEnum_VALUE_0343, hugeEnum_VALUE_0344, hugeEnum_VALUE_0345,
+       hugeEnum_VALUE_0346, hugeEnum_VALUE_0347, hugeEnum_VALUE_0348,
+       hugeEnum_VALUE_0349, hugeEnum_VALUE_0350, hugeEnum_VALUE_0351,
+       hugeEnum_VALUE_0352, hugeEnum_VALUE_0353, hugeEnum_VALUE_0354,
+       hugeEnum_VALUE_0355, hugeEnum_VALUE_0356, hugeEnum_VALUE_0357,
+       hugeEnum_VALUE_0358, hugeEnum_VALUE_0359, hugeEnum_VALUE_0360,
+       hugeEnum_VALUE_0361, hugeEnum_VALUE_0362, hugeEnum_VALUE_0363,
+       hugeEnum_VALUE_0364, hugeEnum_VALUE_0365, hugeEnum_VALUE_0366,
+       hugeEnum_VALUE_0367, hugeEnum_VALUE_0368, hugeEnum_VALUE_0369,
+       hugeEnum_VALUE_0370, hugeEnum_VALUE_0371, hugeEnum_VALUE_0372,
+       hugeEnum_VALUE_0373, hugeEnum_VALUE_0374, hugeEnum_VALUE_0375,
+       hugeEnum_VALUE_0376, hugeEnum_VALUE_0377, hugeEnum_VALUE_0378,
+       hugeEnum_VALUE_0379, hugeEnum_VALUE_0380, hugeEnum_VALUE_0381,
+       hugeEnum_VALUE_0382, hugeEnum_VALUE_0383, hugeEnum_VALUE_0384,
+       hugeEnum_VALUE_0385, hugeEnum_VALUE_0386, hugeEnum_VALUE_0387,
+       hugeEnum_VALUE_0388, hugeEnum_VALUE_0389, hugeEnum_VALUE_0390,
+       hugeEnum_VALUE_0391, hugeEnum_VALUE_0392, hugeEnum_VALUE_0393,
+       hugeEnum_VALUE_0394, hugeEnum_VALUE_0395, hugeEnum_VALUE_0396,
+       hugeEnum_VALUE_0397, hugeEnum_VALUE_0398, hugeEnum_VALUE_0399,
+       hugeEnum_VALUE_0400, hugeEnum_VALUE_0401, hugeEnum_VALUE_0402,
+       hugeEnum_VALUE_0403, hugeEnum_VALUE_0404, hugeEnum_VALUE_0405,
+       hugeEnum_VALUE_0406, hugeEnum_VALUE_0407, hugeEnum_VALUE_0408,
+       hugeEnum_VALUE_0409, hugeEnum_VALUE_0410, hugeEnum_VALUE_0411,
+       hugeEnum_VALUE_0412, hugeEnum_VALUE_0413, hugeEnum_VALUE_0414,
+       hugeEnum_VALUE_0415, hugeEnum_VALUE_0416, hugeEnum_VALUE_0417,
+       hugeEnum_VALUE_0418, hugeEnum_VALUE_0419, hugeEnum_VALUE_0420,
+       hugeEnum_VALUE_0421, hugeEnum_VALUE_0422, hugeEnum_VALUE_0423,
+       hugeEnum_VALUE_0424, hugeEnum_VALUE_0425, hugeEnum_VALUE_0426,
+       hugeEnum_VALUE_0427, hugeEnum_VALUE_0428, hugeEnum_VALUE_0429,
+       hugeEnum_VALUE_0430, hugeEnum_VALUE_0431, hugeEnum_VALUE_0432,
+       hugeEnum_VALUE_0433, hugeEnum_VALUE_0434, hugeEnum_VALUE_0435,
+       hugeEnum_VALUE_0436, hugeEnum_VALUE_0437, hugeEnum_VALUE_0438,
+       hugeEnum_VALUE_0439, hugeEnum_VALUE_0440, hugeEnum_VALUE_0441,
+       hugeEnum_VALUE_0442, hugeEnum_VALUE_0443, hugeEnum_VALUE_0444,
+       hugeEnum_VALUE_0445, hugeEnum_VALUE_0446, hugeEnum_VALUE_0447,
+       hugeEnum_VALUE_0448, hugeEnum_VALUE_0449, hugeEnum_VALUE_0450,
+       hugeEnum_VALUE_0451, hugeEnum_VALUE_0452, hugeEnum_VALUE_0453,
+       hugeEnum_VALUE_0454, hugeEnum_VALUE_0455, hugeEnum_VALUE_0456,
+       hugeEnum_VALUE_0457, hugeEnum_VALUE_0458, hugeEnum_VALUE_0459,
+       hugeEnum_VALUE_0460, hugeEnum_VALUE_0461, hugeEnum_VALUE_0462,
+       hugeEnum_VALUE_0463, hugeEnum_VALUE_0464, hugeEnum_VALUE_0465,
+       hugeEnum_VALUE_0466, hugeEnum_VALUE_0467, hugeEnum_VALUE_0468,
+       hugeEnum_VALUE_0469, hugeEnum_VALUE_0470, hugeEnum_VALUE_0471,
+       hugeEnum_VALUE_0472, hugeEnum_VALUE_0473, hugeEnum_VALUE_0474,
+       hugeEnum_VALUE_0475, hugeEnum_VALUE_0476, hugeEnum_VALUE_0477,
+       hugeEnum_VALUE_0478, hugeEnum_VALUE_0479, hugeEnum_VALUE_0480,
+       hugeEnum_VALUE_0481, hugeEnum_VALUE_0482, hugeEnum_VALUE_0483,
+       hugeEnum_VALUE_0484, hugeEnum_VALUE_0485, hugeEnum_VALUE_0486,
+       hugeEnum_VALUE_0487, hugeEnum_VALUE_0488, hugeEnum_VALUE_0489,
+       hugeEnum_VALUE_0490, hugeEnum_VALUE_0491, hugeEnum_VALUE_0492,
+       hugeEnum_VALUE_0493, hugeEnum_VALUE_0494, hugeEnum_VALUE_0495,
+       hugeEnum_VALUE_0496, hugeEnum_VALUE_0497, hugeEnum_VALUE_0498,
+       hugeEnum_VALUE_0499, hugeEnum_VALUE_0500, hugeEnum_VALUE_0501,
+       hugeEnum_VALUE_0502, hugeEnum_VALUE_0503, hugeEnum_VALUE_0504,
+       hugeEnum_VALUE_0505, hugeEnum_VALUE_0506, hugeEnum_VALUE_0507,
+       hugeEnum_VALUE_0508, hugeEnum_VALUE_0509, hugeEnum_VALUE_0510,
+       hugeEnum_VALUE_0511, hugeEnum_VALUE_0512, hugeEnum_VALUE_0513,
+       hugeEnum_VALUE_0514, hugeEnum_VALUE_0515, hugeEnum_VALUE_0516,
+       hugeEnum_VALUE_0517, hugeEnum_VALUE_0518, hugeEnum_VALUE_0519,
+       hugeEnum_VALUE_0520, hugeEnum_VALUE_0521, hugeEnum_VALUE_0522,
+       hugeEnum_VALUE_0523, hugeEnum_VALUE_0524, hugeEnum_VALUE_0525,
+       hugeEnum_VALUE_0526, hugeEnum_VALUE_0527, hugeEnum_VALUE_0528,
+       hugeEnum_VALUE_0529, hugeEnum_VALUE_0530, hugeEnum_VALUE_0531,
+       hugeEnum_VALUE_0532, hugeEnum_VALUE_0533, hugeEnum_VALUE_0534,
+       hugeEnum_VALUE_0535, hugeEnum_VALUE_0536, hugeEnum_VALUE_0537,
+       hugeEnum_VALUE_0538, hugeEnum_VALUE_0539, hugeEnum_VALUE_0540,
+       hugeEnum_VALUE_0541, hugeEnum_VALUE_0542, hugeEnum_VALUE_0543,
+       hugeEnum_VALUE_0544, hugeEnum_VALUE_0545, hugeEnum_VALUE_0546,
+       hugeEnum_VALUE_0547, hugeEnum_VALUE_0548, hugeEnum_VALUE_0549,
+       hugeEnum_VALUE_0550, hugeEnum_VALUE_0551, hugeEnum_VALUE_0552,
+       hugeEnum_VALUE_0553, hugeEnum_VALUE_0554, hugeEnum_VALUE_0555,
+       hugeEnum_VALUE_0556, hugeEnum_VALUE_0557, hugeEnum_VALUE_0558,
+       hugeEnum_VALUE_0559, hugeEnum_VALUE_0560, hugeEnum_VALUE_0561,
+       hugeEnum_VALUE_0562, hugeEnum_VALUE_0563, hugeEnum_VALUE_0564,
+       hugeEnum_VALUE_0565, hugeEnum_VALUE_0566, hugeEnum_VALUE_0567,
+       hugeEnum_VALUE_0568, hugeEnum_VALUE_0569, hugeEnum_VALUE_0570,
+       hugeEnum_VALUE_0571, hugeEnum_VALUE_0572, hugeEnum_VALUE_0573,
+       hugeEnum_VALUE_0574, hugeEnum_VALUE_0575, hugeEnum_VALUE_0576,
+       hugeEnum_VALUE_0577, hugeEnum_VALUE_0578, hugeEnum_VALUE_0579,
+       hugeEnum_VALUE_0580, hugeEnum_VALUE_0581, hugeEnum_VALUE_0582,
+       hugeEnum_VALUE_0583, hugeEnum_VALUE_0584, hugeEnum_VALUE_0585,
+       hugeEnum_VALUE_0586, hugeEnum_VALUE_0587, hugeEnum_VALUE_0588,
+       hugeEnum_VALUE_0589, hugeEnum_VALUE_0590, hugeEnum_VALUE_0591,
+       hugeEnum_VALUE_0592, hugeEnum_VALUE_0593, hugeEnum_VALUE_0594,
+       hugeEnum_VALUE_0595, hugeEnum_VALUE_0596, hugeEnum_VALUE_0597,
+       hugeEnum_VALUE_0598, hugeEnum_VALUE_0599, hugeEnum_VALUE_0600,
+       hugeEnum_VALUE_0601, hugeEnum_VALUE_0602, hugeEnum_VALUE_0603,
+       hugeEnum_VALUE_0604, hugeEnum_VALUE_0605, hugeEnum_VALUE_0606,
+       hugeEnum_VALUE_0607, hugeEnum_VALUE_0608, hugeEnum_VALUE_0609,
+       hugeEnum_VALUE_0610, hugeEnum_VALUE_0611, hugeEnum_VALUE_0612,
+       hugeEnum_VALUE_0613, hugeEnum_VALUE_0614, hugeEnum_VALUE_0615,
+       hugeEnum_VALUE_0616, hugeEnum_VALUE_0617, hugeEnum_VALUE_0618,
+       hugeEnum_VALUE_0619, hugeEnum_VALUE_0620, hugeEnum_VALUE_0621,
+       hugeEnum_VALUE_0622, hugeEnum_VALUE_0623, hugeEnum_VALUE_0624,
+       hugeEnum_VALUE_0625, hugeEnum_VALUE_0626, hugeEnum_VALUE_0627,
+       hugeEnum_VALUE_0628, hugeEnum_VALUE_0629, hugeEnum_VALUE_0630,
+       hugeEnum_VALUE_0631, hugeEnum_VALUE_0632, hugeEnum_VALUE_0633,
+       hugeEnum_VALUE_0634, hugeEnum_VALUE_0635, hugeEnum_VALUE_0636,
+       hugeEnum_VALUE_0637, hugeEnum_VALUE_0638, hugeEnum_VALUE_0639,
+       hugeEnum_VALUE_0640, hugeEnum_VALUE_0641, hugeEnum_VALUE_0642,
+       hugeEnum_VALUE_0643, hugeEnum_VALUE_0644, hugeEnum_VALUE_0645,
+       hugeEnum_VALUE_0646, hugeEnum_VALUE_0647, hugeEnum_VALUE_0648,
+       hugeEnum_VALUE_0649, hugeEnum_VALUE_0650, hugeEnum_VALUE_0651,
+       hugeEnum_VALUE_0652, hugeEnum_VALUE_0653, hugeEnum_VALUE_0654,
+       hugeEnum_VALUE_0655, hugeEnum_VALUE_0656, hugeEnum_VALUE_0657,
+       hugeEnum_VALUE_0658, hugeEnum_VALUE_0659, hugeEnum_VALUE_0660,
+       hugeEnum_VALUE_0661, hugeEnum_VALUE_0662, hugeEnum_VALUE_0663,
+       hugeEnum_VALUE_0664, hugeEnum_VALUE_0665, hugeEnum_VALUE_0666,
+       hugeEnum_VALUE_0667, hugeEnum_VALUE_0668, hugeEnum_VALUE_0669,
+       hugeEnum_VALUE_0670, hugeEnum_VALUE_0671, hugeEnum_VALUE_0672,
+       hugeEnum_VALUE_0673, hugeEnum_VALUE_0674, hugeEnum_VALUE_0675,
+       hugeEnum_VALUE_0676, hugeEnum_VALUE_0677, hugeEnum_VALUE_0678,
+       hugeEnum_VALUE_0679, hugeEnum_VALUE_0680, hugeEnum_VALUE_0681,
+       hugeEnum_VALUE_0682, hugeEnum_VALUE_0683, hugeEnum_VALUE_0684,
+       hugeEnum_VALUE_0685, hugeEnum_VALUE_0686, hugeEnum_VALUE_0687,
+       hugeEnum_VALUE_0688, hugeEnum_VALUE_0689, hugeEnum_VALUE_0690,
+       hugeEnum_VALUE_0691, hugeEnum_VALUE_0692, hugeEnum_VALUE_0693,
+       hugeEnum_VALUE_0694, hugeEnum_VALUE_0695, hugeEnum_VALUE_0696,
+       hugeEnum_VALUE_0697, hugeEnum_VALUE_0698, hugeEnum_VALUE_0699,
+       hugeEnum_VALUE_0700, hugeEnum_VALUE_0701, hugeEnum_VALUE_0702,
+       hugeEnum_VALUE_0703, hugeEnum_VALUE_0704, hugeEnum_VALUE_0705,
+       hugeEnum_VALUE_0706, hugeEnum_VALUE_0707, hugeEnum_VALUE_0708,
+       hugeEnum_VALUE_0709, hugeEnum_VALUE_0710, hugeEnum_VALUE_0711,
+       hugeEnum_VALUE_0712, hugeEnum_VALUE_0713, hugeEnum_VALUE_0714,
+       hugeEnum_VALUE_0715, hugeEnum_VALUE_0716, hugeEnum_VALUE_0717,
+       hugeEnum_VALUE_0718, hugeEnum_VALUE_0719, hugeEnum_VALUE_0720,
+       hugeEnum_VALUE_0721, hugeEnum_VALUE_0722, hugeEnum_VALUE_0723,
+       hugeEnum_VALUE_0724, hugeEnum_VALUE_0725, hugeEnum_VALUE_0726,
+       hugeEnum_VALUE_0727, hugeEnum_VALUE_0728, hugeEnum_VALUE_0729,
+       hugeEnum_VALUE_0730, hugeEnum_VALUE_0731, hugeEnum_VALUE_0732,
+       hugeEnum_VALUE_0733, hugeEnum_VALUE_0734, hugeEnum_VALUE_0735,
+       hugeEnum_VALUE_0736, hugeEnum_VALUE_0737, hugeEnum_VALUE_0738,
+       hugeEnum_VALUE_0739, hugeEnum_VALUE_0740, hugeEnum_VALUE_0741,
+       hugeEnum_VALUE_0742, hugeEnum_VALUE_0743, hugeEnum_VALUE_0744,
+       hugeEnum_VALUE_0745, hugeEnum_VALUE_0746, hugeEnum_VALUE_0747,
+       hugeEnum_VALUE_0748, hugeEnum_VALUE_0749, hugeEnum_VALUE_0750,
+       hugeEnum_VALUE_0751, hugeEnum_VALUE_0752, hugeEnum_VALUE_0753,
+       hugeEnum_VALUE_0754, hugeEnum_VALUE_0755, hugeEnum_VALUE_0756,
+       hugeEnum_VALUE_0757, hugeEnum_VALUE_0758, hugeEnum_VALUE_0759,
+       hugeEnum_VALUE_0760, hugeEnum_VALUE_0761, hugeEnum_VALUE_0762,
+       hugeEnum_VALUE_0763, hugeEnum_VALUE_0764, hugeEnum_VALUE_0765,
+       hugeEnum_VALUE_0766, hugeEnum_VALUE_0767, hugeEnum_VALUE_0768,
+       hugeEnum_VALUE_0769, hugeEnum_VALUE_0770, hugeEnum_VALUE_0771,
+       hugeEnum_VALUE_0772, hugeEnum_VALUE_0773, hugeEnum_VALUE_0774,
+       hugeEnum_VALUE_0775, hugeEnum_VALUE_0776, hugeEnum_VALUE_0777,
+       hugeEnum_VALUE_0778, hugeEnum_VALUE_0779, hugeEnum_VALUE_0780,
+       hugeEnum_VALUE_0781, hugeEnum_VALUE_0782, hugeEnum_VALUE_0783,
+       hugeEnum_VALUE_0784, hugeEnum_VALUE_0785, hugeEnum_VALUE_0786,
+       hugeEnum_VALUE_0787, hugeEnum_VALUE_0788, hugeEnum_VALUE_0789,
+       hugeEnum_VALUE_0790, hugeEnum_VALUE_0791, hugeEnum_VALUE_0792,
+       hugeEnum_VALUE_0793, hugeEnum_VALUE_0794, hugeEnum_VALUE_0795,
+       hugeEnum_VALUE_0796, hugeEnum_VALUE_0797, hugeEnum_VALUE_0798,
+       hugeEnum_VALUE_0799, hugeEnum_VALUE_0800, hugeEnum_VALUE_0801,
+       hugeEnum_VALUE_0802, hugeEnum_VALUE_0803, hugeEnum_VALUE_0804,
+       hugeEnum_VALUE_0805, hugeEnum_VALUE_0806, hugeEnum_VALUE_0807,
+       hugeEnum_VALUE_0808, hugeEnum_VALUE_0809, hugeEnum_VALUE_0810,
+       hugeEnum_VALUE_0811, hugeEnum_VALUE_0812, hugeEnum_VALUE_0813,
+       hugeEnum_VALUE_0814, hugeEnum_VALUE_0815, hugeEnum_VALUE_0816,
+       hugeEnum_VALUE_0817, hugeEnum_VALUE_0818, hugeEnum_VALUE_0819,
+       hugeEnum_VALUE_0820, hugeEnum_VALUE_0821, hugeEnum_VALUE_0822,
+       hugeEnum_VALUE_0823, hugeEnum_VALUE_0824, hugeEnum_VALUE_0825,
+       hugeEnum_VALUE_0826, hugeEnum_VALUE_0827, hugeEnum_VALUE_0828,
+       hugeEnum_VALUE_0829, hugeEnum_VALUE_0830, hugeEnum_VALUE_0831,
+       hugeEnum_VALUE_0832, hugeEnum_VALUE_0833, hugeEnum_VALUE_0834,
+       hugeEnum_VALUE_0835, hugeEnum_VALUE_0836, hugeEnum_VALUE_0837,
+       hugeEnum_VALUE_0838, hugeEnum_VALUE_0839, hugeEnum_VALUE_0840,
+       hugeEnum_VALUE_0841, hugeEnum_VALUE_0842, hugeEnum_VALUE_0843,
+       hugeEnum_VALUE_0844, hugeEnum_VALUE_0845, hugeEnum_VALUE_0846,
+       hugeEnum_VALUE_0847, hugeEnum_VALUE_0848, hugeEnum_VALUE_0849,
+       hugeEnum_VALUE_0850, hugeEnum_VALUE_0851, hugeEnum_VALUE_0852,
+       hugeEnum_VALUE_0853, hugeEnum_VALUE_0854, hugeEnum_VALUE_0855,
+       hugeEnum_VALUE_0856, hugeEnum_VALUE_0857, hugeEnum_VALUE_0858,
+       hugeEnum_VALUE_0859, hugeEnum_VALUE_0860, hugeEnum_VALUE_0861,
+       hugeEnum_VALUE_0862, hugeEnum_VALUE_0863, hugeEnum_VALUE_0864,
+       hugeEnum_VALUE_0865, hugeEnum_VALUE_0866, hugeEnum_VALUE_0867,
+       hugeEnum_VALUE_0868, hugeEnum_VALUE_0869, hugeEnum_VALUE_0870,
+       hugeEnum_VALUE_0871, hugeEnum_VALUE_0872, hugeEnum_VALUE_0873,
+       hugeEnum_VALUE_0874, hugeEnum_VALUE_0875, hugeEnum_VALUE_0876,
+       hugeEnum_VALUE_0877, hugeEnum_VALUE_0878, hugeEnum_VALUE_0879,
+       hugeEnum_VALUE_0880, hugeEnum_VALUE_0881, hugeEnum_VALUE_0882,
+       hugeEnum_VALUE_0883, hugeEnum_VALUE_0884, hugeEnum_VALUE_0885,
+       hugeEnum_VALUE_0886, hugeEnum_VALUE_0887, hugeEnum_VALUE_0888,
+       hugeEnum_VALUE_0889, hugeEnum_VALUE_0890, hugeEnum_VALUE_0891,
+       hugeEnum_VALUE_0892, hugeEnum_VALUE_0893, hugeEnum_VALUE_0894,
+       hugeEnum_VALUE_0895, hugeEnum_VALUE_0896, hugeEnum_VALUE_0897,
+       hugeEnum_VALUE_0898, hugeEnum_VALUE_0899, hugeEnum_VALUE_0900,
+       hugeEnum_VALUE_0901, hugeEnum_VALUE_0902, hugeEnum_VALUE_0903,
+       hugeEnum_VALUE_0904, hugeEnum_VALUE_0905, hugeEnum_VALUE_0906,
+       hugeEnum_VALUE_0907, hugeEnum_VALUE_0908, hugeEnum_VALUE_0909,
+       hugeEnum_VALUE_0910, hugeEnum_VALUE_0911, hugeEnum_VALUE_0912,
+       hugeEnum_VALUE_0913, hugeEnum_VALUE_0914, hugeEnum_VALUE_0915,
+       hugeEnum_VALUE_0916, hugeEnum_VALUE_0917, hugeEnum_VALUE_0918,
+       hugeEnum_VALUE_0919, hugeEnum_VALUE_0920, hugeEnum_VALUE_0921,
+       hugeEnum_VALUE_0922, hugeEnum_VALUE_0923, hugeEnum_VALUE_0924,
+       hugeEnum_VALUE_0925, hugeEnum_VALUE_0926, hugeEnum_VALUE_0927,
+       hugeEnum_VALUE_0928, hugeEnum_VALUE_0929, hugeEnum_VALUE_0930,
+       hugeEnum_VALUE_0931, hugeEnum_VALUE_0932, hugeEnum_VALUE_0933,
+       hugeEnum_VALUE_0934, hugeEnum_VALUE_0935, hugeEnum_VALUE_0936,
+       hugeEnum_VALUE_0937, hugeEnum_VALUE_0938, hugeEnum_VALUE_0939,
+       hugeEnum_VALUE_0940, hugeEnum_VALUE_0941, hugeEnum_VALUE_0942,
+       hugeEnum_VALUE_0943, hugeEnum_VALUE_0944, hugeEnum_VALUE_0945,
+       hugeEnum_VALUE_0946, hugeEnum_VALUE_0947, hugeEnum_VALUE_0948,
+       hugeEnum_VALUE_0949, hugeEnum_VALUE_0950, hugeEnum_VALUE_0951,
+       hugeEnum_VALUE_0952, hugeEnum_VALUE_0953, hugeEnum_VALUE_0954,
+       hugeEnum_VALUE_0955, hugeEnum_VALUE_0956, hugeEnum_VALUE_0957,
+       hugeEnum_VALUE_0958, hugeEnum_VALUE_0959, hugeEnum_VALUE_0960,
+       hugeEnum_VALUE_0961, hugeEnum_VALUE_0962, hugeEnum_VALUE_0963,
+       hugeEnum_VALUE_0964, hugeEnum_VALUE_0965, hugeEnum_VALUE_0966,
+       hugeEnum_VALUE_0967, hugeEnum_VALUE_0968, hugeEnum_VALUE_0969,
+       hugeEnum_VALUE_0970, hugeEnum_VALUE_0971, hugeEnum_VALUE_0972,
+       hugeEnum_VALUE_0973, hugeEnum_VALUE_0974, hugeEnum_VALUE_0975,
+       hugeEnum_VALUE_0976, hugeEnum_VALUE_0977, hugeEnum_VALUE_0978,
+       hugeEnum_VALUE_0979, hugeEnum_VALUE_0980, hugeEnum_VALUE_0981,
+       hugeEnum_VALUE_0982, hugeEnum_VALUE_0983, hugeEnum_VALUE_0984,
+       hugeEnum_VALUE_0985, hugeEnum_VALUE_0986, hugeEnum_VALUE_0987,
+       hugeEnum_VALUE_0988, hugeEnum_VALUE_0989, hugeEnum_VALUE_0990,
+       hugeEnum_VALUE_0991, hugeEnum_VALUE_0992, hugeEnum_VALUE_0993,
+       hugeEnum_VALUE_0994, hugeEnum_VALUE_0995, hugeEnum_VALUE_0996,
+       hugeEnum_VALUE_0997, hugeEnum_VALUE_0998, hugeEnum_VALUE_0999,
+       hugeEnum_VALUE_1000, hugeEnum_VALUE_1001]
+  toThriftEnumEither val
+    = if Prelude.elem __val Thrift.allThriftEnumValues then
+        Prelude.Right __val else
+        Prelude.Left
+          ("toThriftEnumEither: not a valid identifier for enum HugeEnum: "
+             ++ Prelude.show val)
+    where
+      __val = HugeEnum (Prelude.fromIntegral val)
diff --git a/test/fixtures/gen-hs2/HsTest/Types.hs b/test/fixtures/gen-hs2/HsTest/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/HsTest/Types.hs
@@ -0,0 +1,1420 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LINE 8 "test/fixtures/gen-hs2/HsTest/Types.hs" #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module HsTest.Types
+       (X(X, unX), Y, Z(Z, unZ), Foo(Foo, foo_bar, foo_baz),
+        TUnion(TUnion_EMPTY, TUnion_StringOption, TUnion_I64Option,
+               TUnion_FooOption),
+        TestStruct(TestStruct, testStruct_f_bool, testStruct_f_byte,
+                   testStruct_f_double, testStruct_f_i16, testStruct_f_i32,
+                   testStruct_f_i64, testStruct_f_float, testStruct_f_list,
+                   testStruct_f_map, testStruct_f_text, testStruct_f_set,
+                   testStruct_o_i32, testStruct_foo, testStruct_f_hash_map,
+                   testStruct_f_newtype, testStruct_f_union, testStruct_f_string,
+                   testStruct_f_binary, testStruct_f_optional_newtype,
+                   testStruct_bool_map, testStruct_bool_list, testStruct_i64_vec,
+                   testStruct_i64_svec, testStruct_binary_key,
+                   testStruct_f_bytestring),
+        Number(Number_One, Number_Two, Number_Three, Number__UNKNOWN),
+        Perfect(Perfect_A, Perfect_B, Perfect_C, Perfect__UNKNOWN),
+        Void(Void__UNKNOWN), List_i64_1894, List_i64_7708,
+        Map_Number_i64_1522, String_1484, String_5858)
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.ByteString as ByteString
+import qualified Data.Default as Default
+import qualified Data.Function as Function
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Map.Strict as Map
+import qualified Data.Ord as Ord
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified Data.Vector as Vector
+import qualified Data.Vector.Storable as VectorStorable
+import qualified GHC.Magic as GHC
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Aeson ((.:), (.=))
+import Data.Monoid ((<>))
+import Prelude ((.), (++), (>), (==))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (++))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+{-# LINE 4 "if/hs_test_instances.hs" #-}
+import qualified Test.QuickCheck as QuickCheck
+{-# LINE 5 "if/hs_test_instances.hs" #-}
+import qualified Data.Vector as Vector
+{-# LINE 6 "if/hs_test_instances.hs" #-}
+import qualified Data.Vector.Storable as VectorStorable
+{-# LINE 7 "if/hs_test_instances.hs" #-}
+import Prelude ((/=), ($))
+{-# LINE 76 "test/fixtures/gen-hs2/HsTest/Types.hs" #-}
+
+newtype X = X{unX :: Int.Int64}
+            deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable X where
+  hashWithSalt __salt (X __val) = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON X where
+  toJSON (X __val) = Aeson.toJSON __val
+
+type Y = X
+
+newtype Z = Z{unZ :: Y}
+            deriving (Prelude.Eq, Prelude.Show, DeepSeq.NFData, Prelude.Ord)
+
+instance Hashable.Hashable Z where
+  hashWithSalt __salt (Z __val) = Hashable.hashWithSalt __salt __val
+
+instance Aeson.ToJSON Z where
+  toJSON (Z __val) = Aeson.toJSON (unX __val)
+
+data Foo = Foo{foo_bar :: Int.Int32, foo_baz :: Int.Int32}
+           deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Foo where
+  toJSON (Foo __field__bar __field__baz)
+    = Aeson.object
+        ("bar" .= __field__bar : "baz" .= __field__baz : Prelude.mempty)
+
+instance Thrift.ThriftStruct Foo where
+  buildStruct _proxy (Foo __field__bar __field__baz)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "bar" (Thrift.getI32Type _proxy) 5 0
+           (Thrift.genI32Prim _proxy)
+           __field__bar
+           :
+           Thrift.genFieldPrim _proxy "baz" (Thrift.getI32Type _proxy) 1 5
+             (Thrift.genI32Prim _proxy)
+             __field__baz
+             : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__bar <- ST.newSTRef Default.def
+            __field__baz <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 5 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__bar
+                                                                          _val
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__baz
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__bar <- ST.readSTRef __field__bar
+                                             !__val__baz <- ST.readSTRef __field__baz
+                                             Prelude.pure (Foo __val__bar __val__baz)
+              _idMap = HashMap.fromList [("bar", 5), ("baz", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData Foo where
+  rnf (Foo __field__bar __field__baz)
+    = DeepSeq.rnf __field__bar `Prelude.seq`
+        DeepSeq.rnf __field__baz `Prelude.seq` ()
+
+instance Default.Default Foo where
+  def = Foo Default.def Default.def
+
+instance Hashable.Hashable Foo where
+  hashWithSalt __salt (Foo _bar _baz)
+    = Hashable.hashWithSalt (Hashable.hashWithSalt __salt _bar) _baz
+
+data TUnion = TUnion_StringOption Text.Text
+            | TUnion_I64Option Int.Int64
+            | TUnion_FooOption Foo
+            | TUnion_EMPTY
+              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TUnion where
+  toJSON (TUnion_StringOption __StringOption)
+    = Aeson.object ["StringOption" .= __StringOption]
+  toJSON (TUnion_I64Option __I64Option)
+    = Aeson.object ["I64Option" .= __I64Option]
+  toJSON (TUnion_FooOption __FooOption)
+    = Aeson.object ["FooOption" .= __FooOption]
+  toJSON TUnion_EMPTY = Aeson.object []
+
+instance Thrift.ThriftStruct TUnion where
+  buildStruct _proxy (TUnion_StringOption __StringOption)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "StringOption"
+           (Thrift.getStringType _proxy)
+           1
+           0
+           (Thrift.genText _proxy __StringOption)]
+  buildStruct _proxy (TUnion_I64Option __I64Option)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "I64Option" (Thrift.getI64Type _proxy)
+           2
+           0
+           (Thrift.genI64Prim _proxy)
+           __I64Option]
+  buildStruct _proxy (TUnion_FooOption __FooOption)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "FooOption" (Thrift.getStructType _proxy) 3
+           0
+           (Thrift.buildStruct _proxy __FooOption)]
+  buildStruct _proxy TUnion_EMPTY = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = do _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+         case _fieldBegin of
+           Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                     1 | _type == Thrift.getStringType _proxy ->
+                                                         do _val <- Thrift.parseText _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return
+                                                              (TUnion_StringOption _val)
+                                                     2 | _type == Thrift.getI64Type _proxy ->
+                                                         do _val <- Thrift.parseI64 _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (TUnion_I64Option _val)
+                                                     3 | _type == Thrift.getStructType _proxy ->
+                                                         do _val <- Thrift.parseStruct _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (TUnion_FooOption _val)
+                                                     _ -> do Thrift.parseSkip _proxy _type
+                                                               Prelude.Nothing
+                                                             Thrift.parseStop _proxy
+                                                             Prelude.return TUnion_EMPTY
+           Thrift.FieldEnd -> Prelude.return TUnion_EMPTY
+    where
+      _idMap
+        = HashMap.fromList
+            [("StringOption", 1), ("I64Option", 2), ("FooOption", 3)]
+
+instance DeepSeq.NFData TUnion where
+  rnf (TUnion_StringOption __StringOption)
+    = DeepSeq.rnf __StringOption
+  rnf (TUnion_I64Option __I64Option) = DeepSeq.rnf __I64Option
+  rnf (TUnion_FooOption __FooOption) = DeepSeq.rnf __FooOption
+  rnf TUnion_EMPTY = ()
+
+instance Default.Default TUnion where
+  def = TUnion_EMPTY
+
+instance Hashable.Hashable TUnion where
+  hashWithSalt __salt (TUnion_StringOption _StringOption)
+    = Hashable.hashWithSalt __salt
+        (Hashable.hashWithSalt 1 _StringOption)
+  hashWithSalt __salt (TUnion_I64Option _I64Option)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 2 _I64Option)
+  hashWithSalt __salt (TUnion_FooOption _FooOption)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 3 _FooOption)
+  hashWithSalt __salt TUnion_EMPTY
+    = Hashable.hashWithSalt __salt (0 :: Prelude.Int)
+
+data TestStruct = TestStruct{testStruct_f_bool :: Prelude.Bool,
+                             testStruct_f_byte :: Int.Int8,
+                             testStruct_f_double :: Prelude.Double,
+                             testStruct_f_i16 :: Int.Int16, testStruct_f_i32 :: Int.Int32,
+                             testStruct_f_i64 :: Int.Int64, testStruct_f_float :: Prelude.Float,
+                             testStruct_f_list :: [Int.Int16],
+                             testStruct_f_map :: Map.Map Int.Int16 Int.Int32,
+                             testStruct_f_text :: Text.Text,
+                             testStruct_f_set :: Set.Set Int.Int8,
+                             testStruct_o_i32 :: Prelude.Maybe Int.Int32, testStruct_foo :: Foo,
+                             testStruct_f_hash_map :: Map_Number_i64_1522,
+                             testStruct_f_newtype :: Z, testStruct_f_union :: TUnion,
+                             testStruct_f_string :: String_5858,
+                             testStruct_f_binary :: ByteString.ByteString,
+                             testStruct_f_optional_newtype :: Prelude.Maybe X,
+                             testStruct_bool_map :: Map.Map Int.Int32 Prelude.Bool,
+                             testStruct_bool_list :: [Prelude.Bool],
+                             testStruct_i64_vec :: List_i64_7708,
+                             testStruct_i64_svec :: List_i64_1894,
+                             testStruct_binary_key :: Map.Map ByteString.ByteString Int.Int64,
+                             testStruct_f_bytestring :: String_1484}
+                  deriving (Prelude.Eq, Prelude.Show)
+
+instance Aeson.ToJSON TestStruct where
+  toJSON
+    (TestStruct __field__f_bool __field__f_byte __field__f_double
+       __field__f_i16 __field__f_i32 __field__f_i64 __field__f_float
+       __field__f_list __field__f_map __field__f_text __field__f_set
+       __field__o_i32 __field__foo __field__f_hash_map __field__f_newtype
+       __field__f_union __field__f_string __field__f_binary
+       __field__f_optional_newtype __field__bool_map __field__bool_list
+       __field__i64_vec __field__i64_svec __field__binary_key
+       __field__f_bytestring)
+    = Aeson.object
+        ("f_bool" .= __field__f_bool :
+           "f_byte" .= __field__f_byte :
+             "f_double" .= __field__f_double :
+               "f_i16" .= __field__f_i16 :
+                 "f_i32" .= __field__f_i32 :
+                   "f_i64" .= __field__f_i64 :
+                     "f_float" .= __field__f_float :
+                       "f_list" .= __field__f_list :
+                         "f_map" .= Map.mapKeys Thrift.keyToStr __field__f_map :
+                           "f_text" .= __field__f_text :
+                             "f_set" .= __field__f_set :
+                               Prelude.maybe Prelude.id ((:) . ("o_i32" .=)) __field__o_i32
+                                 ("foo" .= __field__foo :
+                                    "f_hash_map" .=
+                                      Thrift.hmMapKeys Thrift.keyToStr __field__f_hash_map
+                                      :
+                                      "f_newtype" .= (unX . unZ) __field__f_newtype :
+                                        "f_union" .= __field__f_union :
+                                          "f_string" .= __field__f_string :
+                                            "f_binary" .= Thrift.encodeBase64Text __field__f_binary
+                                              :
+                                              Prelude.maybe Prelude.id
+                                                ((:) . ("f_optional_newtype" .=))
+                                                (Prelude.fmap unX __field__f_optional_newtype)
+                                                ("bool_map" .=
+                                                   Map.mapKeys Thrift.keyToStr __field__bool_map
+                                                   :
+                                                   "bool_list" .= __field__bool_list :
+                                                     "i64_vec" .= __field__i64_vec :
+                                                       "i64_svec" .= __field__i64_svec :
+                                                         "binary_key" .=
+                                                           Map.mapKeys Thrift.encodeBase64Text
+                                                             __field__binary_key
+                                                           :
+                                                           "f_bytestring" .=
+                                                             Text.decodeUtf8 __field__f_bytestring
+                                                             : Prelude.mempty)))
+
+instance Thrift.ThriftStruct TestStruct where
+  buildStruct _proxy
+    (TestStruct __field__f_bool __field__f_byte __field__f_double
+       __field__f_i16 __field__f_i32 __field__f_i64 __field__f_float
+       __field__f_list __field__f_map __field__f_text __field__f_set
+       __field__o_i32 __field__foo __field__f_hash_map __field__f_newtype
+       __field__f_union __field__f_string __field__f_binary
+       __field__f_optional_newtype __field__bool_map __field__bool_list
+       __field__i64_vec __field__i64_svec __field__binary_key
+       __field__f_bytestring)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldBool _proxy "f_bool" 1 0 __field__f_bool :
+           Thrift.genFieldPrim _proxy "f_byte" (Thrift.getByteType _proxy) 2 1
+             (Thrift.genBytePrim _proxy)
+             __field__f_byte
+             :
+             Thrift.genField _proxy "f_double" (Thrift.getDoubleType _proxy) 3 2
+               (Thrift.genDouble _proxy __field__f_double)
+               :
+               Thrift.genFieldPrim _proxy "f_i16" (Thrift.getI16Type _proxy) 4 3
+                 (Thrift.genI16Prim _proxy)
+                 __field__f_i16
+                 :
+                 Thrift.genFieldPrim _proxy "f_i32" (Thrift.getI32Type _proxy) 5 4
+                   (Thrift.genI32Prim _proxy)
+                   __field__f_i32
+                   :
+                   Thrift.genFieldPrim _proxy "f_i64" (Thrift.getI64Type _proxy) 6 5
+                     (Thrift.genI64Prim _proxy)
+                     __field__f_i64
+                     :
+                     Thrift.genField _proxy "f_float" (Thrift.getFloatType _proxy) 7 6
+                       (Thrift.genFloat _proxy __field__f_float)
+                       :
+                       Thrift.genField _proxy "f_list" (Thrift.getListType _proxy) 8 7
+                         (Thrift.genListPrim _proxy (Thrift.getI16Type _proxy)
+                            (Thrift.genI16Prim _proxy)
+                            __field__f_list)
+                         :
+                         Thrift.genField _proxy "f_map" (Thrift.getMapType _proxy) 9 8
+                           ((Thrift.genMapPrim _proxy (Thrift.getI16Type _proxy)
+                               (Thrift.getI32Type _proxy)
+                               Prelude.False
+                               (Thrift.genI16Prim _proxy)
+                               (Thrift.genI32Prim _proxy)
+                               . Map.toList)
+                              __field__f_map)
+                           :
+                           Thrift.genField _proxy "f_text" (Thrift.getStringType _proxy) 10 9
+                             (Thrift.genText _proxy __field__f_text)
+                             :
+                             Thrift.genField _proxy "f_set" (Thrift.getSetType _proxy) 11 10
+                               ((Thrift.genListPrim _proxy (Thrift.getByteType _proxy)
+                                   (Thrift.genBytePrim _proxy)
+                                   . Set.toList)
+                                  __field__f_set)
+                               :
+                               let (__cereal__o_i32, __id__o_i32)
+                                     = case __field__o_i32 of
+                                         Prelude.Just _val -> ((:)
+                                                                 (Thrift.genFieldPrim _proxy "o_i32"
+                                                                    (Thrift.getI32Type _proxy)
+                                                                    12
+                                                                    11
+                                                                    (Thrift.genI32Prim _proxy)
+                                                                    _val),
+                                                               12)
+                                         Prelude.Nothing -> (Prelude.id, 11)
+                                 in
+                                 __cereal__o_i32
+                                   (Thrift.genField _proxy "foo" (Thrift.getStructType _proxy) 99
+                                      __id__o_i32
+                                      (Thrift.buildStruct _proxy __field__foo)
+                                      :
+                                      Thrift.genField _proxy "f_hash_map" (Thrift.getMapType _proxy)
+                                        13
+                                        99
+                                        ((Thrift.genMap _proxy (Thrift.getI32Type _proxy)
+                                            (Thrift.getI64Type _proxy)
+                                            Prelude.False
+                                            (Thrift.genI32 _proxy . Prelude.fromIntegral .
+                                               Thrift.fromThriftEnum)
+                                            (Thrift.genI64 _proxy)
+                                            . HashMap.toList)
+                                           __field__f_hash_map)
+                                        :
+                                        Thrift.genField _proxy "f_newtype"
+                                          (Thrift.getI64Type _proxy)
+                                          14
+                                          13
+                                          ((Thrift.genI64 _proxy . unX . unZ) __field__f_newtype)
+                                          :
+                                          Thrift.genField _proxy "f_union"
+                                            (Thrift.getStructType _proxy)
+                                            15
+                                            14
+                                            (Thrift.buildStruct _proxy __field__f_union)
+                                            :
+                                            Thrift.genField _proxy "f_string"
+                                              (Thrift.getStringType _proxy)
+                                              16
+                                              15
+                                              ((Thrift.genText _proxy . Text.pack)
+                                                 __field__f_string)
+                                              :
+                                              Thrift.genField _proxy "f_binary"
+                                                (Thrift.getStringType _proxy)
+                                                17
+                                                16
+                                                (Thrift.genBytes _proxy __field__f_binary)
+                                                :
+                                                let (__cereal__f_optional_newtype,
+                                                     __id__f_optional_newtype)
+                                                      = case __field__f_optional_newtype of
+                                                          Prelude.Just _val -> ((:)
+                                                                                  (Thrift.genField
+                                                                                     _proxy
+                                                                                     "f_optional_newtype"
+                                                                                     (Thrift.getI64Type
+                                                                                        _proxy)
+                                                                                     18
+                                                                                     17
+                                                                                     ((Thrift.genI64
+                                                                                         _proxy
+                                                                                         . unX)
+                                                                                        _val)),
+                                                                                18)
+                                                          Prelude.Nothing -> (Prelude.id, 17)
+                                                  in
+                                                  __cereal__f_optional_newtype
+                                                    (Thrift.genField _proxy "bool_map"
+                                                       (Thrift.getMapType _proxy)
+                                                       19
+                                                       __id__f_optional_newtype
+                                                       ((Thrift.genMapPrim _proxy
+                                                           (Thrift.getI32Type _proxy)
+                                                           (Thrift.getBoolType _proxy)
+                                                           Prelude.False
+                                                           (Thrift.genI32Prim _proxy)
+                                                           (Thrift.genBoolPrim _proxy)
+                                                           . Map.toList)
+                                                          __field__bool_map)
+                                                       :
+                                                       Thrift.genField _proxy "bool_list"
+                                                         (Thrift.getListType _proxy)
+                                                         20
+                                                         19
+                                                         (Thrift.genListPrim _proxy
+                                                            (Thrift.getBoolType _proxy)
+                                                            (Thrift.genBoolPrim _proxy)
+                                                            __field__bool_list)
+                                                         :
+                                                         Thrift.genField _proxy "i64_vec"
+                                                           (Thrift.getListType _proxy)
+                                                           21
+                                                           20
+                                                           ((Thrift.genListPrim _proxy
+                                                               (Thrift.getI64Type _proxy)
+                                                               (Thrift.genI64Prim _proxy)
+                                                               . Vector.toList)
+                                                              __field__i64_vec)
+                                                           :
+                                                           Thrift.genField _proxy "i64_svec"
+                                                             (Thrift.getListType _proxy)
+                                                             22
+                                                             21
+                                                             ((Thrift.genListPrim _proxy
+                                                                 (Thrift.getI64Type _proxy)
+                                                                 (Thrift.genI64Prim _proxy)
+                                                                 . VectorStorable.toList)
+                                                                __field__i64_svec)
+                                                             :
+                                                             Thrift.genField _proxy "binary_key"
+                                                               (Thrift.getMapType _proxy)
+                                                               23
+                                                               22
+                                                               ((Thrift.genMap _proxy
+                                                                   (Thrift.getStringType _proxy)
+                                                                   (Thrift.getI64Type _proxy)
+                                                                   Prelude.True
+                                                                   (Thrift.genBytes _proxy)
+                                                                   (Thrift.genI64 _proxy)
+                                                                   . Map.toList)
+                                                                  __field__binary_key)
+                                                               :
+                                                               Thrift.genField _proxy "f_bytestring"
+                                                                 (Thrift.getStringType _proxy)
+                                                                 24
+                                                                 23
+                                                                 (Thrift.genByteString _proxy
+                                                                    __field__f_bytestring)
+                                                                 : [])))
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__f_bool <- ST.newSTRef Prelude.Nothing
+            __field__f_byte <- ST.newSTRef Default.def
+            __field__f_double <- ST.newSTRef Default.def
+            __field__f_i16 <- ST.newSTRef 5
+            __field__f_i32 <- ST.newSTRef Default.def
+            __field__f_i64 <- ST.newSTRef Default.def
+            __field__f_float <- ST.newSTRef Default.def
+            __field__f_list <- ST.newSTRef Default.def
+            __field__f_map <- ST.newSTRef (Map.fromList [(1, 2)])
+            __field__f_text <- ST.newSTRef ""
+            __field__f_set <- ST.newSTRef Default.def
+            __field__o_i32 <- ST.newSTRef Prelude.Nothing
+            __field__foo <- ST.newSTRef
+                              (Default.def :: Foo){foo_bar = 1, foo_baz = 2}
+            __field__f_hash_map <- ST.newSTRef HashMap.empty
+            __field__f_newtype <- ST.newSTRef (Z (X Default.def))
+            __field__f_union <- ST.newSTRef Default.def
+            __field__f_string <- ST.newSTRef Default.def
+            __field__f_binary <- ST.newSTRef ""
+            __field__f_optional_newtype <- ST.newSTRef Prelude.Nothing
+            __field__bool_map <- ST.newSTRef Default.def
+            __field__bool_list <- ST.newSTRef Default.def
+            __field__i64_vec <- ST.newSTRef Vector.empty
+            __field__i64_svec <- ST.newSTRef VectorStorable.empty
+            __field__binary_key <- ST.newSTRef Default.def
+            __field__f_bytestring <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getBoolType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseBoolF
+                                                                                      _proxy
+                                                                                      _bool)
+                                                                        ST.writeSTRef
+                                                                          __field__f_bool
+                                                                          (Prelude.Just _val)
+                                                                 2 | _type ==
+                                                                       Thrift.getByteType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseByte
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__f_byte
+                                                                          _val
+                                                                 3 | _type ==
+                                                                       Thrift.getDoubleType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseDouble
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__f_double
+                                                                          _val
+                                                                 4 | _type ==
+                                                                       Thrift.getI16Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI16
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__f_i16
+                                                                          _val
+                                                                 5 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI32
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__f_i32
+                                                                          _val
+                                                                 6 | _type ==
+                                                                       Thrift.getI64Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI64
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__f_i64
+                                                                          _val
+                                                                 7 | _type ==
+                                                                       Thrift.getFloatType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseFloat
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__f_float
+                                                                          _val
+                                                                 8 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Thrift.parseI16
+                                                                                           _proxy))
+                                                                        ST.writeSTRef
+                                                                          __field__f_list
+                                                                          _val
+                                                                 9 | _type ==
+                                                                       Thrift.getMapType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Map.fromList <$>
+                                                                                      Thrift.parseMap
+                                                                                        _proxy
+                                                                                        (Thrift.parseI16
+                                                                                           _proxy)
+                                                                                        (Thrift.parseI32
+                                                                                           _proxy)
+                                                                                        Prelude.False)
+                                                                        ST.writeSTRef __field__f_map
+                                                                          _val
+                                                                 10 | _type ==
+                                                                        Thrift.getStringType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseText
+                                                                                       _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__f_text
+                                                                           _val
+                                                                 11 | _type ==
+                                                                        Thrift.getSetType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Set.fromList .
+                                                                                       Prelude.snd
+                                                                                       <$>
+                                                                                       Thrift.parseList
+                                                                                         _proxy
+                                                                                         (Thrift.parseByte
+                                                                                            _proxy))
+                                                                         ST.writeSTRef
+                                                                           __field__f_set
+                                                                           _val
+                                                                 12 | _type ==
+                                                                        Thrift.getI32Type _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseI32
+                                                                                       _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__o_i32
+                                                                           (Prelude.Just _val)
+                                                                 99 | _type ==
+                                                                        Thrift.getStructType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseStruct
+                                                                                       _proxy)
+                                                                         ST.writeSTRef __field__foo
+                                                                           _val
+                                                                 13 | _type ==
+                                                                        Thrift.getMapType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (HashMap.fromList
+                                                                                       <$>
+                                                                                       Thrift.parseMap
+                                                                                         _proxy
+                                                                                         (Thrift.parseEnum
+                                                                                            _proxy
+                                                                                            "Number")
+                                                                                         (Thrift.parseI64
+                                                                                            _proxy)
+                                                                                         Prelude.False)
+                                                                         ST.writeSTRef
+                                                                           __field__f_hash_map
+                                                                           _val
+                                                                 14 | _type ==
+                                                                        Thrift.getI64Type _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Prelude.fmap Z
+                                                                                       (Prelude.fmap
+                                                                                          X
+                                                                                          (Thrift.parseI64
+                                                                                             _proxy)))
+                                                                         ST.writeSTRef
+                                                                           __field__f_newtype
+                                                                           _val
+                                                                 15 | _type ==
+                                                                        Thrift.getStructType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseStruct
+                                                                                       _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__f_union
+                                                                           _val
+                                                                 16 | _type ==
+                                                                        Thrift.getStringType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Text.unpack <$>
+                                                                                       Thrift.parseText
+                                                                                         _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__f_string
+                                                                           _val
+                                                                 17 | _type ==
+                                                                        Thrift.getStringType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseBytes
+                                                                                       _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__f_binary
+                                                                           _val
+                                                                 18 | _type ==
+                                                                        Thrift.getI64Type _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Prelude.fmap X
+                                                                                       (Thrift.parseI64
+                                                                                          _proxy))
+                                                                         ST.writeSTRef
+                                                                           __field__f_optional_newtype
+                                                                           (Prelude.Just _val)
+                                                                 19 | _type ==
+                                                                        Thrift.getMapType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Map.fromList
+                                                                                       <$>
+                                                                                       Thrift.parseMap
+                                                                                         _proxy
+                                                                                         (Thrift.parseI32
+                                                                                            _proxy)
+                                                                                         (Thrift.parseBool
+                                                                                            _proxy)
+                                                                                         Prelude.False)
+                                                                         ST.writeSTRef
+                                                                           __field__bool_map
+                                                                           _val
+                                                                 20 | _type ==
+                                                                        Thrift.getListType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Prelude.snd <$>
+                                                                                       Thrift.parseList
+                                                                                         _proxy
+                                                                                         (Thrift.parseBool
+                                                                                            _proxy))
+                                                                         ST.writeSTRef
+                                                                           __field__bool_list
+                                                                           _val
+                                                                 21 | _type ==
+                                                                        Thrift.getListType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Prelude.uncurry
+                                                                                       Vector.fromListN
+                                                                                       <$>
+                                                                                       Thrift.parseList
+                                                                                         _proxy
+                                                                                         (Thrift.parseI64
+                                                                                            _proxy))
+                                                                         ST.writeSTRef
+                                                                           __field__i64_vec
+                                                                           _val
+                                                                 22 | _type ==
+                                                                        Thrift.getListType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Prelude.uncurry
+                                                                                       VectorStorable.fromListN
+                                                                                       <$>
+                                                                                       Thrift.parseList
+                                                                                         _proxy
+                                                                                         (Thrift.parseI64
+                                                                                            _proxy))
+                                                                         ST.writeSTRef
+                                                                           __field__i64_svec
+                                                                           _val
+                                                                 23 | _type ==
+                                                                        Thrift.getMapType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Map.fromList
+                                                                                       <$>
+                                                                                       Thrift.parseMap
+                                                                                         _proxy
+                                                                                         (Thrift.parseBytes
+                                                                                            _proxy)
+                                                                                         (Thrift.parseI64
+                                                                                            _proxy)
+                                                                                         Prelude.True)
+                                                                         ST.writeSTRef
+                                                                           __field__binary_key
+                                                                           _val
+                                                                 24 | _type ==
+                                                                        Thrift.getStringType _proxy
+                                                                      ->
+                                                                      do !_val <- Trans.lift
+                                                                                    (Thrift.parseByteString
+                                                                                       _proxy)
+                                                                         ST.writeSTRef
+                                                                           __field__f_bytestring
+                                                                           _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__maybe__f_bool <- ST.readSTRef
+                                                                   __field__f_bool
+                                             !__val__f_byte <- ST.readSTRef __field__f_byte
+                                             !__val__f_double <- ST.readSTRef __field__f_double
+                                             !__val__f_i16 <- ST.readSTRef __field__f_i16
+                                             !__val__f_i32 <- ST.readSTRef __field__f_i32
+                                             !__val__f_i64 <- ST.readSTRef __field__f_i64
+                                             !__val__f_float <- ST.readSTRef __field__f_float
+                                             !__val__f_list <- ST.readSTRef __field__f_list
+                                             !__val__f_map <- ST.readSTRef __field__f_map
+                                             !__val__f_text <- ST.readSTRef __field__f_text
+                                             !__val__f_set <- ST.readSTRef __field__f_set
+                                             !__val__o_i32 <- ST.readSTRef __field__o_i32
+                                             !__val__foo <- ST.readSTRef __field__foo
+                                             !__val__f_hash_map <- ST.readSTRef __field__f_hash_map
+                                             !__val__f_newtype <- ST.readSTRef __field__f_newtype
+                                             !__val__f_union <- ST.readSTRef __field__f_union
+                                             !__val__f_string <- ST.readSTRef __field__f_string
+                                             !__val__f_binary <- ST.readSTRef __field__f_binary
+                                             !__val__f_optional_newtype <- ST.readSTRef
+                                                                             __field__f_optional_newtype
+                                             !__val__bool_map <- ST.readSTRef __field__bool_map
+                                             !__val__bool_list <- ST.readSTRef __field__bool_list
+                                             !__val__i64_vec <- ST.readSTRef __field__i64_vec
+                                             !__val__i64_svec <- ST.readSTRef __field__i64_svec
+                                             !__val__binary_key <- ST.readSTRef __field__binary_key
+                                             !__val__f_bytestring <- ST.readSTRef
+                                                                       __field__f_bytestring
+                                             case __maybe__f_bool of
+                                               Prelude.Nothing -> Prelude.fail
+                                                                    "Error parsing type TestStruct: missing required field f_bool of type Prelude.Bool"
+                                               Prelude.Just __val__f_bool -> Prelude.pure
+                                                                               (TestStruct
+                                                                                  __val__f_bool
+                                                                                  __val__f_byte
+                                                                                  __val__f_double
+                                                                                  __val__f_i16
+                                                                                  __val__f_i32
+                                                                                  __val__f_i64
+                                                                                  __val__f_float
+                                                                                  __val__f_list
+                                                                                  __val__f_map
+                                                                                  __val__f_text
+                                                                                  __val__f_set
+                                                                                  __val__o_i32
+                                                                                  __val__foo
+                                                                                  __val__f_hash_map
+                                                                                  __val__f_newtype
+                                                                                  __val__f_union
+                                                                                  __val__f_string
+                                                                                  __val__f_binary
+                                                                                  __val__f_optional_newtype
+                                                                                  __val__bool_map
+                                                                                  __val__bool_list
+                                                                                  __val__i64_vec
+                                                                                  __val__i64_svec
+                                                                                  __val__binary_key
+                                                                                  __val__f_bytestring)
+              _idMap
+                = HashMap.fromList
+                    [("f_bool", 1), ("f_byte", 2), ("f_double", 3), ("f_i16", 4),
+                     ("f_i32", 5), ("f_i64", 6), ("f_float", 7), ("f_list", 8),
+                     ("f_map", 9), ("f_text", 10), ("f_set", 11), ("o_i32", 12),
+                     ("foo", 99), ("f_hash_map", 13), ("f_newtype", 14),
+                     ("f_union", 15), ("f_string", 16), ("f_binary", 17),
+                     ("f_optional_newtype", 18), ("bool_map", 19), ("bool_list", 20),
+                     ("i64_vec", 21), ("i64_svec", 22), ("binary_key", 23),
+                     ("f_bytestring", 24)]
+            _parse 0)
+
+instance DeepSeq.NFData TestStruct where
+  rnf
+    (TestStruct __field__f_bool __field__f_byte __field__f_double
+       __field__f_i16 __field__f_i32 __field__f_i64 __field__f_float
+       __field__f_list __field__f_map __field__f_text __field__f_set
+       __field__o_i32 __field__foo __field__f_hash_map __field__f_newtype
+       __field__f_union __field__f_string __field__f_binary
+       __field__f_optional_newtype __field__bool_map __field__bool_list
+       __field__i64_vec __field__i64_svec __field__binary_key
+       __field__f_bytestring)
+    = DeepSeq.rnf __field__f_bool `Prelude.seq`
+        DeepSeq.rnf __field__f_byte `Prelude.seq`
+          DeepSeq.rnf __field__f_double `Prelude.seq`
+            DeepSeq.rnf __field__f_i16 `Prelude.seq`
+              DeepSeq.rnf __field__f_i32 `Prelude.seq`
+                DeepSeq.rnf __field__f_i64 `Prelude.seq`
+                  DeepSeq.rnf __field__f_float `Prelude.seq`
+                    DeepSeq.rnf __field__f_list `Prelude.seq`
+                      DeepSeq.rnf __field__f_map `Prelude.seq`
+                        DeepSeq.rnf __field__f_text `Prelude.seq`
+                          DeepSeq.rnf __field__f_set `Prelude.seq`
+                            DeepSeq.rnf __field__o_i32 `Prelude.seq`
+                              DeepSeq.rnf __field__foo `Prelude.seq`
+                                DeepSeq.rnf __field__f_hash_map `Prelude.seq`
+                                  DeepSeq.rnf __field__f_newtype `Prelude.seq`
+                                    DeepSeq.rnf __field__f_union `Prelude.seq`
+                                      DeepSeq.rnf __field__f_string `Prelude.seq`
+                                        DeepSeq.rnf __field__f_binary `Prelude.seq`
+                                          DeepSeq.rnf __field__f_optional_newtype `Prelude.seq`
+                                            DeepSeq.rnf __field__bool_map `Prelude.seq`
+                                              DeepSeq.rnf __field__bool_list `Prelude.seq`
+                                                DeepSeq.rnf __field__i64_vec `Prelude.seq`
+                                                  DeepSeq.rnf __field__i64_svec `Prelude.seq`
+                                                    DeepSeq.rnf __field__binary_key `Prelude.seq`
+                                                      DeepSeq.rnf __field__f_bytestring
+                                                        `Prelude.seq` ()
+
+instance Default.Default TestStruct where
+  def
+    = TestStruct Prelude.False Default.def Default.def 5 Default.def
+        Default.def
+        Default.def
+        Default.def
+        (Map.fromList [(1, 2)])
+        ""
+        Default.def
+        Prelude.Nothing
+        (Default.def :: Foo){foo_bar = 1, foo_baz = 2}
+        HashMap.empty
+        (Z (X Default.def))
+        Default.def
+        Default.def
+        ""
+        Prelude.Nothing
+        Default.def
+        Default.def
+        Vector.empty
+        VectorStorable.empty
+        Default.def
+        Default.def
+
+instance Hashable.Hashable TestStruct where
+  hashWithSalt __salt
+    (TestStruct _f_bool _f_byte _f_double _f_i16 _f_i32 _f_i64 _f_float
+       _f_list _f_map _f_text _f_set _o_i32 _foo _f_hash_map _f_newtype
+       _f_union _f_string _f_binary _f_optional_newtype _bool_map
+       _bool_list _i64_vec _i64_svec _binary_key _f_bytestring)
+    = Hashable.hashWithSalt
+        (Hashable.hashWithSalt
+           (Hashable.hashWithSalt
+              (Hashable.hashWithSalt
+                 (Hashable.hashWithSalt
+                    (Hashable.hashWithSalt
+                       (Hashable.hashWithSalt
+                          (Hashable.hashWithSalt
+                             (Hashable.hashWithSalt
+                                (Hashable.hashWithSalt
+                                   (Hashable.hashWithSalt
+                                      (Hashable.hashWithSalt
+                                         (Hashable.hashWithSalt
+                                            (Hashable.hashWithSalt
+                                               (Hashable.hashWithSalt
+                                                  (Hashable.hashWithSalt
+                                                     (Hashable.hashWithSalt
+                                                        (Hashable.hashWithSalt
+                                                           (Hashable.hashWithSalt
+                                                              (Hashable.hashWithSalt
+                                                                 (Hashable.hashWithSalt
+                                                                    (Hashable.hashWithSalt
+                                                                       (Hashable.hashWithSalt
+                                                                          (Hashable.hashWithSalt
+                                                                             (Hashable.hashWithSalt
+                                                                                __salt
+                                                                                _f_bool)
+                                                                             _f_byte)
+                                                                          _f_double)
+                                                                       _f_i16)
+                                                                    _f_i32)
+                                                                 _f_i64)
+                                                              _f_float)
+                                                           _f_list)
+                                                        ((Prelude.map (\ (_k, _v) -> (_k, _v)) .
+                                                            Map.toAscList)
+                                                           _f_map))
+                                                     _f_text)
+                                                  (Set.elems _f_set))
+                                               _o_i32)
+                                            _foo)
+                                         ((List.sort .
+                                             Prelude.map (\ (_k, _v) -> (_k, _v)) . HashMap.toList)
+                                            _f_hash_map))
+                                      _f_newtype)
+                                   _f_union)
+                                _f_string)
+                             _f_binary)
+                          _f_optional_newtype)
+                       ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList) _bool_map))
+                    _bool_list)
+                 (Vector.toList _i64_vec))
+              (VectorStorable.toList _i64_svec))
+           ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList)
+              _binary_key))
+        _f_bytestring
+
+instance Ord.Ord TestStruct where
+  compare __a __b
+    = case Ord.compare (testStruct_f_bool __a) (testStruct_f_bool __b)
+        of
+        Ord.LT -> Ord.LT
+        Ord.GT -> Ord.GT
+        Ord.EQ -> case
+                    Ord.compare (testStruct_f_byte __a) (testStruct_f_byte __b) of
+                    Ord.LT -> Ord.LT
+                    Ord.GT -> Ord.GT
+                    Ord.EQ -> case
+                                Ord.compare (testStruct_f_double __a) (testStruct_f_double __b) of
+                                Ord.LT -> Ord.LT
+                                Ord.GT -> Ord.GT
+                                Ord.EQ -> case
+                                            Ord.compare (testStruct_f_i16 __a)
+                                              (testStruct_f_i16 __b)
+                                            of
+                                            Ord.LT -> Ord.LT
+                                            Ord.GT -> Ord.GT
+                                            Ord.EQ -> case
+                                                        Ord.compare (testStruct_f_i32 __a)
+                                                          (testStruct_f_i32 __b)
+                                                        of
+                                                        Ord.LT -> Ord.LT
+                                                        Ord.GT -> Ord.GT
+                                                        Ord.EQ -> case
+                                                                    Ord.compare
+                                                                      (testStruct_f_i64 __a)
+                                                                      (testStruct_f_i64 __b)
+                                                                    of
+                                                                    Ord.LT -> Ord.LT
+                                                                    Ord.GT -> Ord.GT
+                                                                    Ord.EQ -> case
+                                                                                Ord.compare
+                                                                                  (testStruct_f_float
+                                                                                     __a)
+                                                                                  (testStruct_f_float
+                                                                                     __b)
+                                                                                of
+                                                                                Ord.LT -> Ord.LT
+                                                                                Ord.GT -> Ord.GT
+                                                                                Ord.EQ -> case
+                                                                                            Ord.compare
+                                                                                              (testStruct_f_list
+                                                                                                 __a)
+                                                                                              (testStruct_f_list
+                                                                                                 __b)
+                                                                                            of
+                                                                                            Ord.LT -> Ord.LT
+                                                                                            Ord.GT -> Ord.GT
+                                                                                            Ord.EQ -> case
+                                                                                                        Ord.compare
+                                                                                                          (testStruct_f_map
+                                                                                                             __a)
+                                                                                                          (testStruct_f_map
+                                                                                                             __b)
+                                                                                                        of
+                                                                                                        Ord.LT -> Ord.LT
+                                                                                                        Ord.GT -> Ord.GT
+                                                                                                        Ord.EQ -> case
+                                                                                                                    Ord.compare
+                                                                                                                      (testStruct_f_text
+                                                                                                                         __a)
+                                                                                                                      (testStruct_f_text
+                                                                                                                         __b)
+                                                                                                                    of
+                                                                                                                    Ord.LT -> Ord.LT
+                                                                                                                    Ord.GT -> Ord.GT
+                                                                                                                    Ord.EQ -> case
+                                                                                                                                Ord.compare
+                                                                                                                                  (testStruct_f_set
+                                                                                                                                     __a)
+                                                                                                                                  (testStruct_f_set
+                                                                                                                                     __b)
+                                                                                                                                of
+                                                                                                                                Ord.LT -> Ord.LT
+                                                                                                                                Ord.GT -> Ord.GT
+                                                                                                                                Ord.EQ -> case
+                                                                                                                                            Ord.compare
+                                                                                                                                              (testStruct_o_i32
+                                                                                                                                                 __a)
+                                                                                                                                              (testStruct_o_i32
+                                                                                                                                                 __b)
+                                                                                                                                            of
+                                                                                                                                            Ord.LT -> Ord.LT
+                                                                                                                                            Ord.GT -> Ord.GT
+                                                                                                                                            Ord.EQ -> case
+                                                                                                                                                        Ord.compare
+                                                                                                                                                          (testStruct_foo
+                                                                                                                                                             __a)
+                                                                                                                                                          (testStruct_foo
+                                                                                                                                                             __b)
+                                                                                                                                                        of
+                                                                                                                                                        Ord.LT -> Ord.LT
+                                                                                                                                                        Ord.GT -> Ord.GT
+                                                                                                                                                        Ord.EQ -> case
+                                                                                                                                                                    Ord.compare
+                                                                                                                                                                      ((List.sort
+                                                                                                                                                                          .
+                                                                                                                                                                          Prelude.map
+                                                                                                                                                                            (\ (_k,
+                                                                                                                                                                                _v)
+                                                                                                                                                                               ->
+                                                                                                                                                                               (_k,
+                                                                                                                                                                                _v))
+                                                                                                                                                                            .
+                                                                                                                                                                            HashMap.toList)
+                                                                                                                                                                         (testStruct_f_hash_map
+                                                                                                                                                                            __a))
+                                                                                                                                                                      ((List.sort
+                                                                                                                                                                          .
+                                                                                                                                                                          Prelude.map
+                                                                                                                                                                            (\ (_k,
+                                                                                                                                                                                _v)
+                                                                                                                                                                               ->
+                                                                                                                                                                               (_k,
+                                                                                                                                                                                _v))
+                                                                                                                                                                            .
+                                                                                                                                                                            HashMap.toList)
+                                                                                                                                                                         (testStruct_f_hash_map
+                                                                                                                                                                            __b))
+                                                                                                                                                                    of
+                                                                                                                                                                    Ord.LT -> Ord.LT
+                                                                                                                                                                    Ord.GT -> Ord.GT
+                                                                                                                                                                    Ord.EQ -> case
+                                                                                                                                                                                Ord.compare
+                                                                                                                                                                                  (testStruct_f_newtype
+                                                                                                                                                                                     __a)
+                                                                                                                                                                                  (testStruct_f_newtype
+                                                                                                                                                                                     __b)
+                                                                                                                                                                                of
+                                                                                                                                                                                Ord.LT -> Ord.LT
+                                                                                                                                                                                Ord.GT -> Ord.GT
+                                                                                                                                                                                Ord.EQ -> case
+                                                                                                                                                                                            Ord.compare
+                                                                                                                                                                                              (testStruct_f_union
+                                                                                                                                                                                                 __a)
+                                                                                                                                                                                              (testStruct_f_union
+                                                                                                                                                                                                 __b)
+                                                                                                                                                                                            of
+                                                                                                                                                                                            Ord.LT -> Ord.LT
+                                                                                                                                                                                            Ord.GT -> Ord.GT
+                                                                                                                                                                                            Ord.EQ -> case
+                                                                                                                                                                                                        Ord.compare
+                                                                                                                                                                                                          (testStruct_f_string
+                                                                                                                                                                                                             __a)
+                                                                                                                                                                                                          (testStruct_f_string
+                                                                                                                                                                                                             __b)
+                                                                                                                                                                                                        of
+                                                                                                                                                                                                        Ord.LT -> Ord.LT
+                                                                                                                                                                                                        Ord.GT -> Ord.GT
+                                                                                                                                                                                                        Ord.EQ -> case
+                                                                                                                                                                                                                    Ord.compare
+                                                                                                                                                                                                                      (testStruct_f_binary
+                                                                                                                                                                                                                         __a)
+                                                                                                                                                                                                                      (testStruct_f_binary
+                                                                                                                                                                                                                         __b)
+                                                                                                                                                                                                                    of
+                                                                                                                                                                                                                    Ord.LT -> Ord.LT
+                                                                                                                                                                                                                    Ord.GT -> Ord.GT
+                                                                                                                                                                                                                    Ord.EQ -> case
+                                                                                                                                                                                                                                Ord.compare
+                                                                                                                                                                                                                                  (testStruct_f_optional_newtype
+                                                                                                                                                                                                                                     __a)
+                                                                                                                                                                                                                                  (testStruct_f_optional_newtype
+                                                                                                                                                                                                                                     __b)
+                                                                                                                                                                                                                                of
+                                                                                                                                                                                                                                Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                Ord.EQ -> case
+                                                                                                                                                                                                                                            Ord.compare
+                                                                                                                                                                                                                                              (testStruct_bool_map
+                                                                                                                                                                                                                                                 __a)
+                                                                                                                                                                                                                                              (testStruct_bool_map
+                                                                                                                                                                                                                                                 __b)
+                                                                                                                                                                                                                                            of
+                                                                                                                                                                                                                                            Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                            Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                            Ord.EQ -> case
+                                                                                                                                                                                                                                                        Ord.compare
+                                                                                                                                                                                                                                                          (testStruct_bool_list
+                                                                                                                                                                                                                                                             __a)
+                                                                                                                                                                                                                                                          (testStruct_bool_list
+                                                                                                                                                                                                                                                             __b)
+                                                                                                                                                                                                                                                        of
+                                                                                                                                                                                                                                                        Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                                        Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                                        Ord.EQ -> case
+                                                                                                                                                                                                                                                                    Ord.compare
+                                                                                                                                                                                                                                                                      (testStruct_i64_vec
+                                                                                                                                                                                                                                                                         __a)
+                                                                                                                                                                                                                                                                      (testStruct_i64_vec
+                                                                                                                                                                                                                                                                         __b)
+                                                                                                                                                                                                                                                                    of
+                                                                                                                                                                                                                                                                    Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                                                    Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                                                    Ord.EQ -> case
+                                                                                                                                                                                                                                                                                Ord.compare
+                                                                                                                                                                                                                                                                                  (testStruct_i64_svec
+                                                                                                                                                                                                                                                                                     __a)
+                                                                                                                                                                                                                                                                                  (testStruct_i64_svec
+                                                                                                                                                                                                                                                                                     __b)
+                                                                                                                                                                                                                                                                                of
+                                                                                                                                                                                                                                                                                Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                                                                Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                                                                Ord.EQ -> case
+                                                                                                                                                                                                                                                                                            Ord.compare
+                                                                                                                                                                                                                                                                                              (testStruct_binary_key
+                                                                                                                                                                                                                                                                                                 __a)
+                                                                                                                                                                                                                                                                                              (testStruct_binary_key
+                                                                                                                                                                                                                                                                                                 __b)
+                                                                                                                                                                                                                                                                                            of
+                                                                                                                                                                                                                                                                                            Ord.LT -> Ord.LT
+                                                                                                                                                                                                                                                                                            Ord.GT -> Ord.GT
+                                                                                                                                                                                                                                                                                            Ord.EQ -> Ord.compare
+                                                                                                                                                                                                                                                                                                        (testStruct_f_bytestring
+                                                                                                                                                                                                                                                                                                           __a)
+                                                                                                                                                                                                                                                                                                        (testStruct_f_bytestring
+                                                                                                                                                                                                                                                                                                           __b)
+
+data Number = Number_One
+            | Number_Two
+            | Number_Three
+            | Number__UNKNOWN Prelude.Int
+              deriving (Prelude.Eq, Prelude.Show)
+
+instance Aeson.ToJSON Number where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Number where
+  rnf __Number = Prelude.seq __Number ()
+
+instance Default.Default Number where
+  def = Number_One
+
+instance Hashable.Hashable Number where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Number where
+  toThriftEnum 1 = Number_One
+  toThriftEnum 2 = Number_Two
+  toThriftEnum 3 = Number_Three
+  toThriftEnum val = Number__UNKNOWN val
+  fromThriftEnum Number_One = 1
+  fromThriftEnum Number_Two = 2
+  fromThriftEnum Number_Three = 3
+  fromThriftEnum (Number__UNKNOWN val) = val
+  allThriftEnumValues = [Number_One, Number_Two, Number_Three]
+  toThriftEnumEither 1 = Prelude.Right Number_One
+  toThriftEnumEither 2 = Prelude.Right Number_Two
+  toThriftEnumEither 3 = Prelude.Right Number_Three
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Number: " ++
+           Prelude.show val)
+
+instance Prelude.Ord Number where
+  compare = Function.on Prelude.compare Thrift.fromThriftEnum
+
+data Perfect = Perfect_A
+             | Perfect_B
+             | Perfect_C
+             | Perfect__UNKNOWN Prelude.Int
+               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Perfect where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Perfect where
+  rnf __Perfect = Prelude.seq __Perfect ()
+
+instance Default.Default Perfect where
+  def = Perfect_A
+
+instance Hashable.Hashable Perfect where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Perfect where
+  toThriftEnum 0 = Perfect_A
+  toThriftEnum 1 = Perfect_B
+  toThriftEnum 2 = Perfect_C
+  toThriftEnum val = Perfect__UNKNOWN val
+  fromThriftEnum Perfect_A = 0
+  fromThriftEnum Perfect_B = 1
+  fromThriftEnum Perfect_C = 2
+  fromThriftEnum (Perfect__UNKNOWN val) = val
+  allThriftEnumValues = [Perfect_A, Perfect_B, Perfect_C]
+  toThriftEnumEither 0 = Prelude.Right Perfect_A
+  toThriftEnumEither 1 = Prelude.Right Perfect_B
+  toThriftEnumEither 2 = Prelude.Right Perfect_C
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Perfect: " ++
+           Prelude.show val)
+
+data Void = Void__UNKNOWN Prelude.Int
+            deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Void where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData Void where
+  rnf __Void = Prelude.seq __Void ()
+
+instance Default.Default Void where
+  def
+    = Exception.throw
+        (Thrift.ProtocolException "def: enum Void has no constructors")
+
+instance Hashable.Hashable Void where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum Void where
+  toThriftEnum val = Void__UNKNOWN val
+  fromThriftEnum (Void__UNKNOWN val) = val
+  allThriftEnumValues = []
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum Void: " ++
+           Prelude.show val)
+
+type List_i64_1894 = VectorStorable.Vector Int.Int64
+
+type List_i64_7708 = Vector.Vector Int.Int64
+
+type Map_Number_i64_1522 = HashMap.HashMap Number Int.Int64
+
+type String_1484 = ByteString.ByteString
+
+type String_5858 = Prelude.String
+{-# LINE 9 "if/hs_test_instances.hs" #-}
+instance QuickCheck.Arbitrary Foo where
+  arbitrary = Foo <$> QuickCheck.arbitrary <*> QuickCheck.arbitrary
+{-# LINE 12 "if/hs_test_instances.hs" #-}
+instance QuickCheck.Arbitrary TestStruct where
+  arbitrary
+    = TestStruct <$> QuickCheck.arbitrary <*> QuickCheck.arbitrary <*>
+        QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> (Map.fromList <$> QuickCheck.arbitrary)
+        <*> arbitraryText
+        <*> (Set.fromList <$> QuickCheck.arbitrary)
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> (HashMap.fromList <$> QuickCheck.arbitrary)
+        <*> ((Z . X) <$> QuickCheck.arbitrary)
+        <*> QuickCheck.arbitrary
+        <*> arbitraryString
+        <*> arbitraryBS
+        <*> (Prelude.fmap X <$> QuickCheck.arbitrary)
+        <*> QuickCheck.arbitrary
+        <*> QuickCheck.arbitrary
+        <*> (Vector.fromList <$> QuickCheck.arbitrary)
+        <*> (VectorStorable.fromList <$> QuickCheck.arbitrary)
+        <*> arbitraryBSMap
+        <*> (Text.encodeUtf8 <$> arbitraryText)
+{-# LINE 40 "if/hs_test_instances.hs" #-}
+instance QuickCheck.Arbitrary Number where
+  arbitrary
+    = QuickCheck.oneof $
+        Prelude.map Prelude.pure [Number_One, Number_Two, Number_Three]
+{-# LINE 44 "if/hs_test_instances.hs" #-}
+instance QuickCheck.Arbitrary TUnion where
+  arbitrary
+    = QuickCheck.oneof
+        [TUnion_StringOption <$> arbitraryText,
+         TUnion_I64Option <$> QuickCheck.arbitrary,
+         TUnion_FooOption <$> QuickCheck.arbitrary,
+         Prelude.pure TUnion_EMPTY]
+{-# LINE 52 "if/hs_test_instances.hs" #-}
+arbitraryString :: QuickCheck.Gen Prelude.String
+{-# LINE 53 "if/hs_test_instances.hs" #-}
+arbitraryString
+  = Prelude.filter (/= '\NUL') <$> QuickCheck.arbitrary
+{-# LINE 55 "if/hs_test_instances.hs" #-}
+arbitraryText :: QuickCheck.Gen Text.Text
+{-# LINE 56 "if/hs_test_instances.hs" #-}
+arbitraryText = Text.pack <$> arbitraryString
+{-# LINE 58 "if/hs_test_instances.hs" #-}
+arbitraryBS :: QuickCheck.Gen ByteString.ByteString
+{-# LINE 59 "if/hs_test_instances.hs" #-}
+arbitraryBS = ByteString.pack <$> QuickCheck.arbitrary
+{-# LINE 61 "if/hs_test_instances.hs" #-}
+arbitraryBSMap ::
+                 QuickCheck.Arbitrary a =>
+                 QuickCheck.Gen (Map.Map ByteString.ByteString a)
+{-# LINE 63 "if/hs_test_instances.hs" #-}
+arbitraryBSMap
+  = Map.fromList . Prelude.map (\ (k, v) -> (ByteString.pack k, v))
+      <$> QuickCheck.arbitrary
diff --git a/test/fixtures/gen-hs2/Namespace/E/TU__Service/Client.hs b/test/fixtures/gen-hs2/Namespace/E/TU__Service/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Namespace/E/TU__Service/Client.hs
@@ -0,0 +1,250 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Namespace.E.TU__Service.Client
+       (TU__Service, getNumber, getNumberIO, send_getNumber,
+        _build_getNumber, recv_getNumber, _parse_getNumber, doNothing,
+        doNothingIO, send_doNothing, _build_doNothing, recv_doNothing,
+        _parse_doNothing)
+       where
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import Namespace.E.Types
+
+data TU__Service
+
+getNumber ::
+            (Thrift.Protocol p, Thrift.ClientChannel c,
+             (Thrift.<:) s TU__Service) =>
+            Int.Int32 -> Thrift.ThriftM p c s TU__Type
+getNumber __field__x
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (getNumberIO _proxy _channel _counter _opts __field__x)
+
+getNumberIO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c,
+               (Thrift.<:) s TU__Service) =>
+              Proxy.Proxy p ->
+                c s ->
+                  Thrift.Counter ->
+                    Thrift.RpcOptions -> Int.Int32 -> Prelude.IO TU__Type
+getNumberIO _proxy _channel _counter _opts __field__x
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_getNumber _proxy)
+       send_getNumber _proxy _channel _counter _sendCob _recvCob _opts
+         __field__x
+       Thrift.wait _handle
+
+send_getNumber ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c,
+                  (Thrift.<:) s TU__Service) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback ->
+                         Thrift.RecvCallback ->
+                           Thrift.RpcOptions -> Int.Int32 -> Prelude.IO ()
+send_getNumber _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  __field__x
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString
+                  (_build_getNumber _proxy _seqNum __field__x))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_getNumber ::
+                 (Thrift.Protocol p) =>
+                 Proxy.Proxy p ->
+                   Thrift.Response -> Prelude.Either Exception.SomeException TU__Type
+recv_getNumber _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_getNumber _proxy) _response))
+
+_build_getNumber ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> Int.Int32 -> ByteString.Builder
+_build_getNumber _proxy _seqNum __field__x
+  = Thrift.genMsgBegin _proxy "getNumber" 1 _seqNum <>
+      Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "x" (Thrift.getI32Type _proxy) 1 0
+           (Thrift.genI32Prim _proxy)
+           __field__x
+           : [])
+      <> Thrift.genMsgEnd _proxy
+
+_parse_getNumber ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p ->
+                     Parser.Parser (Prelude.Either Exception.SomeException TU__Type)
+_parse_getNumber _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "getNumber: expected reply but got function call"
+                    2 | _name == "getNumber" ->
+                        do let
+                             _idMap = HashMap.fromList [("getNumber_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI64Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseI64
+                                                                                _proxy)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "getNumber: expected reply but got oneway function call"
+                    _ -> Prelude.fail "getNumber: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
+
+doNothing ::
+            (Thrift.Protocol p, Thrift.ClientChannel c,
+             (Thrift.<:) s TU__Service) =>
+            Thrift.ThriftM p c s ()
+doNothing
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (doNothingIO _proxy _channel _counter _opts)
+
+doNothingIO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c,
+               (Thrift.<:) s TU__Service) =>
+              Proxy.Proxy p ->
+                c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO ()
+doNothingIO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_doNothing _proxy)
+       send_doNothing _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_doNothing ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c,
+                  (Thrift.<:) s TU__Service) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback ->
+                         Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_doNothing _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_doNothing _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_doNothing ::
+                 (Thrift.Protocol p) =>
+                 Proxy.Proxy p ->
+                   Thrift.Response -> Prelude.Either Exception.SomeException ()
+recv_doNothing _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_doNothing _proxy) _response))
+
+_build_doNothing ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_doNothing _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "doNothing" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_doNothing ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p ->
+                     Parser.Parser (Prelude.Either Exception.SomeException ())
+_parse_doNothing _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "doNothing: expected reply but got function call"
+                    2 | _name == "doNothing" ->
+                        do let
+                             _idMap = HashMap.fromList [("ex", 1)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       1 | _type ==
+                                                                             Thrift.getStructType
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             (Prelude.Left .
+                                                                                Exception.SomeException)
+                                                                             (Thrift.parseStruct
+                                                                                _proxy
+                                                                                ::
+                                                                                Parser.Parser
+                                                                                  TU__Exception)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.return (Prelude.Right ())
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "doNothing: expected reply but got oneway function call"
+                    _ -> Prelude.fail "doNothing: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/Namespace/E/TU__Service/Service.hs b/test/fixtures/gen-hs2/Namespace/E/TU__Service/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Namespace/E/TU__Service/Service.hs
@@ -0,0 +1,172 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module Namespace.E.TU__Service.Service
+       (TU__ServiceCommand(..), reqName', reqParser', respWriter',
+        methodsInfo')
+       where
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Namespace.E.Types as Types
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data TU__ServiceCommand a where
+  GetNumber :: Int.Int32 -> TU__ServiceCommand Types.TU__Type
+  DoNothing :: TU__ServiceCommand ()
+
+instance Thrift.Processor TU__ServiceCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: TU__ServiceCommand a -> Text.Text
+reqName' (GetNumber __field__x) = "getNumber"
+reqName' DoNothing = "doNothing"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p ->
+               Text.Text -> Parser.Parser (Thrift.Some TU__ServiceCommand)
+reqParser' _proxy "getNumber"
+  = ST.runSTT
+      (do Prelude.return ()
+          __field__x <- ST.newSTRef Default.def
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               1 | _type == Thrift.getI32Type _proxy
+                                                                   ->
+                                                                   do !_val <- Trans.lift
+                                                                                 (Thrift.parseI32
+                                                                                    _proxy)
+                                                                      ST.writeSTRef __field__x _val
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do !__val__x <- ST.readSTRef __field__x
+                                           Prelude.pure (Thrift.Some (GetNumber __val__x))
+            _idMap = HashMap.fromList [("x", 1)]
+          _parse 0)
+reqParser' _proxy "doNothing"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some DoNothing)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  TU__ServiceCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum GetNumber{} _r
+  = (Thrift.genMsgBegin _proxy "getNumber" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genField _proxy "" (Thrift.getI64Type _proxy) 0 0
+                                         (Thrift.genI64 _proxy _result)],
+                                    Prelude.Nothing)
+respWriter' _proxy _seqNum DoNothing{} _r
+  = (Thrift.genMsgBegin _proxy "doNothing" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.Just _e@Types.TU__Exception{} <- Exception.fromException
+                                                                        _ex
+                             ->
+                             (2,
+                              Thrift.genStruct _proxy
+                                [Thrift.genField _proxy "ex" (Thrift.getStructType _proxy) 1 0
+                                   (Thrift.buildStruct _proxy _e)],
+                              Prelude.Just (_ex, Thrift.ClientError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2, Thrift.genStruct _proxy [],
+                                    Prelude.Nothing)
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.fromList
+      [("getNumber",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False),
+       ("doNothing",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False)]
diff --git a/test/fixtures/gen-hs2/Namespace/E/Types.hs b/test/fixtures/gen-hs2/Namespace/E/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Namespace/E/Types.hs
@@ -0,0 +1,268 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Namespace.E.Types
+       (TU__Type, TU__Exception(TU__Exception, _Exception_reason), a,
+        TU__Struct(TU__Struct, _Struct_a, _Struct_b),
+        TU__Union(TU__Union_EMPTY, TU__Union_x, TU__Union_y, TU__Union_z),
+        u)
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Ord as Ord
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Aeson ((.:), (.=))
+import Data.Monoid ((<>))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (++))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+type TU__Type = Int.Int64
+
+newtype TU__Exception = TU__Exception{_Exception_reason ::
+                                      Text.Text}
+                        deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TU__Exception where
+  toJSON (TU__Exception __field__reason)
+    = Aeson.object ("reason" .= __field__reason : Prelude.mempty)
+
+instance Thrift.ThriftStruct TU__Exception where
+  buildStruct _proxy (TU__Exception __field__reason)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "reason" (Thrift.getStringType _proxy) 1 0
+           (Thrift.genText _proxy __field__reason)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__reason <- ST.newSTRef ""
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef
+                                                                          __field__reason
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__reason <- ST.readSTRef
+                                                                 __field__reason
+                                             Prelude.pure (TU__Exception __val__reason)
+              _idMap = HashMap.fromList [("reason", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData TU__Exception where
+  rnf (TU__Exception __field__reason)
+    = DeepSeq.rnf __field__reason `Prelude.seq` ()
+
+instance Default.Default TU__Exception where
+  def = TU__Exception ""
+
+instance Hashable.Hashable TU__Exception where
+  hashWithSalt __salt (TU__Exception _reason)
+    = Hashable.hashWithSalt __salt _reason
+
+instance Exception.Exception TU__Exception
+
+a :: TU__Type
+a = 100
+
+data TU__Struct = TU__Struct{_Struct_a :: TU__Type,
+                             _Struct_b :: [[TU__Type]]}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TU__Struct where
+  toJSON (TU__Struct __field__a __field__b)
+    = Aeson.object
+        ("a" .= __field__a : "b" .= __field__b : Prelude.mempty)
+
+instance Thrift.ThriftStruct TU__Struct where
+  buildStruct _proxy (TU__Struct __field__a __field__b)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "a" (Thrift.getI64Type _proxy) 1 0
+           (Thrift.genI64 _proxy __field__a)
+           :
+           Thrift.genField _proxy "b" (Thrift.getListType _proxy) 2 1
+             (Thrift.genList _proxy (Thrift.getListType _proxy)
+                (Thrift.genList _proxy (Thrift.getI64Type _proxy)
+                   (Thrift.genI64 _proxy))
+                __field__b)
+             : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__a <- ST.newSTRef a
+            __field__b <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI64Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseI64
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__a
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Prelude.snd
+                                                                                           <$>
+                                                                                           Thrift.parseList
+                                                                                             _proxy
+                                                                                             (Thrift.parseI64
+                                                                                                _proxy)))
+                                                                        ST.writeSTRef __field__b
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__a <- ST.readSTRef __field__a
+                                             !__val__b <- ST.readSTRef __field__b
+                                             Prelude.pure (TU__Struct __val__a __val__b)
+              _idMap = HashMap.fromList [("a", 1), ("b", 2)]
+            _parse 0)
+
+instance DeepSeq.NFData TU__Struct where
+  rnf (TU__Struct __field__a __field__b)
+    = DeepSeq.rnf __field__a `Prelude.seq`
+        DeepSeq.rnf __field__b `Prelude.seq` ()
+
+instance Default.Default TU__Struct where
+  def = TU__Struct a Default.def
+
+instance Hashable.Hashable TU__Struct where
+  hashWithSalt __salt (TU__Struct _a _b)
+    = Hashable.hashWithSalt (Hashable.hashWithSalt __salt _a) _b
+
+data TU__Union = TU__Union_x Int.Int8
+               | TU__Union_y [Text.Text]
+               | TU__Union_z (Set.Set Int.Int64)
+               | TU__Union_EMPTY
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TU__Union where
+  toJSON (TU__Union_x __x) = Aeson.object ["x" .= __x]
+  toJSON (TU__Union_y __y) = Aeson.object ["y" .= __y]
+  toJSON (TU__Union_z __z) = Aeson.object ["z" .= __z]
+  toJSON TU__Union_EMPTY = Aeson.object []
+
+instance Thrift.ThriftStruct TU__Union where
+  buildStruct _proxy (TU__Union_x __x)
+    = Thrift.genStruct _proxy
+        [Thrift.genFieldPrim _proxy "x" (Thrift.getByteType _proxy) 1 0
+           (Thrift.genBytePrim _proxy)
+           __x]
+  buildStruct _proxy (TU__Union_y __y)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "y" (Thrift.getListType _proxy) 2 0
+           (Thrift.genList _proxy (Thrift.getStringType _proxy)
+              (Thrift.genText _proxy)
+              __y)]
+  buildStruct _proxy (TU__Union_z __z)
+    = Thrift.genStruct _proxy
+        [Thrift.genField _proxy "z" (Thrift.getSetType _proxy) 3 0
+           ((Thrift.genListPrim _proxy (Thrift.getI64Type _proxy)
+               (Thrift.genI64Prim _proxy)
+               . Set.toList)
+              __z)]
+  buildStruct _proxy TU__Union_EMPTY = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = do _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+         case _fieldBegin of
+           Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                     1 | _type == Thrift.getByteType _proxy ->
+                                                         do _val <- Thrift.parseByte _proxy
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (TU__Union_x _val)
+                                                     2 | _type == Thrift.getListType _proxy ->
+                                                         do _val <- Prelude.snd <$>
+                                                                      Thrift.parseList _proxy
+                                                                        (Thrift.parseText _proxy)
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (TU__Union_y _val)
+                                                     3 | _type == Thrift.getSetType _proxy ->
+                                                         do _val <- Set.fromList . Prelude.snd <$>
+                                                                      Thrift.parseList _proxy
+                                                                        (Thrift.parseI64 _proxy)
+                                                            Thrift.parseStop _proxy
+                                                            Prelude.return (TU__Union_z _val)
+                                                     _ -> do Thrift.parseSkip _proxy _type
+                                                               Prelude.Nothing
+                                                             Thrift.parseStop _proxy
+                                                             Prelude.return TU__Union_EMPTY
+           Thrift.FieldEnd -> Prelude.return TU__Union_EMPTY
+    where
+      _idMap = HashMap.fromList [("x", 1), ("y", 2), ("z", 3)]
+
+instance DeepSeq.NFData TU__Union where
+  rnf (TU__Union_x __x) = DeepSeq.rnf __x
+  rnf (TU__Union_y __y) = DeepSeq.rnf __y
+  rnf (TU__Union_z __z) = DeepSeq.rnf __z
+  rnf TU__Union_EMPTY = ()
+
+instance Default.Default TU__Union where
+  def = TU__Union_EMPTY
+
+instance Hashable.Hashable TU__Union where
+  hashWithSalt __salt (TU__Union_x _x)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 1 _x)
+  hashWithSalt __salt (TU__Union_y _y)
+    = Hashable.hashWithSalt __salt (Hashable.hashWithSalt 2 _y)
+  hashWithSalt __salt (TU__Union_z _z)
+    = Hashable.hashWithSalt __salt
+        (Hashable.hashWithSalt 3 (Set.elems _z))
+  hashWithSalt __salt TU__Union_EMPTY
+    = Hashable.hashWithSalt __salt (0 :: Prelude.Int)
+
+u :: TU__Union
+u = TU__Union_y ["test"]
diff --git a/test/fixtures/gen-hs2/Scope/Types.hs b/test/fixtures/gen-hs2/Scope/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Scope/Types.hs
@@ -0,0 +1,637 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Scope.Types
+       (Transitive(Transitive), Program(Program), Struct(Struct),
+        Union(Union), Exception(Exception), Field(Field), Typedef(Typedef),
+        Service(Service), Interaction(Interaction), Function(Function),
+        EnumValue(EnumValue), Const(Const), Enum(Enum),
+        Structured(Structured), Interface(Interface),
+        RootDefinition(RootDefinition), Definition(Definition))
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.List as List
+import qualified Data.Ord as Ord
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Monoid ((<>))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+data Transitive = Transitive{}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Transitive where
+  toJSON Transitive = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Transitive where
+  buildStruct _proxy Transitive = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Transitive)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Transitive where
+  rnf Transitive = ()
+
+instance Default.Default Transitive where
+  def = Transitive
+
+instance Hashable.Hashable Transitive where
+  hashWithSalt __salt Transitive = __salt
+
+data Program = Program{}
+               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Program where
+  toJSON Program = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Program where
+  buildStruct _proxy Program = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Program)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Program where
+  rnf Program = ()
+
+instance Default.Default Program where
+  def = Program
+
+instance Hashable.Hashable Program where
+  hashWithSalt __salt Program = __salt
+
+data Struct = Struct{}
+              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Struct where
+  toJSON Struct = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Struct where
+  buildStruct _proxy Struct = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Struct)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Struct where
+  rnf Struct = ()
+
+instance Default.Default Struct where
+  def = Struct
+
+instance Hashable.Hashable Struct where
+  hashWithSalt __salt Struct = __salt
+
+data Union = Union{}
+             deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Union where
+  toJSON Union = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Union where
+  buildStruct _proxy Union = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Union)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Union where
+  rnf Union = ()
+
+instance Default.Default Union where
+  def = Union
+
+instance Hashable.Hashable Union where
+  hashWithSalt __salt Union = __salt
+
+data Exception = Exception{}
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Exception where
+  toJSON Exception = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Exception where
+  buildStruct _proxy Exception = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Exception)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Exception where
+  rnf Exception = ()
+
+instance Default.Default Exception where
+  def = Exception
+
+instance Hashable.Hashable Exception where
+  hashWithSalt __salt Exception = __salt
+
+data Field = Field{}
+             deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Field where
+  toJSON Field = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Field where
+  buildStruct _proxy Field = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Field)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Field where
+  rnf Field = ()
+
+instance Default.Default Field where
+  def = Field
+
+instance Hashable.Hashable Field where
+  hashWithSalt __salt Field = __salt
+
+data Typedef = Typedef{}
+               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Typedef where
+  toJSON Typedef = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Typedef where
+  buildStruct _proxy Typedef = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Typedef)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Typedef where
+  rnf Typedef = ()
+
+instance Default.Default Typedef where
+  def = Typedef
+
+instance Hashable.Hashable Typedef where
+  hashWithSalt __salt Typedef = __salt
+
+data Service = Service{}
+               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Service where
+  toJSON Service = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Service where
+  buildStruct _proxy Service = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Service)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Service where
+  rnf Service = ()
+
+instance Default.Default Service where
+  def = Service
+
+instance Hashable.Hashable Service where
+  hashWithSalt __salt Service = __salt
+
+data Interaction = Interaction{}
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Interaction where
+  toJSON Interaction = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Interaction where
+  buildStruct _proxy Interaction = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Interaction)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Interaction where
+  rnf Interaction = ()
+
+instance Default.Default Interaction where
+  def = Interaction
+
+instance Hashable.Hashable Interaction where
+  hashWithSalt __salt Interaction = __salt
+
+data Function = Function{}
+                deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Function where
+  toJSON Function = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Function where
+  buildStruct _proxy Function = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Function)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Function where
+  rnf Function = ()
+
+instance Default.Default Function where
+  def = Function
+
+instance Hashable.Hashable Function where
+  hashWithSalt __salt Function = __salt
+
+data EnumValue = EnumValue{}
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON EnumValue where
+  toJSON EnumValue = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct EnumValue where
+  buildStruct _proxy EnumValue = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (EnumValue)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData EnumValue where
+  rnf EnumValue = ()
+
+instance Default.Default EnumValue where
+  def = EnumValue
+
+instance Hashable.Hashable EnumValue where
+  hashWithSalt __salt EnumValue = __salt
+
+data Const = Const{}
+             deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Const where
+  toJSON Const = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Const where
+  buildStruct _proxy Const = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Const)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Const where
+  rnf Const = ()
+
+instance Default.Default Const where
+  def = Const
+
+instance Hashable.Hashable Const where
+  hashWithSalt __salt Const = __salt
+
+data Enum = Enum{}
+            deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Enum where
+  toJSON Enum = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Enum where
+  buildStruct _proxy Enum = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Enum)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Enum where
+  rnf Enum = ()
+
+instance Default.Default Enum where
+  def = Enum
+
+instance Hashable.Hashable Enum where
+  hashWithSalt __salt Enum = __salt
+
+data Structured = Structured{}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Structured where
+  toJSON Structured = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Structured where
+  buildStruct _proxy Structured = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Structured)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Structured where
+  rnf Structured = ()
+
+instance Default.Default Structured where
+  def = Structured
+
+instance Hashable.Hashable Structured where
+  hashWithSalt __salt Structured = __salt
+
+data Interface = Interface{}
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Interface where
+  toJSON Interface = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Interface where
+  buildStruct _proxy Interface = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Interface)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Interface where
+  rnf Interface = ()
+
+instance Default.Default Interface where
+  def = Interface
+
+instance Hashable.Hashable Interface where
+  hashWithSalt __salt Interface = __salt
+
+data RootDefinition = RootDefinition{}
+                      deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON RootDefinition where
+  toJSON RootDefinition = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct RootDefinition where
+  buildStruct _proxy RootDefinition = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (RootDefinition)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData RootDefinition where
+  rnf RootDefinition = ()
+
+instance Default.Default RootDefinition where
+  def = RootDefinition
+
+instance Hashable.Hashable RootDefinition where
+  hashWithSalt __salt RootDefinition = __salt
+
+data Definition = Definition{}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Definition where
+  toJSON Definition = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Definition where
+  buildStruct _proxy Definition = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Definition)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Definition where
+  rnf Definition = ()
+
+instance Default.Default Definition where
+  def = Definition
+
+instance Hashable.Hashable Definition where
+  hashWithSalt __salt Definition = __salt
diff --git a/test/fixtures/gen-hs2/Service/MyService/Client.hs b/test/fixtures/gen-hs2/Service/MyService/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/MyService/Client.hs
@@ -0,0 +1,254 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Service.MyService.Client
+       (MyService, testFunc, testFuncIO, send_testFunc, _build_testFunc,
+        recv_testFunc, _parse_testFunc, x_foo, x_fooIO, send_x_foo,
+        _build_x_foo, recv_x_foo, _parse_x_foo)
+       where
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import Service.Types
+
+data MyService
+
+testFunc ::
+           (Thrift.Protocol p, Thrift.ClientChannel c,
+            (Thrift.<:) s MyService) =>
+           Int.Int64 -> Z -> Thrift.ThriftM p c s Int.Int64
+testFunc __field__arg1 __field__arg2
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift
+         (testFuncIO _proxy _channel _counter _opts __field__arg1
+            __field__arg2)
+
+testFuncIO ::
+             (Thrift.Protocol p, Thrift.ClientChannel c,
+              (Thrift.<:) s MyService) =>
+             Proxy.Proxy p ->
+               c s ->
+                 Thrift.Counter ->
+                   Thrift.RpcOptions -> Int.Int64 -> Z -> Prelude.IO Int.Int64
+testFuncIO _proxy _channel _counter _opts __field__arg1
+  __field__arg2
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_testFunc _proxy)
+       send_testFunc _proxy _channel _counter _sendCob _recvCob _opts
+         __field__arg1
+         __field__arg2
+       Thrift.wait _handle
+
+send_testFunc ::
+                (Thrift.Protocol p, Thrift.ClientChannel c,
+                 (Thrift.<:) s MyService) =>
+                Proxy.Proxy p ->
+                  c s ->
+                    Thrift.Counter ->
+                      Thrift.SendCallback ->
+                        Thrift.RecvCallback ->
+                          Thrift.RpcOptions -> Int.Int64 -> Z -> Prelude.IO ()
+send_testFunc _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  __field__arg1 __field__arg2
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString
+                  (_build_testFunc _proxy _seqNum __field__arg1 __field__arg2))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_testFunc ::
+                (Thrift.Protocol p) =>
+                Proxy.Proxy p ->
+                  Thrift.Response -> Prelude.Either Exception.SomeException Int.Int64
+recv_testFunc _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_testFunc _proxy) _response))
+
+_build_testFunc ::
+                  Thrift.Protocol p =>
+                  Proxy.Proxy p -> Int.Int32 -> Int.Int64 -> Z -> ByteString.Builder
+_build_testFunc _proxy _seqNum __field__arg1 __field__arg2
+  = Thrift.genMsgBegin _proxy "testFunc" 1 _seqNum <>
+      Thrift.genStruct _proxy
+        (Thrift.genFieldPrim _proxy "arg1" (Thrift.getI64Type _proxy) 1 0
+           (Thrift.genI64Prim _proxy)
+           __field__arg1
+           :
+           Thrift.genField _proxy "arg2" (Thrift.getStructType _proxy) 2 1
+             (Thrift.buildStruct _proxy __field__arg2)
+             : [])
+      <> Thrift.genMsgEnd _proxy
+
+_parse_testFunc ::
+                  Thrift.Protocol p =>
+                  Proxy.Proxy p ->
+                    Parser.Parser (Prelude.Either Exception.SomeException Int.Int64)
+_parse_testFunc _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "testFunc: expected reply but got function call"
+                    2 | _name == "testFunc" ->
+                        do let
+                             _idMap = HashMap.fromList [("testFunc_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI64Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseI64
+                                                                                _proxy)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "testFunc: expected reply but got oneway function call"
+                    _ -> Prelude.fail "testFunc: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
+
+x_foo ::
+        (Thrift.Protocol p, Thrift.ClientChannel c,
+         (Thrift.<:) s MyService) =>
+        Thrift.ThriftM p c s ()
+x_foo
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (x_fooIO _proxy _channel _counter _opts)
+
+x_fooIO ::
+          (Thrift.Protocol p, Thrift.ClientChannel c,
+           (Thrift.<:) s MyService) =>
+          Proxy.Proxy p ->
+            c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO ()
+x_fooIO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_x_foo _proxy)
+       send_x_foo _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_x_foo ::
+             (Thrift.Protocol p, Thrift.ClientChannel c,
+              (Thrift.<:) s MyService) =>
+             Proxy.Proxy p ->
+               c s ->
+                 Thrift.Counter ->
+                   Thrift.SendCallback ->
+                     Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_x_foo _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_x_foo _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_x_foo ::
+             (Thrift.Protocol p) =>
+             Proxy.Proxy p ->
+               Thrift.Response -> Prelude.Either Exception.SomeException ()
+recv_x_foo _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_x_foo _proxy) _response))
+
+_build_x_foo ::
+               Thrift.Protocol p =>
+               Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_x_foo _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "foo" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_x_foo ::
+               Thrift.Protocol p =>
+               Proxy.Proxy p ->
+                 Parser.Parser (Prelude.Either Exception.SomeException ())
+_parse_x_foo _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "foo: expected reply but got function call"
+                    2 | _name == "foo" ->
+                        do let
+                             _idMap = HashMap.fromList [("ex", 1)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       1 | _type ==
+                                                                             Thrift.getStructType
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             (Prelude.Left .
+                                                                                Exception.SomeException)
+                                                                             (Thrift.parseStruct
+                                                                                _proxy
+                                                                                :: Parser.Parser Ex)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.return (Prelude.Right ())
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "foo: expected reply but got oneway function call"
+                    _ -> Prelude.fail "foo: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/Service/MyService/Service.hs b/test/fixtures/gen-hs2/Service/MyService/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/MyService/Service.hs
@@ -0,0 +1,181 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module Service.MyService.Service
+       (MyServiceCommand(..), reqName', reqParser', respWriter',
+        methodsInfo')
+       where
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Service.Types as Types
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data MyServiceCommand a where
+  TestFunc :: Int.Int64 -> Types.Z -> MyServiceCommand Int.Int64
+  Foo :: MyServiceCommand ()
+
+instance Thrift.Processor MyServiceCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: MyServiceCommand a -> Text.Text
+reqName' (TestFunc __field__arg1 __field__arg2) = "testFunc"
+reqName' Foo = "foo"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p ->
+               Text.Text -> Parser.Parser (Thrift.Some MyServiceCommand)
+reqParser' _proxy "testFunc"
+  = ST.runSTT
+      (do Prelude.return ()
+          __field__arg1 <- ST.newSTRef Default.def
+          __field__arg2 <- ST.newSTRef Types.z
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               1 | _type == Thrift.getI64Type _proxy
+                                                                   ->
+                                                                   do !_val <- Trans.lift
+                                                                                 (Thrift.parseI64
+                                                                                    _proxy)
+                                                                      ST.writeSTRef __field__arg1
+                                                                        _val
+                                                               2 | _type ==
+                                                                     Thrift.getStructType _proxy
+                                                                   ->
+                                                                   do !_val <- Trans.lift
+                                                                                 (Thrift.parseStruct
+                                                                                    _proxy)
+                                                                      ST.writeSTRef __field__arg2
+                                                                        _val
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do !__val__arg1 <- ST.readSTRef __field__arg1
+                                           !__val__arg2 <- ST.readSTRef __field__arg2
+                                           Prelude.pure
+                                             (Thrift.Some (TestFunc __val__arg1 __val__arg2))
+            _idMap = HashMap.fromList [("arg1", 1), ("arg2", 2)]
+          _parse 0)
+reqParser' _proxy "foo"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some Foo)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  MyServiceCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum TestFunc{} _r
+  = (Thrift.genMsgBegin _proxy "testFunc" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genFieldPrim _proxy "" (Thrift.getI64Type _proxy) 0 0
+                                         (Thrift.genI64Prim _proxy)
+                                         _result],
+                                    Prelude.Nothing)
+respWriter' _proxy _seqNum Foo{} _r
+  = (Thrift.genMsgBegin _proxy "foo" _msgType _seqNum <> _msgBody <>
+       Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.Just _e@Types.Ex{} <- Exception.fromException _ex ->
+                             (2,
+                              Thrift.genStruct _proxy
+                                [Thrift.genField _proxy "ex" (Thrift.getStructType _proxy) 1 0
+                                   (Thrift.buildStruct _proxy _e)],
+                              Prelude.Just (_ex, Thrift.ClientError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2, Thrift.genStruct _proxy [],
+                                    Prelude.Nothing)
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.fromList
+      [("testFunc",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False),
+       ("foo", Thrift.MethodInfo Thrift.NormalPriority Prelude.False)]
diff --git a/test/fixtures/gen-hs2/Service/Q/Client.hs b/test/fixtures/gen-hs2/Service/Q/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/Q/Client.hs
@@ -0,0 +1,180 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Service.Q.Client
+       (Q, testFunc1, testFunc1IO, send_testFunc1, _build_testFunc1,
+        testFunc2, testFunc2IO, send_testFunc2, _build_testFunc2,
+        recv_testFunc2, _parse_testFunc2)
+       where
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import Service.Types
+
+data Q
+
+testFunc1 ::
+            (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+            Thrift.ThriftM p c s ()
+testFunc1
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (testFunc1IO _proxy _channel _counter _opts)
+
+testFunc1IO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+              Proxy.Proxy p ->
+                c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO ()
+testFunc1IO _proxy _channel _counter _opts
+  = do _handle <- Concurrent.newEmptyMVar
+       send_testFunc1 _proxy _channel _counter
+         (Concurrent.putMVar _handle)
+         _opts
+       Concurrent.takeMVar _handle >>=
+         Prelude.maybe (Prelude.return ()) Exception.throw
+
+send_testFunc1 ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_testFunc1 _proxy _channel _counter _sendCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_testFunc1 _proxy _seqNum))
+       Thrift.sendOnewayRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+
+_build_testFunc1 ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_testFunc1 _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "testFunc1" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+testFunc2 ::
+            (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+            Thrift.ThriftM p c s Int.Int32
+testFunc2
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (testFunc2IO _proxy _channel _counter _opts)
+
+testFunc2IO ::
+              (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+              Proxy.Proxy p ->
+                c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO Int.Int32
+testFunc2IO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_testFunc2 _proxy)
+       send_testFunc2 _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_testFunc2 ::
+                 (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s Q) =>
+                 Proxy.Proxy p ->
+                   c s ->
+                     Thrift.Counter ->
+                       Thrift.SendCallback ->
+                         Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_testFunc2 _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_testFunc2 _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_testFunc2 ::
+                 (Thrift.Protocol p) =>
+                 Proxy.Proxy p ->
+                   Thrift.Response -> Prelude.Either Exception.SomeException Int.Int32
+recv_testFunc2 _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_testFunc2 _proxy) _response))
+
+_build_testFunc2 ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_testFunc2 _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "testFunc2" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_testFunc2 ::
+                   Thrift.Protocol p =>
+                   Proxy.Proxy p ->
+                     Parser.Parser (Prelude.Either Exception.SomeException Int.Int32)
+_parse_testFunc2 _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "testFunc2: expected reply but got function call"
+                    2 | _name == "testFunc2" ->
+                        do let
+                             _idMap = HashMap.fromList [("testFunc2_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI32Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseI32
+                                                                                _proxy)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "testFunc2: expected reply but got oneway function call"
+                    _ -> Prelude.fail "testFunc2: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/Service/Q/Service.hs b/test/fixtures/gen-hs2/Service/Q/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/Q/Service.hs
@@ -0,0 +1,155 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module Service.Q.Service
+       (QCommand(..), reqName', reqParser', respWriter', methodsInfo')
+       where
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Service.Types as Types
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data QCommand a where
+  TestFunc1 :: QCommand ()
+  TestFunc2 :: QCommand Int.Int32
+
+instance Thrift.Processor QCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: QCommand a -> Text.Text
+reqName' TestFunc1 = "testFunc1"
+reqName' TestFunc2 = "testFunc2"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p -> Text.Text -> Parser.Parser (Thrift.Some QCommand)
+reqParser' _proxy "testFunc1"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some TestFunc1)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _proxy "testFunc2"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some TestFunc2)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  QCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum TestFunc1{} _r
+  = (Thrift.genMsgBegin _proxy "testFunc1" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2, Thrift.genStruct _proxy [],
+                                    Prelude.Nothing)
+respWriter' _proxy _seqNum TestFunc2{} _r
+  = (Thrift.genMsgBegin _proxy "testFunc2" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genFieldPrim _proxy "" (Thrift.getI32Type _proxy) 0 0
+                                         (Thrift.genI32Prim _proxy)
+                                         _result],
+                                    Prelude.Nothing)
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.fromList
+      [("testFunc1",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.True),
+       ("testFunc2",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False)]
diff --git a/test/fixtures/gen-hs2/Service/Types.hs b/test/fixtures/gen-hs2/Service/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/Types.hs
@@ -0,0 +1,168 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Service.Types (Z(Z, z_name), z, TestFunc(TestFunc), Ex(Ex))
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.List as List
+import qualified Data.Ord as Ord
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Monoid ((<>))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+newtype Z = Z{z_name :: Text.Text}
+            deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Z where
+  toJSON (Z __field__name)
+    = Aeson.object ("name" .= __field__name : Prelude.mempty)
+
+instance Thrift.ThriftStruct Z where
+  buildStruct _proxy (Z __field__name)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "name" (Thrift.getStringType _proxy) 1 0
+           (Thrift.genText _proxy __field__name)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__name <- ST.newSTRef ""
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__name
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__name <- ST.readSTRef __field__name
+                                             Prelude.pure (Z __val__name)
+              _idMap = HashMap.fromList [("name", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData Z where
+  rnf (Z __field__name) = DeepSeq.rnf __field__name `Prelude.seq` ()
+
+instance Default.Default Z where
+  def = Z ""
+
+instance Hashable.Hashable Z where
+  hashWithSalt __salt (Z _name) = Hashable.hashWithSalt __salt _name
+
+instance Thrift.HasField "name" Z (Text.Text) where
+  getField = z_name
+
+z :: Z
+z = (Default.def :: Z){z_name = "Z"}
+
+data TestFunc = TestFunc{}
+                deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TestFunc where
+  toJSON TestFunc = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct TestFunc where
+  buildStruct _proxy TestFunc = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (TestFunc)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData TestFunc where
+  rnf TestFunc = ()
+
+instance Default.Default TestFunc where
+  def = TestFunc
+
+instance Hashable.Hashable TestFunc where
+  hashWithSalt __salt TestFunc = __salt
+
+data Ex = Ex{}
+          deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Ex where
+  toJSON Ex = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Ex where
+  buildStruct _proxy Ex = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Ex)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Ex where
+  rnf Ex = ()
+
+instance Default.Default Ex where
+  def = Ex
+
+instance Hashable.Hashable Ex where
+  hashWithSalt __salt Ex = __salt
+
+instance Exception.Exception Ex
diff --git a/test/fixtures/gen-hs2/Service/X/Client.hs b/test/fixtures/gen-hs2/Service/X/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/X/Client.hs
@@ -0,0 +1,135 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Service.X.Client
+       (X, testFunc, testFuncIO, send_testFunc, _build_testFunc,
+        recv_testFunc, _parse_testFunc)
+       where
+import qualified Control.Arrow as Arrow
+import qualified Control.Concurrent as Concurrent
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Data.ByteString.Builder as ByteString
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Proxy as Proxy
+import qualified Prelude as Prelude
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Data.Monoid ((<>))
+import Prelude ((==), (=<<), (>>=), (<$>), (.))
+import Service.Types
+
+data X
+
+testFunc ::
+           (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s X) =>
+           Thrift.ThriftM p c s Int.Int32
+testFunc
+  = do Thrift.ThriftEnv _proxy _channel _opts _counter <- Reader.ask
+       Trans.lift (testFuncIO _proxy _channel _counter _opts)
+
+testFuncIO ::
+             (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s X) =>
+             Proxy.Proxy p ->
+               c s -> Thrift.Counter -> Thrift.RpcOptions -> Prelude.IO Int.Int32
+testFuncIO _proxy _channel _counter _opts
+  = do (_handle, _sendCob, _recvCob) <- Thrift.mkCallbacks
+                                          (recv_testFunc _proxy)
+       send_testFunc _proxy _channel _counter _sendCob _recvCob _opts
+       Thrift.wait _handle
+
+send_testFunc ::
+                (Thrift.Protocol p, Thrift.ClientChannel c, (Thrift.<:) s X) =>
+                Proxy.Proxy p ->
+                  c s ->
+                    Thrift.Counter ->
+                      Thrift.SendCallback ->
+                        Thrift.RecvCallback -> Thrift.RpcOptions -> Prelude.IO ()
+send_testFunc _proxy _channel _counter _sendCob _recvCob _rpcOpts
+  = do _seqNum <- _counter
+       let
+         _callMsg
+           = LBS.toStrict
+               (ByteString.toLazyByteString (_build_testFunc _proxy _seqNum))
+       Thrift.sendRequest _channel
+         (Thrift.Request _callMsg
+            (Thrift.setRpcPriority _rpcOpts Thrift.NormalPriority))
+         _sendCob
+         _recvCob
+
+recv_testFunc ::
+                (Thrift.Protocol p) =>
+                Proxy.Proxy p ->
+                  Thrift.Response -> Prelude.Either Exception.SomeException Int.Int32
+recv_testFunc _proxy (Thrift.Response _response _)
+  = Monad.join
+      (Arrow.left (Exception.SomeException . Thrift.ProtocolException)
+         (Parser.parse (_parse_testFunc _proxy) _response))
+
+_build_testFunc ::
+                  Thrift.Protocol p =>
+                  Proxy.Proxy p -> Int.Int32 -> ByteString.Builder
+_build_testFunc _proxy _seqNum
+  = Thrift.genMsgBegin _proxy "testFunc" 1 _seqNum <>
+      Thrift.genStruct _proxy []
+      <> Thrift.genMsgEnd _proxy
+
+_parse_testFunc ::
+                  Thrift.Protocol p =>
+                  Proxy.Proxy p ->
+                    Parser.Parser (Prelude.Either Exception.SomeException Int.Int32)
+_parse_testFunc _proxy
+  = do Thrift.MsgBegin _name _msgTy _ <- Thrift.parseMsgBegin _proxy
+       _result <- case _msgTy of
+                    1 -> Prelude.fail "testFunc: expected reply but got function call"
+                    2 | _name == "testFunc" ->
+                        do let
+                             _idMap = HashMap.fromList [("testFunc_success", 0)]
+                           _fieldBegin <- Thrift.parseFieldBegin _proxy 0 _idMap
+                           case _fieldBegin of
+                             Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                       0 | _type ==
+                                                                             Thrift.getI32Type
+                                                                               _proxy
+                                                                           ->
+                                                                           Prelude.fmap
+                                                                             Prelude.Right
+                                                                             (Thrift.parseI32
+                                                                                _proxy)
+                                                                       _ -> Prelude.fail
+                                                                              (Prelude.unwords
+                                                                                 ["unrecognized exception, type:",
+                                                                                  Prelude.show
+                                                                                    _type,
+                                                                                  "field id:",
+                                                                                  Prelude.show _id])
+                             Thrift.FieldEnd -> Prelude.fail "no response"
+                      | Prelude.otherwise -> Prelude.fail "reply function does not match"
+                    3 -> Prelude.fmap (Prelude.Left . Exception.SomeException)
+                           (Thrift.parseStruct _proxy ::
+                              Parser.Parser Thrift.ApplicationException)
+                    4 -> Prelude.fail
+                           "testFunc: expected reply but got oneway function call"
+                    _ -> Prelude.fail "testFunc: invalid message type"
+       Thrift.parseMsgEnd _proxy
+       Prelude.return _result
diff --git a/test/fixtures/gen-hs2/Service/X/Service.hs b/test/fixtures/gen-hs2/Service/X/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/X/Service.hs
@@ -0,0 +1,113 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module Service.X.Service
+       (XCommand(..), reqName', reqParser', respWriter', methodsInfo')
+       where
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Service.Types as Types
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data XCommand a where
+  TestFunc :: XCommand Int.Int32
+
+instance Thrift.Processor XCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: XCommand a -> Text.Text
+reqName' TestFunc = "testFunc"
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p -> Text.Text -> Parser.Parser (Thrift.Some XCommand)
+reqParser' _proxy "testFunc"
+  = ST.runSTT
+      (do Prelude.return ()
+          let
+            _parse _lastId
+              = do _fieldBegin <- Trans.lift
+                                    (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                   case _fieldBegin of
+                     Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                               _ -> Trans.lift
+                                                                      (Thrift.parseSkip _proxy _type
+                                                                         (Prelude.Just _bool))
+                                                             _parse _id
+                     Thrift.FieldEnd -> do Prelude.pure (Thrift.Some TestFunc)
+            _idMap = HashMap.fromList []
+          _parse 0)
+reqParser' _ funName
+  = Prelude.errorWithoutStackTrace
+      ("unknown function call: " ++ Text.unpack funName)
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  XCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum TestFunc{} _r
+  = (Thrift.genMsgBegin _proxy "testFunc" _msgType _seqNum <>
+       _msgBody
+       <> Thrift.genMsgEnd _proxy,
+     _msgException)
+  where
+    (_msgType, _msgBody, _msgException)
+      = case _r of
+          Prelude.Left _ex | Prelude.Just
+                               _e@Thrift.ApplicationException{} <- Exception.fromException _ex
+                             ->
+                             (3, Thrift.buildStruct _proxy _e,
+                              Prelude.Just (_ex, Thrift.ServerError))
+                           | Prelude.otherwise ->
+                             let _e
+                                   = Thrift.ApplicationException (Text.pack (Prelude.show _ex))
+                                       Thrift.ApplicationExceptionType_InternalError
+                               in
+                               (3, Thrift.buildStruct _proxy _e,
+                                Prelude.Just (Exception.toException _e, Thrift.ServerError))
+          Prelude.Right _result -> (2,
+                                    Thrift.genStruct _proxy
+                                      [Thrift.genFieldPrim _proxy "" (Thrift.getI32Type _proxy) 0 0
+                                         (Thrift.genI32Prim _proxy)
+                                         _result],
+                                    Prelude.Nothing)
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo'
+  = Map.fromList
+      [("testFunc",
+        Thrift.MethodInfo Thrift.NormalPriority Prelude.False)]
diff --git a/test/fixtures/gen-hs2/Service/Y/Client.hs b/test/fixtures/gen-hs2/Service/Y/Client.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/Y/Client.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Service.Y.Client (Y) where
+import qualified Service.X.Client as X
+import qualified Thrift.Codegen as Thrift
+import Service.Types
+
+data Y
+
+type instance Thrift.Super Y = X.X
diff --git a/test/fixtures/gen-hs2/Service/Y/Service.hs b/test/fixtures/gen-hs2/Service/Y/Service.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Service/Y/Service.hs
@@ -0,0 +1,71 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-record-updates#-}
+{-# LANGUAGE GADTs #-}
+module Service.Y.Service
+       (YCommand(..), reqName', reqParser', respWriter', methodsInfo')
+       where
+import qualified Control.Exception as Exception
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.ByteString.Builder as Builder
+import qualified Data.Default as Default
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Int as Int
+import qualified Data.Map.Strict as Map
+import qualified Data.Proxy as Proxy
+import qualified Data.Text as Text
+import qualified Prelude as Prelude
+import qualified Service.Types as Types
+import qualified Service.X.Service as X
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.Codegen as Thrift
+import qualified Thrift.Processor as Thrift
+import qualified Thrift.Protocol.ApplicationException.Types
+       as Thrift
+import Control.Applicative ((<*), (*>))
+import Data.Monoid ((<>))
+import Prelude ((<$>), (<*>), (++), (.), (==))
+
+data YCommand a where
+  SuperX :: X.XCommand a -> YCommand a
+
+instance Thrift.Processor YCommand where
+  reqName = reqName'
+  reqParser = reqParser'
+  respWriter = respWriter'
+  methodsInfo _ = methodsInfo'
+
+reqName' :: YCommand a -> Text.Text
+reqName' (SuperX x) = X.reqName' x
+
+reqParser' ::
+             Thrift.Protocol p =>
+             Proxy.Proxy p -> Text.Text -> Parser.Parser (Thrift.Some YCommand)
+reqParser' _proxy funName
+  = do Thrift.Some x <- X.reqParser' _proxy funName
+       Prelude.return (Thrift.Some (SuperX x))
+
+respWriter' ::
+              Thrift.Protocol p =>
+              Proxy.Proxy p ->
+                Int.Int32 ->
+                  YCommand a ->
+                    Prelude.Either Exception.SomeException a ->
+                      (Builder.Builder,
+                       Prelude.Maybe (Exception.SomeException, Thrift.Blame))
+respWriter' _proxy _seqNum (SuperX _x) _r
+  = X.respWriter' _proxy _seqNum _x _r
+
+methodsInfo' :: Map.Map Text.Text Thrift.MethodInfo
+methodsInfo' = Map.union (Map.fromList []) X.methodsInfo'
diff --git a/test/fixtures/gen-hs2/Thrift/Types.hs b/test/fixtures/gen-hs2/Thrift/Types.hs
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-hs2/Thrift/Types.hs
@@ -0,0 +1,829 @@
+-----------------------------------------------------------------
+-- Autogenerated by Thrift
+--
+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+--  @generated
+-----------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports#-}
+{-# OPTIONS_GHC -fno-warn-overlapping-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns#-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns#-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Thrift.Types
+       (Experimental(Experimental),
+        ReserveIds(ReserveIds, reserveIds_ids, reserveIds_id_ranges),
+        RequiresBackwardCompatibility(RequiresBackwardCompatibility,
+                                      requiresBackwardCompatibility_field_name),
+        TerseWrite(TerseWrite), Box(Box), Mixin(Mixin),
+        SerializeInFieldIdOrder(SerializeInFieldIdOrder),
+        BitmaskEnum(BitmaskEnum), ExceptionMessage(ExceptionMessage),
+        GenerateRuntimeSchema(GenerateRuntimeSchema,
+                              generateRuntimeSchema_name),
+        InternBox(InternBox), Serial(Serial), Uri(Uri, uri_value),
+        Priority(Priority, priority_level),
+        RpcPriority(RpcPriority_HIGH_IMPORTANT, RpcPriority_HIGH,
+                    RpcPriority_IMPORTANT, RpcPriority_NORMAL, RpcPriority_BEST_EFFORT,
+                    RpcPriority__UNKNOWN),
+        DeprecatedUnvalidatedAnnotations(DeprecatedUnvalidatedAnnotations,
+                                         deprecatedUnvalidatedAnnotations_items))
+       where
+import qualified Control.DeepSeq as DeepSeq
+import qualified Control.Exception as Exception
+import qualified Control.Monad as Monad
+import qualified Control.Monad.ST.Trans as ST
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.Default as Default
+import qualified Data.Function as Function
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Hashable as Hashable
+import qualified Data.Int as Int
+import qualified Data.List as List
+import qualified Data.Map.Strict as Map
+import qualified Data.Ord as Ord
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified GHC.Magic as GHC
+import qualified Prelude as Prelude
+import qualified Scope.Types as Scope
+import qualified Thrift.Binary.Parser as Parser
+import qualified Thrift.CodegenTypesOnly as Thrift
+import Control.Applicative ((<|>), (*>), (<*))
+import Data.Aeson ((.:), (.:?), (.=), (.!=))
+import Data.Monoid ((<>))
+import Prelude ((.), (++), (>), (==))
+import Prelude ((.), (<$>), (<*>), (>>=), (==), (/=), (<), (++))
+
+data Experimental = Experimental{}
+                    deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Experimental where
+  toJSON Experimental = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Experimental where
+  buildStruct _proxy Experimental = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Experimental)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Experimental where
+  rnf Experimental = ()
+
+instance Default.Default Experimental where
+  def = Experimental
+
+instance Hashable.Hashable Experimental where
+  hashWithSalt __salt Experimental = __salt
+
+data ReserveIds = ReserveIds{reserveIds_ids :: [Int.Int32],
+                             reserveIds_id_ranges :: Map.Map Int.Int32 Int.Int32}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON ReserveIds where
+  toJSON (ReserveIds __field__ids __field__id_ranges)
+    = Aeson.object
+        ("ids" .= __field__ids :
+           "id_ranges" .= Map.mapKeys Thrift.keyToStr __field__id_ranges :
+             Prelude.mempty)
+
+instance Thrift.ThriftStruct ReserveIds where
+  buildStruct _proxy (ReserveIds __field__ids __field__id_ranges)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "ids" (Thrift.getListType _proxy) 1 0
+           (Thrift.genListPrim _proxy (Thrift.getI32Type _proxy)
+              (Thrift.genI32Prim _proxy)
+              __field__ids)
+           :
+           Thrift.genField _proxy "id_ranges" (Thrift.getMapType _proxy) 2 1
+             ((Thrift.genMapPrim _proxy (Thrift.getI32Type _proxy)
+                 (Thrift.getI32Type _proxy)
+                 Prelude.False
+                 (Thrift.genI32Prim _proxy)
+                 (Thrift.genI32Prim _proxy)
+                 . Map.toList)
+                __field__id_ranges)
+             : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__ids <- ST.newSTRef Default.def
+            __field__id_ranges <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getListType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Prelude.snd <$>
+                                                                                      Thrift.parseList
+                                                                                        _proxy
+                                                                                        (Thrift.parseI32
+                                                                                           _proxy))
+                                                                        ST.writeSTRef __field__ids
+                                                                          _val
+                                                                 2 | _type ==
+                                                                       Thrift.getMapType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Map.fromList <$>
+                                                                                      Thrift.parseMap
+                                                                                        _proxy
+                                                                                        (Thrift.parseI32
+                                                                                           _proxy)
+                                                                                        (Thrift.parseI32
+                                                                                           _proxy)
+                                                                                        Prelude.False)
+                                                                        ST.writeSTRef
+                                                                          __field__id_ranges
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__ids <- ST.readSTRef __field__ids
+                                             !__val__id_ranges <- ST.readSTRef __field__id_ranges
+                                             Prelude.pure (ReserveIds __val__ids __val__id_ranges)
+              _idMap = HashMap.fromList [("ids", 1), ("id_ranges", 2)]
+            _parse 0)
+
+instance DeepSeq.NFData ReserveIds where
+  rnf (ReserveIds __field__ids __field__id_ranges)
+    = DeepSeq.rnf __field__ids `Prelude.seq`
+        DeepSeq.rnf __field__id_ranges `Prelude.seq` ()
+
+instance Default.Default ReserveIds where
+  def = ReserveIds Default.def Default.def
+
+instance Hashable.Hashable ReserveIds where
+  hashWithSalt __salt (ReserveIds _ids _id_ranges)
+    = Hashable.hashWithSalt (Hashable.hashWithSalt __salt _ids)
+        ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList) _id_ranges)
+
+instance Thrift.HasField "ids" ReserveIds ([Int.Int32]) where
+  getField = reserveIds_ids
+
+instance Thrift.HasField "id_ranges" ReserveIds
+           (Map.Map Int.Int32 Int.Int32)
+         where
+  getField = reserveIds_id_ranges
+
+newtype RequiresBackwardCompatibility = RequiresBackwardCompatibility{requiresBackwardCompatibility_field_name
+                                                                      :: Prelude.Bool}
+                                        deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON RequiresBackwardCompatibility where
+  toJSON (RequiresBackwardCompatibility __field__field_name)
+    = Aeson.object
+        ("field_name" .= __field__field_name : Prelude.mempty)
+
+instance Thrift.ThriftStruct RequiresBackwardCompatibility where
+  buildStruct _proxy
+    (RequiresBackwardCompatibility __field__field_name)
+    = Thrift.genStruct _proxy
+        (Thrift.genFieldBool _proxy "field_name" 1 0 __field__field_name :
+           [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__field_name <- ST.newSTRef Prelude.False
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getBoolType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseBoolF
+                                                                                      _proxy
+                                                                                      _bool)
+                                                                        ST.writeSTRef
+                                                                          __field__field_name
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__field_name <- ST.readSTRef
+                                                                     __field__field_name
+                                             Prelude.pure
+                                               (RequiresBackwardCompatibility __val__field_name)
+              _idMap = HashMap.fromList [("field_name", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData RequiresBackwardCompatibility where
+  rnf (RequiresBackwardCompatibility __field__field_name)
+    = DeepSeq.rnf __field__field_name `Prelude.seq` ()
+
+instance Default.Default RequiresBackwardCompatibility where
+  def = RequiresBackwardCompatibility Prelude.False
+
+instance Hashable.Hashable RequiresBackwardCompatibility where
+  hashWithSalt __salt (RequiresBackwardCompatibility _field_name)
+    = Hashable.hashWithSalt __salt _field_name
+
+instance Thrift.HasField "field_name" RequiresBackwardCompatibility
+           (Prelude.Bool)
+         where
+  getField = requiresBackwardCompatibility_field_name
+
+data TerseWrite = TerseWrite{}
+                  deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON TerseWrite where
+  toJSON TerseWrite = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct TerseWrite where
+  buildStruct _proxy TerseWrite = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (TerseWrite)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData TerseWrite where
+  rnf TerseWrite = ()
+
+instance Default.Default TerseWrite where
+  def = TerseWrite
+
+instance Hashable.Hashable TerseWrite where
+  hashWithSalt __salt TerseWrite = __salt
+
+data Box = Box{}
+           deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Box where
+  toJSON Box = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Box where
+  buildStruct _proxy Box = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Box)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Box where
+  rnf Box = ()
+
+instance Default.Default Box where
+  def = Box
+
+instance Hashable.Hashable Box where
+  hashWithSalt __salt Box = __salt
+
+data Mixin = Mixin{}
+             deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Mixin where
+  toJSON Mixin = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Mixin where
+  buildStruct _proxy Mixin = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Mixin)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Mixin where
+  rnf Mixin = ()
+
+instance Default.Default Mixin where
+  def = Mixin
+
+instance Hashable.Hashable Mixin where
+  hashWithSalt __salt Mixin = __salt
+
+data SerializeInFieldIdOrder = SerializeInFieldIdOrder{}
+                               deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON SerializeInFieldIdOrder where
+  toJSON SerializeInFieldIdOrder = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct SerializeInFieldIdOrder where
+  buildStruct _proxy SerializeInFieldIdOrder
+    = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (SerializeInFieldIdOrder)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData SerializeInFieldIdOrder where
+  rnf SerializeInFieldIdOrder = ()
+
+instance Default.Default SerializeInFieldIdOrder where
+  def = SerializeInFieldIdOrder
+
+instance Hashable.Hashable SerializeInFieldIdOrder where
+  hashWithSalt __salt SerializeInFieldIdOrder = __salt
+
+data BitmaskEnum = BitmaskEnum{}
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON BitmaskEnum where
+  toJSON BitmaskEnum = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct BitmaskEnum where
+  buildStruct _proxy BitmaskEnum = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (BitmaskEnum)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData BitmaskEnum where
+  rnf BitmaskEnum = ()
+
+instance Default.Default BitmaskEnum where
+  def = BitmaskEnum
+
+instance Hashable.Hashable BitmaskEnum where
+  hashWithSalt __salt BitmaskEnum = __salt
+
+data ExceptionMessage = ExceptionMessage{}
+                        deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON ExceptionMessage where
+  toJSON ExceptionMessage = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct ExceptionMessage where
+  buildStruct _proxy ExceptionMessage = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (ExceptionMessage)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData ExceptionMessage where
+  rnf ExceptionMessage = ()
+
+instance Default.Default ExceptionMessage where
+  def = ExceptionMessage
+
+instance Hashable.Hashable ExceptionMessage where
+  hashWithSalt __salt ExceptionMessage = __salt
+
+newtype GenerateRuntimeSchema = GenerateRuntimeSchema{generateRuntimeSchema_name
+                                                      :: Text.Text}
+                                deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON GenerateRuntimeSchema where
+  toJSON (GenerateRuntimeSchema __field__name)
+    = Aeson.object ("name" .= __field__name : Prelude.mempty)
+
+instance Thrift.ThriftStruct GenerateRuntimeSchema where
+  buildStruct _proxy (GenerateRuntimeSchema __field__name)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "name" (Thrift.getStringType _proxy) 1 0
+           (Thrift.genText _proxy __field__name)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__name <- ST.newSTRef ""
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__name
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__name <- ST.readSTRef __field__name
+                                             Prelude.pure (GenerateRuntimeSchema __val__name)
+              _idMap = HashMap.fromList [("name", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData GenerateRuntimeSchema where
+  rnf (GenerateRuntimeSchema __field__name)
+    = DeepSeq.rnf __field__name `Prelude.seq` ()
+
+instance Default.Default GenerateRuntimeSchema where
+  def = GenerateRuntimeSchema ""
+
+instance Hashable.Hashable GenerateRuntimeSchema where
+  hashWithSalt __salt (GenerateRuntimeSchema _name)
+    = Hashable.hashWithSalt __salt _name
+
+instance Thrift.HasField "name" GenerateRuntimeSchema (Text.Text)
+         where
+  getField = generateRuntimeSchema_name
+
+data InternBox = InternBox{}
+                 deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON InternBox where
+  toJSON InternBox = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct InternBox where
+  buildStruct _proxy InternBox = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (InternBox)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData InternBox where
+  rnf InternBox = ()
+
+instance Default.Default InternBox where
+  def = InternBox
+
+instance Hashable.Hashable InternBox where
+  hashWithSalt __salt InternBox = __salt
+
+data Serial = Serial{}
+              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Serial where
+  toJSON Serial = Aeson.object Prelude.mempty
+
+instance Thrift.ThriftStruct Serial where
+  buildStruct _proxy Serial = Thrift.genStruct _proxy []
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do Prelude.pure (Serial)
+              _idMap = HashMap.fromList []
+            _parse 0)
+
+instance DeepSeq.NFData Serial where
+  rnf Serial = ()
+
+instance Default.Default Serial where
+  def = Serial
+
+instance Hashable.Hashable Serial where
+  hashWithSalt __salt Serial = __salt
+
+newtype Uri = Uri{uri_value :: Text.Text}
+              deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Uri where
+  toJSON (Uri __field__value)
+    = Aeson.object ("value" .= __field__value : Prelude.mempty)
+
+instance Thrift.ThriftStruct Uri where
+  buildStruct _proxy (Uri __field__value)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "value" (Thrift.getStringType _proxy) 1 0
+           (Thrift.genText _proxy __field__value)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__value <- ST.newSTRef ""
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getStringType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseText
+                                                                                      _proxy)
+                                                                        ST.writeSTRef __field__value
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__value <- ST.readSTRef __field__value
+                                             Prelude.pure (Uri __val__value)
+              _idMap = HashMap.fromList [("value", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData Uri where
+  rnf (Uri __field__value)
+    = DeepSeq.rnf __field__value `Prelude.seq` ()
+
+instance Default.Default Uri where
+  def = Uri ""
+
+instance Hashable.Hashable Uri where
+  hashWithSalt __salt (Uri _value)
+    = Hashable.hashWithSalt __salt _value
+
+instance Thrift.HasField "value" Uri (Text.Text) where
+  getField = uri_value
+
+newtype Priority = Priority{priority_level :: RpcPriority}
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON Priority where
+  toJSON (Priority __field__level)
+    = Aeson.object ("level" .= __field__level : Prelude.mempty)
+
+instance Thrift.ThriftStruct Priority where
+  buildStruct _proxy (Priority __field__level)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "level" (Thrift.getI32Type _proxy) 1 0
+           ((Thrift.genI32 _proxy . Prelude.fromIntegral .
+               Thrift.fromThriftEnum)
+              __field__level)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__level <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getI32Type _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Thrift.parseEnum
+                                                                                      _proxy
+                                                                                      "RpcPriority")
+                                                                        ST.writeSTRef __field__level
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__level <- ST.readSTRef __field__level
+                                             Prelude.pure (Priority __val__level)
+              _idMap = HashMap.fromList [("level", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData Priority where
+  rnf (Priority __field__level)
+    = DeepSeq.rnf __field__level `Prelude.seq` ()
+
+instance Default.Default Priority where
+  def = Priority Default.def
+
+instance Hashable.Hashable Priority where
+  hashWithSalt __salt (Priority _level)
+    = Hashable.hashWithSalt __salt _level
+
+instance Thrift.HasField "level" Priority (RpcPriority) where
+  getField = priority_level
+
+data RpcPriority = RpcPriority_HIGH_IMPORTANT
+                 | RpcPriority_HIGH
+                 | RpcPriority_IMPORTANT
+                 | RpcPriority_NORMAL
+                 | RpcPriority_BEST_EFFORT
+                 | RpcPriority__UNKNOWN Prelude.Int
+                   deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON RpcPriority where
+  toJSON = Aeson.toJSON . Thrift.fromThriftEnum
+
+instance DeepSeq.NFData RpcPriority where
+  rnf __RpcPriority = Prelude.seq __RpcPriority ()
+
+instance Default.Default RpcPriority where
+  def = RpcPriority_HIGH_IMPORTANT
+
+instance Hashable.Hashable RpcPriority where
+  hashWithSalt _salt _val
+    = Hashable.hashWithSalt _salt (Thrift.fromThriftEnum _val)
+
+instance Thrift.ThriftEnum RpcPriority where
+  toThriftEnum 0 = RpcPriority_HIGH_IMPORTANT
+  toThriftEnum 1 = RpcPriority_HIGH
+  toThriftEnum 2 = RpcPriority_IMPORTANT
+  toThriftEnum 3 = RpcPriority_NORMAL
+  toThriftEnum 4 = RpcPriority_BEST_EFFORT
+  toThriftEnum val = RpcPriority__UNKNOWN val
+  fromThriftEnum RpcPriority_HIGH_IMPORTANT = 0
+  fromThriftEnum RpcPriority_HIGH = 1
+  fromThriftEnum RpcPriority_IMPORTANT = 2
+  fromThriftEnum RpcPriority_NORMAL = 3
+  fromThriftEnum RpcPriority_BEST_EFFORT = 4
+  fromThriftEnum (RpcPriority__UNKNOWN val) = val
+  allThriftEnumValues
+    = [RpcPriority_HIGH_IMPORTANT, RpcPriority_HIGH,
+       RpcPriority_IMPORTANT, RpcPriority_NORMAL, RpcPriority_BEST_EFFORT]
+  toThriftEnumEither 0 = Prelude.Right RpcPriority_HIGH_IMPORTANT
+  toThriftEnumEither 1 = Prelude.Right RpcPriority_HIGH
+  toThriftEnumEither 2 = Prelude.Right RpcPriority_IMPORTANT
+  toThriftEnumEither 3 = Prelude.Right RpcPriority_NORMAL
+  toThriftEnumEither 4 = Prelude.Right RpcPriority_BEST_EFFORT
+  toThriftEnumEither val
+    = Prelude.Left
+        ("toThriftEnumEither: not a valid identifier for enum RpcPriority: "
+           ++ Prelude.show val)
+
+newtype DeprecatedUnvalidatedAnnotations = DeprecatedUnvalidatedAnnotations{deprecatedUnvalidatedAnnotations_items
+                                                                            ::
+                                                                            Map.Map Text.Text
+                                                                              Text.Text}
+                                           deriving (Prelude.Eq, Prelude.Show, Prelude.Ord)
+
+instance Aeson.ToJSON DeprecatedUnvalidatedAnnotations where
+  toJSON (DeprecatedUnvalidatedAnnotations __field__items)
+    = Aeson.object ("items" .= __field__items : Prelude.mempty)
+
+instance Thrift.ThriftStruct DeprecatedUnvalidatedAnnotations where
+  buildStruct _proxy
+    (DeprecatedUnvalidatedAnnotations __field__items)
+    = Thrift.genStruct _proxy
+        (Thrift.genField _proxy "items" (Thrift.getMapType _proxy) 1 0
+           ((Thrift.genMap _proxy (Thrift.getStringType _proxy)
+               (Thrift.getStringType _proxy)
+               Prelude.True
+               (Thrift.genText _proxy)
+               (Thrift.genText _proxy)
+               . Map.toList)
+              __field__items)
+           : [])
+  parseStruct _proxy
+    = ST.runSTT
+        (do Prelude.return ()
+            __field__items <- ST.newSTRef Default.def
+            let
+              _parse _lastId
+                = do _fieldBegin <- Trans.lift
+                                      (Thrift.parseFieldBegin _proxy _lastId _idMap)
+                     case _fieldBegin of
+                       Thrift.FieldBegin _type _id _bool -> do case _id of
+                                                                 1 | _type ==
+                                                                       Thrift.getMapType _proxy
+                                                                     ->
+                                                                     do !_val <- Trans.lift
+                                                                                   (Map.fromList <$>
+                                                                                      Thrift.parseMap
+                                                                                        _proxy
+                                                                                        (Thrift.parseText
+                                                                                           _proxy)
+                                                                                        (Thrift.parseText
+                                                                                           _proxy)
+                                                                                        Prelude.True)
+                                                                        ST.writeSTRef __field__items
+                                                                          _val
+                                                                 _ -> Trans.lift
+                                                                        (Thrift.parseSkip _proxy
+                                                                           _type
+                                                                           (Prelude.Just _bool))
+                                                               _parse _id
+                       Thrift.FieldEnd -> do !__val__items <- ST.readSTRef __field__items
+                                             Prelude.pure
+                                               (DeprecatedUnvalidatedAnnotations __val__items)
+              _idMap = HashMap.fromList [("items", 1)]
+            _parse 0)
+
+instance DeepSeq.NFData DeprecatedUnvalidatedAnnotations where
+  rnf (DeprecatedUnvalidatedAnnotations __field__items)
+    = DeepSeq.rnf __field__items `Prelude.seq` ()
+
+instance Default.Default DeprecatedUnvalidatedAnnotations where
+  def = DeprecatedUnvalidatedAnnotations Default.def
+
+instance Hashable.Hashable DeprecatedUnvalidatedAnnotations where
+  hashWithSalt __salt (DeprecatedUnvalidatedAnnotations _items)
+    = Hashable.hashWithSalt __salt
+        ((Prelude.map (\ (_k, _v) -> (_k, _v)) . Map.toAscList) _items)
+
+instance Thrift.HasField "items" DeprecatedUnvalidatedAnnotations
+           (Map.Map Text.Text Text.Text)
+         where
+  getField = deprecatedUnvalidatedAnnotations_items
diff --git a/test/fixtures/gen-single-out-loc/a.ast b/test/fixtures/gen-single-out-loc/a.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-single-out-loc/a.ast
@@ -0,0 +1,1847 @@
+[
+    {
+        "consts": [
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 7, locEndLine = 9, locEndCol = 8}"
+                    ],
+                    "type": {
+                        "name": "T"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 1, locEndLine = 9, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 9, locEndLine = 9, locEndCol = 10}",
+                "name": "a",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+                    "name": {
+                        "name": "T"
+                    },
+                    "type": "typedef"
+                },
+                "value": {
+                    "named_constant": {
+                        "name": "i64_value",
+                        "src": "b"
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 7, locEndLine = 9, locEndCol = 8}",
+                        "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 9, locStartCol = 13, locEndLine = 9, locEndCol = 24}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 11, locEndLine = 51, locEndCol = 20}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 7, locEndLine = 31, locEndCol = 8}"
+                    ],
+                    "type": {
+                        "name": "U"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 1, locEndLine = 31, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 9, locEndLine = 31, locEndCol = 10}",
+                "name": "u",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}",
+                    "name": {
+                        "name": "U"
+                    },
+                    "type": "union"
+                },
+                "value": {
+                    "literal": {
+                        "type": "union",
+                        "value": {
+                            "field_name": "y",
+                            "field_type": {
+                                "inner_type": {
+                                    "type": "string"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": [
+                                        {
+                                            "named_constant": {
+                                                "name": "string_value",
+                                                "src": "b"
+                                            }
+                                        }
+                                    ]
+                                }
+                            }
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 31, locStartCol = 7, locEndLine = 31, locEndCol = 8}",
+                        "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 7, locEndLine = 33, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "name": "b.B"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 1, locEndLine = 33, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 11, locEndLine = 33, locEndCol = 12}",
+                "name": "b",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                    "name": {
+                        "name": "B",
+                        "src": "b"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i16_value",
+                                        "src": "b"
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i32_value",
+                                        "src": "b"
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i64_value",
+                                        "src": "b"
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 33, locStartCol = 7, locEndLine = 33, locEndCol = 10}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 7, locEndLine = 35, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "name": "b.B"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 1, locEndLine = 35, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 11, locEndLine = 35, locEndCol = 20}",
+                "name": "default_d",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                    "name": {
+                        "name": "B",
+                        "src": "b"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 35, locStartCol = 7, locEndLine = 35, locEndCol = 10}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 7, locEndLine = 37, locEndCol = 15}"
+                    ],
+                    "type": {
+                        "name": "b.Number"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 1, locEndLine = 37, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 16, locEndLine = 37, locEndCol = 20}",
+                "name": "zero",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                    "name": {
+                        "name": "Number",
+                        "src": "b"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero",
+                            "src": "b"
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 7, locEndLine = 37, locEndCol = 15}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 37, locStartCol = 23, locEndLine = 37, locEndCol = 29}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}"
+                    }
+                ]
+            }
+        ],
+        "enums": [],
+        "includes": [
+            "test/if/b.thrift"
+        ],
+        "name": "a",
+        "options": {
+            "genfiles": null,
+            "include_path": ".",
+            "out_path": "test/fixtures/gen-single-out-loc",
+            "path": "test/if/a.thrift",
+            "recursive": true
+        },
+        "path": "test/if/a.thrift",
+        "services": [
+            {
+                "functions": [
+                    {
+                        "args": [
+                            {
+                                "id": 1,
+                                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 40, locStartCol = 29, locEndLine = 40, locEndCol = 30}",
+                                "name": "x",
+                                "type": {
+                                    "type": "i32"
+                                },
+                                "xref": []
+                            }
+                        ],
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 40, locStartCol = 12, locEndLine = 40, locEndCol = 21}",
+                        "name": "getNumber",
+                        "oneway": false,
+                        "return_type": {
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                            "name": {
+                                "name": "Number",
+                                "src": "b"
+                            },
+                            "type": "enum"
+                        },
+                        "throws": []
+                    },
+                    {
+                        "args": [],
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 8, locEndLine = 42, locEndCol = 17}",
+                        "name": "doNothing",
+                        "oneway": false,
+                        "return_type": {
+                            "type": "void"
+                        },
+                        "throws": [
+                            {
+                                "id": 1,
+                                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 33, locEndLine = 42, locEndCol = 35}",
+                                "name": "ex",
+                                "type": {
+                                    "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}",
+                                    "name": {
+                                        "name": "X"
+                                    },
+                                    "type": "exception"
+                                },
+                                "xref": [
+                                    {
+                                        "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 42, locStartCol = 31, locEndLine = 42, locEndCol = 32}",
+                                        "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}"
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 39, locStartCol = 1, locEndLine = 39, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 39, locStartCol = 9, locEndLine = 39, locEndCol = 10}",
+                "name": "S"
+            },
+            {
+                "functions": [],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 45, locStartCol = 1, locEndLine = 45, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 45, locStartCol = 9, locEndLine = 45, locEndCol = 22}",
+                "name": "ParentService"
+            },
+            {
+                "functions": [
+                    {
+                        "args": [],
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 49, locStartCol = 7, locEndLine = 49, locEndCol = 10}",
+                        "name": "foo",
+                        "oneway": false,
+                        "return_type": {
+                            "type": "i32"
+                        },
+                        "throws": []
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 48, locStartCol = 1, locEndLine = 48, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 48, locStartCol = 9, locEndLine = 48, locEndCol = 21}",
+                "name": "ChildService",
+                "super": {
+                    "name": "ParentService"
+                }
+            }
+        ],
+        "structs": [
+            {
+                "fields": [
+                    {
+                        "default_value": {
+                            "named_constant": {
+                                "name": "a"
+                            }
+                        },
+                        "id": 1,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 12, locStartCol = 8, locEndLine = 12, locEndCol = 9}",
+                        "name": "a",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "type": "i64"
+                            },
+                            "loc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+                            "name": {
+                                "name": "T"
+                            },
+                            "type": "typedef"
+                        },
+                        "xref": [
+                            {
+                                "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 12, locStartCol = 6, locEndLine = 12, locEndCol = 7}",
+                                "rLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}"
+                            }
+                        ]
+                    },
+                    {
+                        "default_value": {
+                            "named_constant": {
+                                "name": "bool_value",
+                                "src": "b"
+                            }
+                        },
+                        "id": 3,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 13, locStartCol = 11, locEndLine = 13, locEndCol = 12}",
+                        "name": "c",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "bool"
+                        },
+                        "xref": []
+                    },
+                    {
+                        "id": 4,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 14, locStartCol = 22, locEndLine = 14, locEndCol = 23}",
+                        "name": "d",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "inner_type": {
+                                    "type": "i32"
+                                },
+                                "type": "list"
+                            },
+                            "type": "list"
+                        },
+                        "xref": []
+                    },
+                    {
+                        "id": 5,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 15, locStartCol = 23, locEndLine = 15, locEndCol = 24}",
+                        "name": "e",
+                        "requiredness": "default",
+                        "type": {
+                            "key_type": {
+                                "type": "i32"
+                            },
+                            "type": "map",
+                            "val_type": {
+                                "type": "string"
+                            }
+                        },
+                        "xref": []
+                    },
+                    {
+                        "default_value": {
+                            "literal": {
+                                "type": "enum",
+                                "value": {
+                                    "name": "Two",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        "id": 6,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 16, locStartCol = 15, locEndLine = 16, locEndCol = 16}",
+                        "name": "f",
+                        "requiredness": "default",
+                        "type": {
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                            "name": {
+                                "name": "Number",
+                                "src": "b"
+                            },
+                            "type": "enum"
+                        },
+                        "xref": [
+                            {
+                                "aLoc": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 16, locStartCol = 6, locEndLine = 16, locEndCol = 14}",
+                                "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                            }
+                        ]
+                    },
+                    {
+                        "id": 7,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 17, locStartCol = 22, locEndLine = 17, locEndCol = 23}",
+                        "name": "g",
+                        "requiredness": "optional",
+                        "type": {
+                            "type": "string"
+                        },
+                        "xref": []
+                    },
+                    {
+                        "id": 8,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 18, locStartCol = 22, locEndLine = 18, locEndCol = 23}",
+                        "name": "h",
+                        "requiredness": "required",
+                        "type": {
+                            "type": "string"
+                        },
+                        "xref": []
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 11, locStartCol = 1, locEndLine = 11, locEndCol = 7}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 11, locStartCol = 8, locEndLine = 11, locEndCol = 9}",
+                "name": "A",
+                "struct_type": "STRUCT"
+            },
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 28, locStartCol = 13, locEndLine = 28, locEndCol = 19}",
+                        "name": "reason",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "string"
+                        },
+                        "xref": []
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 1, locEndLine = 27, locEndCol = 10}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 27, locStartCol = 11, locEndLine = 27, locEndCol = 12}",
+                "name": "X",
+                "struct_type": "EXCEPTION"
+            }
+        ],
+        "typedefs": [
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 9, locEndLine = 7, locEndCol = 12}"
+                    ],
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                "anns": null,
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 1, locEndLine = 7, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 7, locStartCol = 13, locEndLine = 7, locEndCol = 14}",
+                "name": "T",
+                "newtype": false,
+                "type": {
+                    "type": "i64"
+                },
+                "xref": []
+            }
+        ],
+        "unions": [
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 22, locStartCol = 11, locEndLine = 22, locEndCol = 12}",
+                        "name": "x",
+                        "type": {
+                            "type": "byte"
+                        }
+                    },
+                    {
+                        "id": 2,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 23, locStartCol = 19, locEndLine = 23, locEndCol = 20}",
+                        "name": "y",
+                        "type": {
+                            "inner_type": {
+                                "type": "string"
+                            },
+                            "type": "list"
+                        }
+                    },
+                    {
+                        "id": 3,
+                        "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 24, locStartCol = 15, locEndLine = 24, locEndCol = 16}",
+                        "name": "z",
+                        "type": {
+                            "inner_type": {
+                                "type": "i64"
+                            },
+                            "type": "set"
+                        }
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 1, locEndLine = 21, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/a.thrift\", locStartLine = 21, locStartCol = 7, locEndLine = 21, locEndCol = 8}",
+                "name": "U"
+            }
+        ]
+    },
+    {
+        "consts": [
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 7, locEndLine = 48, locEndCol = 11}"
+                    ],
+                    "type": {
+                        "type": "byte"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 1, locEndLine = 48, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 48, locStartCol = 12, locEndLine = 48, locEndCol = 22}",
+                "name": "byte_value",
+                "type": {
+                    "type": "byte"
+                },
+                "value": {
+                    "literal": {
+                        "type": "byte",
+                        "value": 0
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 7, locEndLine = 49, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "type": "i16"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 1, locEndLine = 49, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 49, locStartCol = 11, locEndLine = 49, locEndCol = 20}",
+                "name": "i16_value",
+                "type": {
+                    "type": "i16"
+                },
+                "value": {
+                    "literal": {
+                        "type": "i16",
+                        "value": 1
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 7, locEndLine = 50, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "type": "i32"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 1, locEndLine = 50, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 50, locStartCol = 11, locEndLine = 50, locEndCol = 20}",
+                "name": "i32_value",
+                "type": {
+                    "type": "i32"
+                },
+                "value": {
+                    "literal": {
+                        "type": "i32",
+                        "value": 2
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 7, locEndLine = 51, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 1, locEndLine = 51, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 51, locStartCol = 11, locEndLine = 51, locEndCol = 20}",
+                "name": "i64_value",
+                "type": {
+                    "type": "i64"
+                },
+                "value": {
+                    "literal": {
+                        "string": "3",
+                        "type": "i64",
+                        "value": 3
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 7, locEndLine = 52, locEndCol = 12}"
+                    ],
+                    "type": {
+                        "type": "float"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 1, locEndLine = 52, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 52, locStartCol = 13, locEndLine = 52, locEndCol = 24}",
+                "name": "float_value",
+                "type": {
+                    "type": "float"
+                },
+                "value": {
+                    "literal": {
+                        "binary": "3f000000",
+                        "type": "float",
+                        "value": 0.5
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 7, locEndLine = 53, locEndCol = 13}"
+                    ],
+                    "type": {
+                        "type": "double"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 1, locEndLine = 53, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 53, locStartCol = 14, locEndLine = 53, locEndCol = 26}",
+                "name": "double_value",
+                "type": {
+                    "type": "double"
+                },
+                "value": {
+                    "literal": {
+                        "binary": "400921f9f01b866e",
+                        "type": "double",
+                        "value": 3.14159
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 7, locEndLine = 54, locEndCol = 11}"
+                    ],
+                    "type": {
+                        "type": "bool"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 1, locEndLine = 54, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 54, locStartCol = 12, locEndLine = 54, locEndCol = 22}",
+                "name": "bool_value",
+                "type": {
+                    "type": "bool"
+                },
+                "value": {
+                    "literal": {
+                        "type": "bool",
+                        "value": true
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 7, locEndLine = 55, locEndCol = 13}"
+                    ],
+                    "type": {
+                        "type": "string"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 1, locEndLine = 55, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 55, locStartCol = 14, locEndLine = 55, locEndCol = 26}",
+                "name": "string_value",
+                "type": {
+                    "type": "string"
+                },
+                "value": {
+                    "literal": {
+                        "type": "string",
+                        "value": "xxx"
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 7, locEndLine = 56, locEndCol = 13}"
+                    ],
+                    "type": {
+                        "type": "binary"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 1, locEndLine = 56, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 56, locStartCol = 14, locEndLine = 56, locEndCol = 26}",
+                "name": "binary_value",
+                "type": {
+                    "type": "binary"
+                },
+                "value": {
+                    "literal": {
+                        "type": "binary",
+                        "value": "797979"
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 7, locEndLine = 57, locEndCol = 10}"
+                    ],
+                    "type": {
+                        "name": "Int"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 1, locEndLine = 57, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 11, locEndLine = 57, locEndCol = 24}",
+                "name": "newtype_value",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}",
+                    "name": {
+                        "name": "Int"
+                    },
+                    "type": "newtype"
+                },
+                "value": {
+                    "literal": {
+                        "type": "newtype",
+                        "value": {
+                            "string": "10",
+                            "type": "i64",
+                            "value": 10
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 57, locStartCol = 7, locEndLine = 57, locEndCol = 10}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 7, locEndLine = 58, locEndCol = 13}"
+                    ],
+                    "type": {
+                        "name": "Number"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 1, locEndLine = 58, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 14, locEndLine = 58, locEndCol = 31}",
+                "name": "scoped_enum_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                    "name": {
+                        "name": "Number"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero"
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 7, locEndLine = 58, locEndCol = 13}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 58, locStartCol = 34, locEndLine = 58, locEndCol = 45}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 7, locEndLine = 59, locEndCol = 13}"
+                    ],
+                    "type": {
+                        "name": "Number"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 1, locEndLine = 59, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 14, locEndLine = 59, locEndCol = 24}",
+                "name": "enum_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                    "name": {
+                        "name": "Number"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "One"
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 7, locEndLine = 59, locEndCol = 13}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 59, locStartCol = 27, locEndLine = 59, locEndCol = 30}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 23, locStartCol = 3, locEndLine = 23, locEndCol = 6}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 7, locEndLine = 60, locEndCol = 20}"
+                    ],
+                    "type": {
+                        "name": "Number_Pseudo"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 1, locEndLine = 60, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 21, locEndLine = 60, locEndCol = 44}",
+                "name": "scoped_pseudoenum_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+                    "name": {
+                        "name": "Number_Pseudo"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero"
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 7, locEndLine = 60, locEndCol = 20}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 60, locStartCol = 47, locEndLine = 60, locEndCol = 65}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 33, locStartCol = 3, locEndLine = 33, locEndCol = 7}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 7, locEndLine = 61, locEndCol = 20}"
+                    ],
+                    "type": {
+                        "name": "Number_Pseudo"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 1, locEndLine = 61, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 21, locEndLine = 61, locEndCol = 37}",
+                "name": "pseudoenum_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+                    "name": {
+                        "name": "Number_Pseudo"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Four"
+                        }
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 7, locEndLine = 61, locEndCol = 20}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}"
+                    },
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 61, locStartCol = 40, locEndLine = 61, locEndCol = 44}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 34, locStartCol = 3, locEndLine = 34, locEndCol = 7}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 7, locEndLine = 64, locEndCol = 11}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 11, locEndLine = 64, locEndCol = 12}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 15, locEndLine = 64, locEndCol = 16}"
+                    ],
+                    "type": {
+                        "inner_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 12, locEndLine = 64, locEndCol = 15}"
+                            ],
+                            "type": {
+                                "type": "i64"
+                            }
+                        },
+                        "type": "list"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 1, locEndLine = 64, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 64, locStartCol = 17, locEndLine = 64, locEndCol = 27}",
+                "name": "list_value",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "type": "list"
+                },
+                "value": {
+                    "literal": {
+                        "type": "list",
+                        "value": [
+                            {
+                                "literal": {
+                                    "string": "0",
+                                    "type": "i64",
+                                    "value": 0
+                                }
+                            },
+                            {
+                                "named_constant": {
+                                    "name": "i64_value"
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 7, locEndLine = 65, locEndCol = 10}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 10, locEndLine = 65, locEndCol = 11}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 17, locEndLine = 65, locEndCol = 18}"
+                    ],
+                    "type": {
+                        "inner_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 11, locEndLine = 65, locEndCol = 17}"
+                            ],
+                            "type": {
+                                "type": "string"
+                            }
+                        },
+                        "type": "set"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 1, locEndLine = 65, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 65, locStartCol = 19, locEndLine = 65, locEndCol = 28}",
+                "name": "set_value",
+                "type": {
+                    "inner_type": {
+                        "type": "string"
+                    },
+                    "type": "set"
+                },
+                "value": {
+                    "literal": {
+                        "type": "set",
+                        "value": [
+                            {
+                                "named_constant": {
+                                    "name": "string_value"
+                                }
+                            },
+                            {
+                                "literal": {
+                                    "type": "string",
+                                    "value": ""
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 7, locEndLine = 68, locEndCol = 10}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 10, locEndLine = 68, locEndCol = 11}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 14, locEndLine = 68, locEndCol = 15}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 20, locEndLine = 68, locEndCol = 21}"
+                    ],
+                    "type": {
+                        "key_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 11, locEndLine = 68, locEndCol = 14}"
+                            ],
+                            "type": {
+                                "type": "i64"
+                            }
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 16, locEndLine = 68, locEndCol = 20}"
+                            ],
+                            "type": {
+                                "type": "bool"
+                            }
+                        }
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 1, locEndLine = 68, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 68, locStartCol = 22, locEndLine = 68, locEndCol = 31}",
+                "name": "map_value",
+                "type": {
+                    "key_type": {
+                        "type": "i64"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "bool"
+                    }
+                },
+                "value": {
+                    "literal": {
+                        "type": "map",
+                        "value": [
+                            {
+                                "key": {
+                                    "literal": {
+                                        "string": "0",
+                                        "type": "i64",
+                                        "value": 0
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "bool",
+                                        "value": true
+                                    }
+                                }
+                            },
+                            {
+                                "key": {
+                                    "literal": {
+                                        "string": "1",
+                                        "type": "i64",
+                                        "value": 1
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "bool",
+                                        "value": false
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 7, locEndLine = 69, locEndCol = 29}"
+                    ],
+                    "type": {
+                        "name": "map_string_string_6258"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 1, locEndLine = 69, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 30, locEndLine = 69, locEndCol = 44}",
+                "name": "hash_map_value",
+                "type": {
+                    "inner_type": {
+                        "key_type": {
+                            "type": "string"
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "type": "string"
+                        }
+                    },
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}",
+                    "name": {
+                        "name": "map_string_string_6258"
+                    },
+                    "type": "typedef"
+                },
+                "value": {
+                    "literal": {
+                        "type": "map",
+                        "value": [
+                            {
+                                "key": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "a"
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "A"
+                                    }
+                                }
+                            },
+                            {
+                                "key": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "b"
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "B"
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 69, locStartCol = 7, locEndLine = 69, locEndCol = 29}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 7, locEndLine = 71, locEndCol = 8}"
+                    ],
+                    "type": {
+                        "name": "B"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 1, locEndLine = 71, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 9, locEndLine = 71, locEndCol = 21}",
+                "name": "struct_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                    "name": {
+                        "name": "B"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i16",
+                                        "value": 1
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i32",
+                                        "value": 2
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "string": "3",
+                                        "type": "i64",
+                                        "value": 3
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 71, locStartCol = 7, locEndLine = 71, locEndCol = 8}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 7, locEndLine = 72, locEndCol = 8}"
+                    ],
+                    "type": {
+                        "name": "B"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 1, locEndLine = 72, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 9, locEndLine = 72, locEndCol = 30}",
+                "name": "explicit_struct_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                    "name": {
+                        "name": "B"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i16",
+                                        "value": 1
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i32",
+                                        "value": 2
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "string": "3",
+                                        "type": "i64",
+                                        "value": 3
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 72, locStartCol = 7, locEndLine = 72, locEndCol = 8}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                    }
+                ]
+            },
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 7, locEndLine = 73, locEndCol = 8}"
+                    ],
+                    "type": {
+                        "name": "C"
+                    }
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 1, locEndLine = 73, locEndCol = 6}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 9, locEndLine = 73, locEndCol = 37}",
+                "name": "explicit_nested_struct_value",
+                "type": {
+                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}",
+                    "name": {
+                        "name": "C"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "x",
+                                "field_type": {
+                                    "inner_type": {
+                                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                                        "name": {
+                                            "name": "Number"
+                                        },
+                                        "type": "enum"
+                                    },
+                                    "type": "list"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "list",
+                                        "value": []
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "y",
+                                "field_type": {
+                                    "inner_type": {
+                                        "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+                                        "name": {
+                                            "name": "Number_Strict"
+                                        },
+                                        "type": "enum"
+                                    },
+                                    "type": "list"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "list",
+                                        "value": []
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "z",
+                                "field_type": {
+                                    "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                                    "name": {
+                                        "name": "B"
+                                    },
+                                    "type": "struct"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "struct",
+                                        "value": [
+                                            {
+                                                "field_name": "a",
+                                                "field_type": {
+                                                    "type": "i16"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "type": "i16",
+                                                        "value": 1
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                "field_name": "b",
+                                                "field_type": {
+                                                    "type": "i32"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "type": "i32",
+                                                        "value": 2
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                "field_name": "c",
+                                                "field_type": {
+                                                    "type": "i64"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "string": "3",
+                                                        "type": "i64",
+                                                        "value": 3
+                                                    }
+                                                }
+                                            }
+                                        ]
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                },
+                "xref": [
+                    {
+                        "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 73, locStartCol = 7, locEndLine = 73, locEndCol = 8}",
+                        "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}"
+                    }
+                ]
+            }
+        ],
+        "enums": [
+            {
+                "constants": [
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 22, locStartCol = 3, locEndLine = 22, locEndCol = 7}",
+                        "name": "Zero",
+                        "value": 0
+                    },
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 23, locStartCol = 3, locEndLine = 23, locEndCol = 6}",
+                        "name": "One",
+                        "value": 1
+                    },
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 24, locStartCol = 3, locEndLine = 24, locEndCol = 6}",
+                        "name": "Two",
+                        "value": 2
+                    },
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 25, locStartCol = 3, locEndLine = 25, locEndCol = 8}",
+                        "name": "Three",
+                        "value": 3
+                    }
+                ],
+                "flavour": "sum_type",
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 1, locEndLine = 21, locEndCol = 5}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                "name": "Number"
+            },
+            {
+                "constants": [
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 29, locStartCol = 3, locEndLine = 29, locEndCol = 7}",
+                        "name": "Zero",
+                        "value": 0
+                    }
+                ],
+                "flavour": "sum_type",
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 1, locEndLine = 28, locEndCol = 5}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+                "name": "Number_Strict"
+            },
+            {
+                "constants": [
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 33, locStartCol = 3, locEndLine = 33, locEndCol = 7}",
+                        "name": "Zero",
+                        "value": 0
+                    },
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 34, locStartCol = 3, locEndLine = 34, locEndCol = 7}",
+                        "name": "Four",
+                        "value": 4
+                    }
+                ],
+                "flavour": "sum_type",
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 1, locEndLine = 32, locEndCol = 5}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 32, locStartCol = 6, locEndLine = 32, locEndCol = 19}",
+                "name": "Number_Pseudo"
+            },
+            {
+                "constants": [
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 38, locStartCol = 3, locEndLine = 38, locEndCol = 7}",
+                        "name": "Five",
+                        "value": 5
+                    },
+                    {
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 39, locStartCol = 3, locEndLine = 39, locEndCol = 7}",
+                        "name": "Zero",
+                        "value": 0
+                    }
+                ],
+                "flavour": "sum_type",
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 37, locStartCol = 1, locEndLine = 37, locEndCol = 5}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 37, locStartCol = 6, locEndLine = 37, locEndCol = 26}",
+                "name": "Number_Discontinuous"
+            },
+            {
+                "constants": [],
+                "flavour": "sum_type",
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 42, locStartCol = 1, locEndLine = 42, locEndCol = 5}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 42, locStartCol = 6, locEndLine = 42, locEndCol = 18}",
+                "name": "Number_Empty"
+            }
+        ],
+        "includes": [],
+        "name": "b",
+        "options": {
+            "genfiles": null,
+            "include_path": ".",
+            "out_path": "test/fixtures/gen-single-out-loc",
+            "path": "test/if/a.thrift",
+            "recursive": true
+        },
+        "path": "test/if/b.thrift",
+        "services": [],
+        "structs": [
+            {
+                "fields": [
+                    {
+                        "default_value": {
+                            "literal": {
+                                "type": "i16",
+                                "value": 1
+                            }
+                        },
+                        "id": 1,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 10, locStartCol = 10, locEndLine = 10, locEndCol = 11}",
+                        "name": "a",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i16"
+                        },
+                        "xref": []
+                    },
+                    {
+                        "id": 2,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 11, locStartCol = 10, locEndLine = 11, locEndCol = 11}",
+                        "name": "b",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i32"
+                        },
+                        "xref": []
+                    },
+                    {
+                        "id": 3,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 12, locStartCol = 10, locEndLine = 12, locEndCol = 11}",
+                        "name": "c",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i64"
+                        },
+                        "xref": []
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 1, locEndLine = 9, locEndCol = 7}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                "name": "B",
+                "struct_type": "STRUCT"
+            },
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 16, locStartCol = 19, locEndLine = 16, locEndCol = 20}",
+                        "name": "x",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}",
+                                "name": {
+                                    "name": "Number"
+                                },
+                                "type": "enum"
+                            },
+                            "type": "list"
+                        },
+                        "xref": [
+                            {
+                                "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 16, locStartCol = 11, locEndLine = 16, locEndCol = 17}",
+                                "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 21, locStartCol = 6, locEndLine = 21, locEndCol = 12}"
+                            }
+                        ]
+                    },
+                    {
+                        "id": 2,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 17, locStartCol = 26, locEndLine = 17, locEndCol = 27}",
+                        "name": "y",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}",
+                                "name": {
+                                    "name": "Number_Strict"
+                                },
+                                "type": "enum"
+                            },
+                            "type": "list"
+                        },
+                        "xref": [
+                            {
+                                "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 17, locStartCol = 11, locEndLine = 17, locEndCol = 24}",
+                                "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 28, locStartCol = 6, locEndLine = 28, locEndCol = 19}"
+                            }
+                        ]
+                    },
+                    {
+                        "id": 3,
+                        "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 18, locStartCol = 8, locEndLine = 18, locEndCol = 9}",
+                        "name": "z",
+                        "requiredness": "default",
+                        "type": {
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}",
+                            "name": {
+                                "name": "B"
+                            },
+                            "type": "struct"
+                        },
+                        "xref": [
+                            {
+                                "aLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 18, locStartCol = 6, locEndLine = 18, locEndCol = 7}",
+                                "rLoc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 9, locStartCol = 8, locEndLine = 9, locEndCol = 9}"
+                            }
+                        ]
+                    }
+                ],
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 1, locEndLine = 15, locEndCol = 7}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 15, locStartCol = 8, locEndLine = 15, locEndCol = 9}",
+                "name": "C",
+                "struct_type": "STRUCT"
+            }
+        ],
+        "typedefs": [
+            {
+                "ann_type": {
+                    "anns": null,
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 9, locEndLine = 45, locEndCol = 12}"
+                    ],
+                    "type": {
+                        "type": "i64"
+                    }
+                },
+                "anns": {
+                    "loc_ann_list": [
+                        {
+                            "ann_tag": "hs.newtype",
+                            "ann_type": "SimpleAnn",
+                            "loc": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 18, locEndLine = 45, locEndCol = 28}",
+                            "sep": {
+                                "sep_type": "NoSep"
+                            }
+                        }
+                    ],
+                    "loc_close": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 28, locEndLine = 45, locEndCol = 29}",
+                    "loc_open": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 17, locEndLine = 45, locEndCol = 18}"
+                },
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 1, locEndLine = 45, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 45, locStartCol = 13, locEndLine = 45, locEndCol = 16}",
+                "name": "Int",
+                "newtype": true,
+                "type": {
+                    "type": "i64"
+                },
+                "xref": []
+            },
+            {
+                "ann_type": {
+                    "anns": {
+                        "loc_ann_list": [
+                            {
+                                "ann_type": "ValueAnn",
+                                "loc_equal": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 38, locEndLine = 80, locEndCol = 39}",
+                                "loc_tag": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 30, locEndLine = 80, locEndCol = 37}",
+                                "loc_val": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 40, locEndLine = 80, locEndCol = 49}",
+                                "sep": {
+                                    "sep_type": "NoSep"
+                                },
+                                "tag": "hs.type",
+                                "val": {
+                                    "ann_value_type": "TextAnn",
+                                    "q": "DoubleQuote",
+                                    "t": "HashMap"
+                                }
+                            }
+                        ],
+                        "loc_close": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 49, locEndLine = 80, locEndCol = 50}",
+                        "loc_open": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 29, locEndLine = 80, locEndCol = 30}"
+                    },
+                    "loc": [
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 9, locEndLine = 80, locEndCol = 12}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 12, locEndLine = 80, locEndCol = 13}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 19, locEndLine = 80, locEndCol = 20}",
+                        "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 27, locEndLine = 80, locEndCol = 28}"
+                    ],
+                    "type": {
+                        "key_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 13, locEndLine = 80, locEndCol = 19}"
+                            ],
+                            "type": {
+                                "type": "string"
+                            }
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "anns": null,
+                            "loc": [
+                                "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 21, locEndLine = 80, locEndCol = 27}"
+                            ],
+                            "type": {
+                                "type": "string"
+                            }
+                        }
+                    }
+                },
+                "anns": null,
+                "loc_keyword": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 1, locEndLine = 80, locEndCol = 8}",
+                "loc_name": "Loc {locFile = \"test/if/b.thrift\", locStartLine = 80, locStartCol = 51, locEndLine = 80, locEndCol = 73}",
+                "name": "map_string_string_6258",
+                "newtype": false,
+                "type": {
+                    "key_type": {
+                        "type": "string"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "string"
+                    }
+                },
+                "xref": []
+            }
+        ],
+        "unions": []
+    }
+]
diff --git a/test/fixtures/gen-single-out/a.ast b/test/fixtures/gen-single-out/a.ast
new file mode 100644
--- /dev/null
+++ b/test/fixtures/gen-single-out/a.ast
@@ -0,0 +1,1178 @@
+[
+    {
+        "consts": [
+            {
+                "name": "a",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "name": {
+                        "name": "T"
+                    },
+                    "type": "typedef"
+                },
+                "value": {
+                    "named_constant": {
+                        "name": "i64_value",
+                        "src": "b"
+                    }
+                }
+            },
+            {
+                "name": "u",
+                "type": {
+                    "name": {
+                        "name": "U"
+                    },
+                    "type": "union"
+                },
+                "value": {
+                    "literal": {
+                        "type": "union",
+                        "value": {
+                            "field_name": "y",
+                            "field_type": {
+                                "inner_type": {
+                                    "type": "string"
+                                },
+                                "type": "list"
+                            },
+                            "field_value": {
+                                "literal": {
+                                    "type": "list",
+                                    "value": [
+                                        {
+                                            "named_constant": {
+                                                "name": "string_value",
+                                                "src": "b"
+                                            }
+                                        }
+                                    ]
+                                }
+                            }
+                        }
+                    }
+                }
+            },
+            {
+                "name": "b",
+                "type": {
+                    "name": {
+                        "name": "B",
+                        "src": "b"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i16_value",
+                                        "src": "b"
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i32_value",
+                                        "src": "b"
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "named_constant": {
+                                        "name": "i64_value",
+                                        "src": "b"
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "default_d",
+                "type": {
+                    "name": {
+                        "name": "B",
+                        "src": "b"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "default": null
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "zero",
+                "type": {
+                    "name": {
+                        "name": "Number",
+                        "src": "b"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero",
+                            "src": "b"
+                        }
+                    }
+                }
+            }
+        ],
+        "enums": [],
+        "includes": [
+            "test/if/b.thrift"
+        ],
+        "name": "a",
+        "options": {
+            "genfiles": null,
+            "include_path": ".",
+            "out_path": "test/fixtures/gen-single-out",
+            "path": "test/if/a.thrift",
+            "recursive": true
+        },
+        "path": "test/if/a.thrift",
+        "services": [
+            {
+                "functions": [
+                    {
+                        "args": [
+                            {
+                                "id": 1,
+                                "name": "x",
+                                "type": {
+                                    "type": "i32"
+                                }
+                            }
+                        ],
+                        "name": "getNumber",
+                        "oneway": false,
+                        "return_type": {
+                            "name": {
+                                "name": "Number",
+                                "src": "b"
+                            },
+                            "type": "enum"
+                        },
+                        "throws": []
+                    },
+                    {
+                        "args": [],
+                        "name": "doNothing",
+                        "oneway": false,
+                        "return_type": {
+                            "type": "void"
+                        },
+                        "throws": [
+                            {
+                                "id": 1,
+                                "name": "ex",
+                                "type": {
+                                    "name": {
+                                        "name": "X"
+                                    },
+                                    "type": "exception"
+                                }
+                            }
+                        ]
+                    }
+                ],
+                "name": "S"
+            },
+            {
+                "functions": [],
+                "name": "ParentService"
+            },
+            {
+                "functions": [
+                    {
+                        "args": [],
+                        "name": "foo",
+                        "oneway": false,
+                        "return_type": {
+                            "type": "i32"
+                        },
+                        "throws": []
+                    }
+                ],
+                "name": "ChildService",
+                "super": {
+                    "name": "ParentService"
+                }
+            }
+        ],
+        "structs": [
+            {
+                "fields": [
+                    {
+                        "default_value": {
+                            "named_constant": {
+                                "name": "a"
+                            }
+                        },
+                        "id": 1,
+                        "name": "a",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "type": "i64"
+                            },
+                            "name": {
+                                "name": "T"
+                            },
+                            "type": "typedef"
+                        }
+                    },
+                    {
+                        "default_value": {
+                            "named_constant": {
+                                "name": "bool_value",
+                                "src": "b"
+                            }
+                        },
+                        "id": 3,
+                        "name": "c",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "bool"
+                        }
+                    },
+                    {
+                        "id": 4,
+                        "name": "d",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "inner_type": {
+                                    "type": "i32"
+                                },
+                                "type": "list"
+                            },
+                            "type": "list"
+                        }
+                    },
+                    {
+                        "id": 5,
+                        "name": "e",
+                        "requiredness": "default",
+                        "type": {
+                            "key_type": {
+                                "type": "i32"
+                            },
+                            "type": "map",
+                            "val_type": {
+                                "type": "string"
+                            }
+                        }
+                    },
+                    {
+                        "default_value": {
+                            "literal": {
+                                "type": "enum",
+                                "value": {
+                                    "name": "Two",
+                                    "src": "b"
+                                }
+                            }
+                        },
+                        "id": 6,
+                        "name": "f",
+                        "requiredness": "default",
+                        "type": {
+                            "name": {
+                                "name": "Number",
+                                "src": "b"
+                            },
+                            "type": "enum"
+                        }
+                    },
+                    {
+                        "id": 7,
+                        "name": "g",
+                        "requiredness": "optional",
+                        "type": {
+                            "type": "string"
+                        }
+                    },
+                    {
+                        "id": 8,
+                        "name": "h",
+                        "requiredness": "required",
+                        "type": {
+                            "type": "string"
+                        }
+                    }
+                ],
+                "name": "A",
+                "struct_type": "STRUCT"
+            },
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "name": "reason",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "string"
+                        }
+                    }
+                ],
+                "name": "X",
+                "struct_type": "EXCEPTION"
+            }
+        ],
+        "typedefs": [
+            {
+                "name": "T",
+                "newtype": false,
+                "type": {
+                    "type": "i64"
+                }
+            }
+        ],
+        "unions": [
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "name": "x",
+                        "type": {
+                            "type": "byte"
+                        }
+                    },
+                    {
+                        "id": 2,
+                        "name": "y",
+                        "type": {
+                            "inner_type": {
+                                "type": "string"
+                            },
+                            "type": "list"
+                        }
+                    },
+                    {
+                        "id": 3,
+                        "name": "z",
+                        "type": {
+                            "inner_type": {
+                                "type": "i64"
+                            },
+                            "type": "set"
+                        }
+                    }
+                ],
+                "name": "U"
+            }
+        ]
+    },
+    {
+        "consts": [
+            {
+                "name": "byte_value",
+                "type": {
+                    "type": "byte"
+                },
+                "value": {
+                    "literal": {
+                        "type": "byte",
+                        "value": 0
+                    }
+                }
+            },
+            {
+                "name": "i16_value",
+                "type": {
+                    "type": "i16"
+                },
+                "value": {
+                    "literal": {
+                        "type": "i16",
+                        "value": 1
+                    }
+                }
+            },
+            {
+                "name": "i32_value",
+                "type": {
+                    "type": "i32"
+                },
+                "value": {
+                    "literal": {
+                        "type": "i32",
+                        "value": 2
+                    }
+                }
+            },
+            {
+                "name": "i64_value",
+                "type": {
+                    "type": "i64"
+                },
+                "value": {
+                    "literal": {
+                        "string": "3",
+                        "type": "i64",
+                        "value": 3
+                    }
+                }
+            },
+            {
+                "name": "float_value",
+                "type": {
+                    "type": "float"
+                },
+                "value": {
+                    "literal": {
+                        "binary": "3f000000",
+                        "type": "float",
+                        "value": 0.5
+                    }
+                }
+            },
+            {
+                "name": "double_value",
+                "type": {
+                    "type": "double"
+                },
+                "value": {
+                    "literal": {
+                        "binary": "400921f9f01b866e",
+                        "type": "double",
+                        "value": 3.14159
+                    }
+                }
+            },
+            {
+                "name": "bool_value",
+                "type": {
+                    "type": "bool"
+                },
+                "value": {
+                    "literal": {
+                        "type": "bool",
+                        "value": true
+                    }
+                }
+            },
+            {
+                "name": "string_value",
+                "type": {
+                    "type": "string"
+                },
+                "value": {
+                    "literal": {
+                        "type": "string",
+                        "value": "xxx"
+                    }
+                }
+            },
+            {
+                "name": "binary_value",
+                "type": {
+                    "type": "binary"
+                },
+                "value": {
+                    "literal": {
+                        "type": "binary",
+                        "value": "797979"
+                    }
+                }
+            },
+            {
+                "name": "newtype_value",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "name": {
+                        "name": "Int"
+                    },
+                    "type": "newtype"
+                },
+                "value": {
+                    "literal": {
+                        "type": "newtype",
+                        "value": {
+                            "string": "10",
+                            "type": "i64",
+                            "value": 10
+                        }
+                    }
+                }
+            },
+            {
+                "name": "scoped_enum_value",
+                "type": {
+                    "name": {
+                        "name": "Number"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero"
+                        }
+                    }
+                }
+            },
+            {
+                "name": "enum_value",
+                "type": {
+                    "name": {
+                        "name": "Number"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "One"
+                        }
+                    }
+                }
+            },
+            {
+                "name": "scoped_pseudoenum_value",
+                "type": {
+                    "name": {
+                        "name": "Number_Pseudo"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Zero"
+                        }
+                    }
+                }
+            },
+            {
+                "name": "pseudoenum_value",
+                "type": {
+                    "name": {
+                        "name": "Number_Pseudo"
+                    },
+                    "type": "enum"
+                },
+                "value": {
+                    "literal": {
+                        "type": "enum",
+                        "value": {
+                            "name": "Four"
+                        }
+                    }
+                }
+            },
+            {
+                "name": "list_value",
+                "type": {
+                    "inner_type": {
+                        "type": "i64"
+                    },
+                    "type": "list"
+                },
+                "value": {
+                    "literal": {
+                        "type": "list",
+                        "value": [
+                            {
+                                "literal": {
+                                    "string": "0",
+                                    "type": "i64",
+                                    "value": 0
+                                }
+                            },
+                            {
+                                "named_constant": {
+                                    "name": "i64_value"
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "set_value",
+                "type": {
+                    "inner_type": {
+                        "type": "string"
+                    },
+                    "type": "set"
+                },
+                "value": {
+                    "literal": {
+                        "type": "set",
+                        "value": [
+                            {
+                                "named_constant": {
+                                    "name": "string_value"
+                                }
+                            },
+                            {
+                                "literal": {
+                                    "type": "string",
+                                    "value": ""
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "map_value",
+                "type": {
+                    "key_type": {
+                        "type": "i64"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "bool"
+                    }
+                },
+                "value": {
+                    "literal": {
+                        "type": "map",
+                        "value": [
+                            {
+                                "key": {
+                                    "literal": {
+                                        "string": "0",
+                                        "type": "i64",
+                                        "value": 0
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "bool",
+                                        "value": true
+                                    }
+                                }
+                            },
+                            {
+                                "key": {
+                                    "literal": {
+                                        "string": "1",
+                                        "type": "i64",
+                                        "value": 1
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "bool",
+                                        "value": false
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "hash_map_value",
+                "type": {
+                    "inner_type": {
+                        "key_type": {
+                            "type": "string"
+                        },
+                        "type": "map",
+                        "val_type": {
+                            "type": "string"
+                        }
+                    },
+                    "name": {
+                        "name": "map_string_string_6258"
+                    },
+                    "type": "typedef"
+                },
+                "value": {
+                    "literal": {
+                        "type": "map",
+                        "value": [
+                            {
+                                "key": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "a"
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "A"
+                                    }
+                                }
+                            },
+                            {
+                                "key": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "b"
+                                    }
+                                },
+                                "val": {
+                                    "literal": {
+                                        "type": "string",
+                                        "value": "B"
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "struct_value",
+                "type": {
+                    "name": {
+                        "name": "B"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i16",
+                                        "value": 1
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i32",
+                                        "value": 2
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "string": "3",
+                                        "type": "i64",
+                                        "value": 3
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "explicit_struct_value",
+                "type": {
+                    "name": {
+                        "name": "B"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "a",
+                                "field_type": {
+                                    "type": "i16"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i16",
+                                        "value": 1
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "b",
+                                "field_type": {
+                                    "type": "i32"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "i32",
+                                        "value": 2
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "c",
+                                "field_type": {
+                                    "type": "i64"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "string": "3",
+                                        "type": "i64",
+                                        "value": 3
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "name": "explicit_nested_struct_value",
+                "type": {
+                    "name": {
+                        "name": "C"
+                    },
+                    "type": "struct"
+                },
+                "value": {
+                    "literal": {
+                        "type": "struct",
+                        "value": [
+                            {
+                                "field_name": "x",
+                                "field_type": {
+                                    "inner_type": {
+                                        "name": {
+                                            "name": "Number"
+                                        },
+                                        "type": "enum"
+                                    },
+                                    "type": "list"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "list",
+                                        "value": []
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "y",
+                                "field_type": {
+                                    "inner_type": {
+                                        "name": {
+                                            "name": "Number_Strict"
+                                        },
+                                        "type": "enum"
+                                    },
+                                    "type": "list"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "list",
+                                        "value": []
+                                    }
+                                }
+                            },
+                            {
+                                "field_name": "z",
+                                "field_type": {
+                                    "name": {
+                                        "name": "B"
+                                    },
+                                    "type": "struct"
+                                },
+                                "field_value": {
+                                    "literal": {
+                                        "type": "struct",
+                                        "value": [
+                                            {
+                                                "field_name": "a",
+                                                "field_type": {
+                                                    "type": "i16"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "type": "i16",
+                                                        "value": 1
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                "field_name": "b",
+                                                "field_type": {
+                                                    "type": "i32"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "type": "i32",
+                                                        "value": 2
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                "field_name": "c",
+                                                "field_type": {
+                                                    "type": "i64"
+                                                },
+                                                "field_value": {
+                                                    "literal": {
+                                                        "string": "3",
+                                                        "type": "i64",
+                                                        "value": 3
+                                                    }
+                                                }
+                                            }
+                                        ]
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                }
+            }
+        ],
+        "enums": [
+            {
+                "constants": [
+                    {
+                        "name": "Zero",
+                        "value": 0
+                    },
+                    {
+                        "name": "One",
+                        "value": 1
+                    },
+                    {
+                        "name": "Two",
+                        "value": 2
+                    },
+                    {
+                        "name": "Three",
+                        "value": 3
+                    }
+                ],
+                "flavour": "sum_type",
+                "name": "Number"
+            },
+            {
+                "constants": [
+                    {
+                        "name": "Zero",
+                        "value": 0
+                    }
+                ],
+                "flavour": "sum_type",
+                "name": "Number_Strict"
+            },
+            {
+                "constants": [
+                    {
+                        "name": "Zero",
+                        "value": 0
+                    },
+                    {
+                        "name": "Four",
+                        "value": 4
+                    }
+                ],
+                "flavour": "sum_type",
+                "name": "Number_Pseudo"
+            },
+            {
+                "constants": [
+                    {
+                        "name": "Five",
+                        "value": 5
+                    },
+                    {
+                        "name": "Zero",
+                        "value": 0
+                    }
+                ],
+                "flavour": "sum_type",
+                "name": "Number_Discontinuous"
+            },
+            {
+                "constants": [],
+                "flavour": "sum_type",
+                "name": "Number_Empty"
+            }
+        ],
+        "includes": [],
+        "name": "b",
+        "options": {
+            "genfiles": null,
+            "include_path": ".",
+            "out_path": "test/fixtures/gen-single-out",
+            "path": "test/if/a.thrift",
+            "recursive": true
+        },
+        "path": "test/if/b.thrift",
+        "services": [],
+        "structs": [
+            {
+                "fields": [
+                    {
+                        "default_value": {
+                            "literal": {
+                                "type": "i16",
+                                "value": 1
+                            }
+                        },
+                        "id": 1,
+                        "name": "a",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i16"
+                        }
+                    },
+                    {
+                        "id": 2,
+                        "name": "b",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i32"
+                        }
+                    },
+                    {
+                        "id": 3,
+                        "name": "c",
+                        "requiredness": "default",
+                        "type": {
+                            "type": "i64"
+                        }
+                    }
+                ],
+                "name": "B",
+                "struct_type": "STRUCT"
+            },
+            {
+                "fields": [
+                    {
+                        "id": 1,
+                        "name": "x",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "name": {
+                                    "name": "Number"
+                                },
+                                "type": "enum"
+                            },
+                            "type": "list"
+                        }
+                    },
+                    {
+                        "id": 2,
+                        "name": "y",
+                        "requiredness": "default",
+                        "type": {
+                            "inner_type": {
+                                "name": {
+                                    "name": "Number_Strict"
+                                },
+                                "type": "enum"
+                            },
+                            "type": "list"
+                        }
+                    },
+                    {
+                        "id": 3,
+                        "name": "z",
+                        "requiredness": "default",
+                        "type": {
+                            "name": {
+                                "name": "B"
+                            },
+                            "type": "struct"
+                        }
+                    }
+                ],
+                "name": "C",
+                "struct_type": "STRUCT"
+            }
+        ],
+        "typedefs": [
+            {
+                "name": "Int",
+                "newtype": true,
+                "type": {
+                    "type": "i64"
+                }
+            },
+            {
+                "name": "map_string_string_6258",
+                "newtype": false,
+                "type": {
+                    "key_type": {
+                        "type": "string"
+                    },
+                    "type": "map",
+                    "val_type": {
+                        "type": "string"
+                    }
+                }
+            }
+        ],
+        "unions": []
+    }
+]
diff --git a/test/github/Util.hs b/test/github/Util.hs
new file mode 100644
--- /dev/null
+++ b/test/github/Util.hs
@@ -0,0 +1,88 @@
+{-
+  Copyright (c) Meta Platforms, Inc. and affiliates.
+  All rights reserved.
+
+  This source code is licensed under the BSD-style license found in the
+  LICENSE file in the root directory of this source tree.
+-}
+
+module Util (withFixtureOptions) where
+
+import Data.List
+import System.Directory
+import System.FilePath
+
+import Thrift.Compiler.Options
+import Thrift.Compiler.OptParse
+import Thrift.Compiler.Plugins.Haskell
+import Thrift.Compiler.Plugins.Linter
+
+withFixtureOptions :: ([SomeOptions] -> IO a) -> IO a
+withFixtureOptions f = do
+  dir <- getCurrentDirectory
+  compilerDir <- findCompilerDir dir
+  let outPath = if inTree
+        then "compiler" </> "test" </> "fixtures"
+        else                "test" </> "fixtures"
+      inTree = takeBaseName compilerDir == "compiler"
+      testsCwd = if inTree then takeDirectory compilerDir else compilerDir
+      includePathFor fp
+        | inTree, "compiler/" `isPrefixOf` fp = "compiler"
+        | "tests/" `isPrefixOf` fp = "tests"
+        | otherwise = "."
+      fixup fp
+        | Just rest <- stripPrefix "compiler/" fp = rest
+        | Just rest <- stripPrefix "tests/" fp = rest
+        | otherwise = fp
+
+  withCurrentDirectory testsCwd $ f
+    [ TheseOptions (defaultOptions langopts)
+         { optsPath = fixup path
+         , optsOutPath = outPath </> genDir
+         , optsIncludePath = includePathFor path
+         , optsRecursive = True
+         , optsGenMode = mode
+         , optsSingleOutput = singleOut
+         }
+    | (TheseLangOpts langopts, mode, singleOut, genDir, path) <-
+         [ (TheseLangOpts defaultHsOpts, EmitCode, False, "",
+            "tests/if/hs_test.thrift")
+         , (TheseLangOpts defaultHsOpts{hsoptsExtraHasFields=True},
+            EmitCode, False, "",
+            "tests/if/service.thrift")
+         , (TheseLangOpts defaultHsOpts, EmitCode, False, "",
+            "compiler/test/if/a.thrift")
+         , (TheseLangOpts NoOpts, EmitJSON WithoutLoc, False, "gen-basic",
+            "compiler/test/if/a.thrift")
+         , (TheseLangOpts NoOpts, EmitJSON WithoutLoc, True, "gen-single-out",
+            "compiler/test/if/a.thrift")
+         , (TheseLangOpts NoOpts, EmitJSON WithLoc, False, "gen-basic-loc",
+            "compiler/test/if/a.thrift")
+         , (TheseLangOpts NoOpts, EmitJSON WithLoc, True, "gen-single-out-loc",
+            "compiler/test/if/a.thrift")
+         ]
+    ]
+
+findCompilerDir :: FilePath -> IO FilePath
+findCompilerDir cwd = lookFor "thrift-compiler.cabal" cwd maxDepth >>= \mdir ->
+  case mdir of
+    Nothing -> error "findCompilerDir: reached max depth, couldn't find thrift-compiler.cabal"
+    Just d  -> return d
+
+  where lookFor _ _ (-1) = return Nothing
+        lookFor file curDir depth = do
+          existsHere <- doesFileExist (curDir </> file)
+          if existsHere
+            then return (Just curDir)
+            else do xs <- listDirectory curDir
+                    visitDirsIn xs file curDir depth
+        visitDirsIn [] _ _ _ = return Nothing
+        visitDirsIn (d:ds) file curDir depth = do
+          dirExists <- doesDirectoryExist (curDir </> d)
+          if dirExists
+            then do mfp <- lookFor file (curDir </> d) (depth-1)
+                    case mfp of
+                      Nothing -> visitDirsIn ds file curDir depth
+                      Just fp -> return (Just fp)
+            else visitDirsIn ds file curDir depth
+        maxDepth = 2 :: Int
diff --git a/test/if/a.thrift b/test/if/a.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/a.thrift
@@ -0,0 +1,50 @@
+// Copyright (c) Facebook, Inc. and its affiliates.
+
+# @nolint
+
+include "test/if/b.thrift"
+
+typedef i64 T
+
+const T a = b.i64_value;
+
+struct A {
+  1: T a = a;
+  3: bool c = b.bool_value;
+  4: list<list<i32>> d;
+  5: map<i32, string> e;
+  6: b.Number f = b.Two;
+  7: optional string g;
+  8: required string h;
+}
+
+union U {
+  1: byte x;
+  2: list<string> y;
+  3: set<i64> z;
+}
+
+exception X {
+  1: string reason;
+}
+
+const U u = {"y": [b.string_value]};
+
+const b.B b = {"a": b.i16_value, "b": b.i32_value, "c": b.i64_value};
+
+const b.B default_d = {};
+
+const b.Number zero = b.Zero;
+
+service S {
+  b.Number getNumber(1: i32 x);
+
+  void doNothing() throws (1: X ex);
+}
+
+service ParentService {
+}
+
+service ChildService extends ParentService {
+  i32 foo();
+}
diff --git a/test/if/b.thrift b/test/if/b.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/b.thrift
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct B {
+  1: i16 a = 1;
+  2: i32 b;
+  3: i64 c;
+}
+
+struct C {
+  1: list<Number> x;
+  2: list<Number_Strict> y;
+  3: B z;
+}
+
+enum Number {
+  Zero = 0,
+  One = 1,
+  Two = 2,
+  Three = 3,
+}
+
+enum Number_Strict {
+  Zero = 0,
+} (hs.nounknown)
+
+enum Number_Pseudo {
+  Zero = 0,
+  Four = 4,
+} (hs.pseudoenum)
+
+enum Number_Discontinuous {
+  Five = 5,
+  Zero = 0,
+}
+
+enum Number_Empty {
+}
+
+typedef i64 Int (hs.newtype)
+
+# All the Base types as constants
+const byte byte_value = 0;
+const i16 i16_value = 1;
+const i32 i32_value = 2;
+const i64 i64_value = 3;
+const float float_value = 0.5;
+const double double_value = 3.14159;
+const bool bool_value = true;
+const string string_value = "xxx";
+const binary binary_value = "yyy";
+const Int newtype_value = 10;
+const Number scoped_enum_value = Number.Zero;
+const Number enum_value = One;
+const Number_Pseudo scoped_pseudoenum_value = Number_Pseudo.Zero;
+const Number_Pseudo pseudoenum_value = Four;
+
+# Some Collection Types
+const list<i64> list_value = [0, i64_value];
+const set<string> set_value = [string_value, ""];
+# set<float> is undefined - can't handle NaN.
+# const set<double> (cpp.template = 'std::unordered_set') hash_set_value = [0.1, 0.2]
+const map<i64, bool> map_value = {0: true, 1: false};
+const map_string_string_6258 hash_map_value = {"a": "A", "b": "B"};
+
+const B struct_value = {"a": 1, "b": 2, "c": 3};
+const B explicit_struct_value = B{a = 1, b = 2, c = 3};
+const C explicit_nested_struct_value = C{
+  x = [],
+  y = [],
+  z = B{a = 1, b = 2, c = 3},
+};
+
+// The following were automatically generated and may benefit from renaming.
+typedef map<string, string> (hs.type = "HashMap") map_string_string_6258
diff --git a/test/if/c.thrift b/test/if/c.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/c.thrift
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct FirstAnnotation {
+  1: string name;
+  2: i64 count = 1;
+}
+struct SecondAnnotation {
+  2: i64 total = 0;
+  3: SecondAnnotation recurse;
+  4: UnionAnnotation either;
+}
+union UnionAnnotation {
+  2: i64 left;
+  3: i64 right;
+}
+
+@FirstAnnotation{name = "my_type"}
+typedef string annotated_string
+
+@FirstAnnotation{name = "my_struct", count = 3}
+@SecondAnnotation
+struct MyStruct {
+  @SecondAnnotation{}
+  5: annotated_string tag;
+}
+
+@FirstAnnotation
+exception MyException {
+  1: string message;
+}
+
+@SecondAnnotation{total = 1, either = UnionAnnotation{left = 0}}
+union MyUnion {
+  1: i64 int_value;
+  2: string string_value;
+}
+
+@SecondAnnotation{total = 4, recurse = SecondAnnotation{total = 5}}
+service MyService {
+  @SecondAnnotation
+  i64 my_function(2: annotated_string param);
+}
+
+@FirstAnnotation{name = "shiny"}
+enum MyEnum {
+  UNKNOWN = 0,
+  @SecondAnnotation
+  FIRST = 1,
+}
+
+@FirstAnnotation{name = "my_hack_enum"}
+const map<string, string> MyConst = {"ENUMERATOR": "value"};
diff --git a/test/if/d.thrift b/test/if/d.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/d.thrift
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef map<string, string> hstypedef
+typedef map<string, string> hsnewtypeann (hs.newtype)
+
+struct HsStruct {
+  1: i32 strictann (hs.strict);
+  2: i32 lazyann (hs.lazy);
+  3: i32 inherit;
+}
+struct HsStrictAnn {
+  1: i32 strictann (hs.strict);
+  2: i32 lazyann (hs.lazy);
+  3: i32 inherit;
+} (hs.strict)
+struct HsLazyAnn {
+  1: i32 strictann (hs.strict);
+  2: i32 lazyann (hs.lazy);
+  3: i32 inherit;
+} (hs.lazy)
+struct HsPrefixAnn {
+  1: i32 strictann (hs.strict);
+  2: i32 lazyann (hs.lazy);
+  3: i32 inherit;
+} (hs.prefix = "structprefix")
+
+union HsUnion {
+  1: i32 left;
+  2: i32 right;
+}
+union HsUnionNonEmptyAnn {
+  1: i32 left;
+  2: i32 right;
+} (hs.nonempty)
+
+enum HsEnum {
+  ONE = 1,
+  TWO = 2,
+  THREE = 3,
+}
+enum HsEnumEmpty {
+}
+enum HsEnumNoUnknownAnn {
+  ONE = 1,
+  TWO = 2,
+  THREE = 3,
+} (hs.nounknown)
+enum HsEnumEmptyNoUnknownAnn {
+} (hs.nounknown)
+enum HsEnumPseudoenumAnn {
+  ONE = 1,
+  TWO = 2,
+  THREE = 3,
+} (hs.pseudoenum)
+enum HsEnumDuplicatedPseudoenumAnn {
+  ONE = 1,
+  TWO = 2,
+  THREE = 3,
+} (hs.pseudoenum)
+enum HsEnumEmptyPseudoenumAnn {
+} (hs.pseudoenum)
+enum HsEnumPseudoenumThriftAnn {
+  ONE = 1,
+  TWO = 2,
+  THREE = 3,
+} (hs.pseudoenum = "thriftenum")
+enum HsEnumEmptyPseudoenumThriftAnn {
+} (hs.pseudoenum = "thriftenum")
+
+struct HsStructOfComplexTypes {
+  1: HsStruct a_struct;
+  2: HsUnion a_union;
+  3: HsEnum an_enum;
+  4: HsEnumPseudoenumAnn a_pseudoenum;
+  5: HsEnumPseudoenumThriftAnn a_thrift_pseudoenum;
+}
diff --git a/test/if/e.thrift b/test/if/e.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/e.thrift
@@ -0,0 +1,31 @@
+// Copyright (c) Facebook, Inc. and its affiliates.
+
+# @nolint
+
+namespace hs Namespace
+typedef i64 _Type
+
+exception _Exception {
+  1: string reason;
+}
+
+const _Type a = 100;
+
+struct _Struct {
+  1: _Type a = a;
+  2: list<list<_Type>> b;
+}
+
+union _Union {
+  1: byte x;
+  2: list<string> y;
+  3: set<i64> z;
+}
+
+const _Union u = {"y": ["test"]};
+
+service _Service {
+  _Type getNumber(1: i32 x);
+
+  void doNothing() throws (1: _Exception ex);
+}
diff --git a/test/if/f.thrift b/test/if/f.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/f.thrift
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum HugeEnum {
+  VALUE_0001 = 1,
+  VALUE_0002 = 2,
+  VALUE_0003 = 3,
+  VALUE_0004 = 4,
+  VALUE_0005 = 5,
+  VALUE_0006 = 6,
+  VALUE_0007 = 7,
+  VALUE_0008 = 8,
+  VALUE_0009 = 9,
+  VALUE_0010 = 10,
+  VALUE_0011 = 11,
+  VALUE_0012 = 12,
+  VALUE_0013 = 13,
+  VALUE_0014 = 14,
+  VALUE_0015 = 15,
+  VALUE_0016 = 16,
+  VALUE_0017 = 17,
+  VALUE_0018 = 18,
+  VALUE_0019 = 19,
+  VALUE_0020 = 20,
+  VALUE_0021 = 21,
+  VALUE_0022 = 22,
+  VALUE_0023 = 23,
+  VALUE_0024 = 24,
+  VALUE_0025 = 25,
+  VALUE_0026 = 26,
+  VALUE_0027 = 27,
+  VALUE_0028 = 28,
+  VALUE_0029 = 29,
+  VALUE_0030 = 30,
+  VALUE_0031 = 31,
+  VALUE_0032 = 32,
+  VALUE_0033 = 33,
+  VALUE_0034 = 34,
+  VALUE_0035 = 35,
+  VALUE_0036 = 36,
+  VALUE_0037 = 37,
+  VALUE_0038 = 38,
+  VALUE_0039 = 39,
+  VALUE_0040 = 40,
+  VALUE_0041 = 41,
+  VALUE_0042 = 42,
+  VALUE_0043 = 43,
+  VALUE_0044 = 44,
+  VALUE_0045 = 45,
+  VALUE_0046 = 46,
+  VALUE_0047 = 47,
+  VALUE_0048 = 48,
+  VALUE_0049 = 49,
+  VALUE_0050 = 50,
+  VALUE_0051 = 51,
+  VALUE_0052 = 52,
+  VALUE_0053 = 53,
+  VALUE_0054 = 54,
+  VALUE_0055 = 55,
+  VALUE_0056 = 56,
+  VALUE_0057 = 57,
+  VALUE_0058 = 58,
+  VALUE_0059 = 59,
+  VALUE_0060 = 60,
+  VALUE_0061 = 61,
+  VALUE_0062 = 62,
+  VALUE_0063 = 63,
+  VALUE_0064 = 64,
+  VALUE_0065 = 65,
+  VALUE_0066 = 66,
+  VALUE_0067 = 67,
+  VALUE_0068 = 68,
+  VALUE_0069 = 69,
+  VALUE_0070 = 70,
+  VALUE_0071 = 71,
+  VALUE_0072 = 72,
+  VALUE_0073 = 73,
+  VALUE_0074 = 74,
+  VALUE_0075 = 75,
+  VALUE_0076 = 76,
+  VALUE_0077 = 77,
+  VALUE_0078 = 78,
+  VALUE_0079 = 79,
+  VALUE_0080 = 80,
+  VALUE_0081 = 81,
+  VALUE_0082 = 82,
+  VALUE_0083 = 83,
+  VALUE_0084 = 84,
+  VALUE_0085 = 85,
+  VALUE_0086 = 86,
+  VALUE_0087 = 87,
+  VALUE_0088 = 88,
+  VALUE_0089 = 89,
+  VALUE_0090 = 90,
+  VALUE_0091 = 91,
+  VALUE_0092 = 92,
+  VALUE_0093 = 93,
+  VALUE_0094 = 94,
+  VALUE_0095 = 95,
+  VALUE_0096 = 96,
+  VALUE_0097 = 97,
+  VALUE_0098 = 98,
+  VALUE_0099 = 99,
+  VALUE_0100 = 100,
+  VALUE_0101 = 101,
+  VALUE_0102 = 102,
+  VALUE_0103 = 103,
+  VALUE_0104 = 104,
+  VALUE_0105 = 105,
+  VALUE_0106 = 106,
+  VALUE_0107 = 107,
+  VALUE_0108 = 108,
+  VALUE_0109 = 109,
+  VALUE_0110 = 110,
+  VALUE_0111 = 111,
+  VALUE_0112 = 112,
+  VALUE_0113 = 113,
+  VALUE_0114 = 114,
+  VALUE_0115 = 115,
+  VALUE_0116 = 116,
+  VALUE_0117 = 117,
+  VALUE_0118 = 118,
+  VALUE_0119 = 119,
+  VALUE_0120 = 120,
+  VALUE_0121 = 121,
+  VALUE_0122 = 122,
+  VALUE_0123 = 123,
+  VALUE_0124 = 124,
+  VALUE_0125 = 125,
+  VALUE_0126 = 126,
+  VALUE_0127 = 127,
+  VALUE_0128 = 128,
+  VALUE_0129 = 129,
+  VALUE_0130 = 130,
+  VALUE_0131 = 131,
+  VALUE_0132 = 132,
+  VALUE_0133 = 133,
+  VALUE_0134 = 134,
+  VALUE_0135 = 135,
+  VALUE_0136 = 136,
+  VALUE_0137 = 137,
+  VALUE_0138 = 138,
+  VALUE_0139 = 139,
+  VALUE_0140 = 140,
+  VALUE_0141 = 141,
+  VALUE_0142 = 142,
+  VALUE_0143 = 143,
+  VALUE_0144 = 144,
+  VALUE_0145 = 145,
+  VALUE_0146 = 146,
+  VALUE_0147 = 147,
+  VALUE_0148 = 148,
+  VALUE_0149 = 149,
+  VALUE_0150 = 150,
+  VALUE_0151 = 151,
+  VALUE_0152 = 152,
+  VALUE_0153 = 153,
+  VALUE_0154 = 154,
+  VALUE_0155 = 155,
+  VALUE_0156 = 156,
+  VALUE_0157 = 157,
+  VALUE_0158 = 158,
+  VALUE_0159 = 159,
+  VALUE_0160 = 160,
+  VALUE_0161 = 161,
+  VALUE_0162 = 162,
+  VALUE_0163 = 163,
+  VALUE_0164 = 164,
+  VALUE_0165 = 165,
+  VALUE_0166 = 166,
+  VALUE_0167 = 167,
+  VALUE_0168 = 168,
+  VALUE_0169 = 169,
+  VALUE_0170 = 170,
+  VALUE_0171 = 171,
+  VALUE_0172 = 172,
+  VALUE_0173 = 173,
+  VALUE_0174 = 174,
+  VALUE_0175 = 175,
+  VALUE_0176 = 176,
+  VALUE_0177 = 177,
+  VALUE_0178 = 178,
+  VALUE_0179 = 179,
+  VALUE_0180 = 180,
+  VALUE_0181 = 181,
+  VALUE_0182 = 182,
+  VALUE_0183 = 183,
+  VALUE_0184 = 184,
+  VALUE_0185 = 185,
+  VALUE_0186 = 186,
+  VALUE_0187 = 187,
+  VALUE_0188 = 188,
+  VALUE_0189 = 189,
+  VALUE_0190 = 190,
+  VALUE_0191 = 191,
+  VALUE_0192 = 192,
+  VALUE_0193 = 193,
+  VALUE_0194 = 194,
+  VALUE_0195 = 195,
+  VALUE_0196 = 196,
+  VALUE_0197 = 197,
+  VALUE_0198 = 198,
+  VALUE_0199 = 199,
+  VALUE_0200 = 200,
+  VALUE_0201 = 201,
+  VALUE_0202 = 202,
+  VALUE_0203 = 203,
+  VALUE_0204 = 204,
+  VALUE_0205 = 205,
+  VALUE_0206 = 206,
+  VALUE_0207 = 207,
+  VALUE_0208 = 208,
+  VALUE_0209 = 209,
+  VALUE_0210 = 210,
+  VALUE_0211 = 211,
+  VALUE_0212 = 212,
+  VALUE_0213 = 213,
+  VALUE_0214 = 214,
+  VALUE_0215 = 215,
+  VALUE_0216 = 216,
+  VALUE_0217 = 217,
+  VALUE_0218 = 218,
+  VALUE_0219 = 219,
+  VALUE_0220 = 220,
+  VALUE_0221 = 221,
+  VALUE_0222 = 222,
+  VALUE_0223 = 223,
+  VALUE_0224 = 224,
+  VALUE_0225 = 225,
+  VALUE_0226 = 226,
+  VALUE_0227 = 227,
+  VALUE_0228 = 228,
+  VALUE_0229 = 229,
+  VALUE_0230 = 230,
+  VALUE_0231 = 231,
+  VALUE_0232 = 232,
+  VALUE_0233 = 233,
+  VALUE_0234 = 234,
+  VALUE_0235 = 235,
+  VALUE_0236 = 236,
+  VALUE_0237 = 237,
+  VALUE_0238 = 238,
+  VALUE_0239 = 239,
+  VALUE_0240 = 240,
+  VALUE_0241 = 241,
+  VALUE_0242 = 242,
+  VALUE_0243 = 243,
+  VALUE_0244 = 244,
+  VALUE_0245 = 245,
+  VALUE_0246 = 246,
+  VALUE_0247 = 247,
+  VALUE_0248 = 248,
+  VALUE_0249 = 249,
+  VALUE_0250 = 250,
+  VALUE_0251 = 251,
+  VALUE_0252 = 252,
+  VALUE_0253 = 253,
+  VALUE_0254 = 254,
+  VALUE_0255 = 255,
+  VALUE_0256 = 256,
+  VALUE_0257 = 257,
+  VALUE_0258 = 258,
+  VALUE_0259 = 259,
+  VALUE_0260 = 260,
+  VALUE_0261 = 261,
+  VALUE_0262 = 262,
+  VALUE_0263 = 263,
+  VALUE_0264 = 264,
+  VALUE_0265 = 265,
+  VALUE_0266 = 266,
+  VALUE_0267 = 267,
+  VALUE_0268 = 268,
+  VALUE_0269 = 269,
+  VALUE_0270 = 270,
+  VALUE_0271 = 271,
+  VALUE_0272 = 272,
+  VALUE_0273 = 273,
+  VALUE_0274 = 274,
+  VALUE_0275 = 275,
+  VALUE_0276 = 276,
+  VALUE_0277 = 277,
+  VALUE_0278 = 278,
+  VALUE_0279 = 279,
+  VALUE_0280 = 280,
+  VALUE_0281 = 281,
+  VALUE_0282 = 282,
+  VALUE_0283 = 283,
+  VALUE_0284 = 284,
+  VALUE_0285 = 285,
+  VALUE_0286 = 286,
+  VALUE_0287 = 287,
+  VALUE_0288 = 288,
+  VALUE_0289 = 289,
+  VALUE_0290 = 290,
+  VALUE_0291 = 291,
+  VALUE_0292 = 292,
+  VALUE_0293 = 293,
+  VALUE_0294 = 294,
+  VALUE_0295 = 295,
+  VALUE_0296 = 296,
+  VALUE_0297 = 297,
+  VALUE_0298 = 298,
+  VALUE_0299 = 299,
+  VALUE_0300 = 300,
+  VALUE_0301 = 301,
+  VALUE_0302 = 302,
+  VALUE_0303 = 303,
+  VALUE_0304 = 304,
+  VALUE_0305 = 305,
+  VALUE_0306 = 306,
+  VALUE_0307 = 307,
+  VALUE_0308 = 308,
+  VALUE_0309 = 309,
+  VALUE_0310 = 310,
+  VALUE_0311 = 311,
+  VALUE_0312 = 312,
+  VALUE_0313 = 313,
+  VALUE_0314 = 314,
+  VALUE_0315 = 315,
+  VALUE_0316 = 316,
+  VALUE_0317 = 317,
+  VALUE_0318 = 318,
+  VALUE_0319 = 319,
+  VALUE_0320 = 320,
+  VALUE_0321 = 321,
+  VALUE_0322 = 322,
+  VALUE_0323 = 323,
+  VALUE_0324 = 324,
+  VALUE_0325 = 325,
+  VALUE_0326 = 326,
+  VALUE_0327 = 327,
+  VALUE_0328 = 328,
+  VALUE_0329 = 329,
+  VALUE_0330 = 330,
+  VALUE_0331 = 331,
+  VALUE_0332 = 332,
+  VALUE_0333 = 333,
+  VALUE_0334 = 334,
+  VALUE_0335 = 335,
+  VALUE_0336 = 336,
+  VALUE_0337 = 337,
+  VALUE_0338 = 338,
+  VALUE_0339 = 339,
+  VALUE_0340 = 340,
+  VALUE_0341 = 341,
+  VALUE_0342 = 342,
+  VALUE_0343 = 343,
+  VALUE_0344 = 344,
+  VALUE_0345 = 345,
+  VALUE_0346 = 346,
+  VALUE_0347 = 347,
+  VALUE_0348 = 348,
+  VALUE_0349 = 349,
+  VALUE_0350 = 350,
+  VALUE_0351 = 351,
+  VALUE_0352 = 352,
+  VALUE_0353 = 353,
+  VALUE_0354 = 354,
+  VALUE_0355 = 355,
+  VALUE_0356 = 356,
+  VALUE_0357 = 357,
+  VALUE_0358 = 358,
+  VALUE_0359 = 359,
+  VALUE_0360 = 360,
+  VALUE_0361 = 361,
+  VALUE_0362 = 362,
+  VALUE_0363 = 363,
+  VALUE_0364 = 364,
+  VALUE_0365 = 365,
+  VALUE_0366 = 366,
+  VALUE_0367 = 367,
+  VALUE_0368 = 368,
+  VALUE_0369 = 369,
+  VALUE_0370 = 370,
+  VALUE_0371 = 371,
+  VALUE_0372 = 372,
+  VALUE_0373 = 373,
+  VALUE_0374 = 374,
+  VALUE_0375 = 375,
+  VALUE_0376 = 376,
+  VALUE_0377 = 377,
+  VALUE_0378 = 378,
+  VALUE_0379 = 379,
+  VALUE_0380 = 380,
+  VALUE_0381 = 381,
+  VALUE_0382 = 382,
+  VALUE_0383 = 383,
+  VALUE_0384 = 384,
+  VALUE_0385 = 385,
+  VALUE_0386 = 386,
+  VALUE_0387 = 387,
+  VALUE_0388 = 388,
+  VALUE_0389 = 389,
+  VALUE_0390 = 390,
+  VALUE_0391 = 391,
+  VALUE_0392 = 392,
+  VALUE_0393 = 393,
+  VALUE_0394 = 394,
+  VALUE_0395 = 395,
+  VALUE_0396 = 396,
+  VALUE_0397 = 397,
+  VALUE_0398 = 398,
+  VALUE_0399 = 399,
+  VALUE_0400 = 400,
+  VALUE_0401 = 401,
+  VALUE_0402 = 402,
+  VALUE_0403 = 403,
+  VALUE_0404 = 404,
+  VALUE_0405 = 405,
+  VALUE_0406 = 406,
+  VALUE_0407 = 407,
+  VALUE_0408 = 408,
+  VALUE_0409 = 409,
+  VALUE_0410 = 410,
+  VALUE_0411 = 411,
+  VALUE_0412 = 412,
+  VALUE_0413 = 413,
+  VALUE_0414 = 414,
+  VALUE_0415 = 415,
+  VALUE_0416 = 416,
+  VALUE_0417 = 417,
+  VALUE_0418 = 418,
+  VALUE_0419 = 419,
+  VALUE_0420 = 420,
+  VALUE_0421 = 421,
+  VALUE_0422 = 422,
+  VALUE_0423 = 423,
+  VALUE_0424 = 424,
+  VALUE_0425 = 425,
+  VALUE_0426 = 426,
+  VALUE_0427 = 427,
+  VALUE_0428 = 428,
+  VALUE_0429 = 429,
+  VALUE_0430 = 430,
+  VALUE_0431 = 431,
+  VALUE_0432 = 432,
+  VALUE_0433 = 433,
+  VALUE_0434 = 434,
+  VALUE_0435 = 435,
+  VALUE_0436 = 436,
+  VALUE_0437 = 437,
+  VALUE_0438 = 438,
+  VALUE_0439 = 439,
+  VALUE_0440 = 440,
+  VALUE_0441 = 441,
+  VALUE_0442 = 442,
+  VALUE_0443 = 443,
+  VALUE_0444 = 444,
+  VALUE_0445 = 445,
+  VALUE_0446 = 446,
+  VALUE_0447 = 447,
+  VALUE_0448 = 448,
+  VALUE_0449 = 449,
+  VALUE_0450 = 450,
+  VALUE_0451 = 451,
+  VALUE_0452 = 452,
+  VALUE_0453 = 453,
+  VALUE_0454 = 454,
+  VALUE_0455 = 455,
+  VALUE_0456 = 456,
+  VALUE_0457 = 457,
+  VALUE_0458 = 458,
+  VALUE_0459 = 459,
+  VALUE_0460 = 460,
+  VALUE_0461 = 461,
+  VALUE_0462 = 462,
+  VALUE_0463 = 463,
+  VALUE_0464 = 464,
+  VALUE_0465 = 465,
+  VALUE_0466 = 466,
+  VALUE_0467 = 467,
+  VALUE_0468 = 468,
+  VALUE_0469 = 469,
+  VALUE_0470 = 470,
+  VALUE_0471 = 471,
+  VALUE_0472 = 472,
+  VALUE_0473 = 473,
+  VALUE_0474 = 474,
+  VALUE_0475 = 475,
+  VALUE_0476 = 476,
+  VALUE_0477 = 477,
+  VALUE_0478 = 478,
+  VALUE_0479 = 479,
+  VALUE_0480 = 480,
+  VALUE_0481 = 481,
+  VALUE_0482 = 482,
+  VALUE_0483 = 483,
+  VALUE_0484 = 484,
+  VALUE_0485 = 485,
+  VALUE_0486 = 486,
+  VALUE_0487 = 487,
+  VALUE_0488 = 488,
+  VALUE_0489 = 489,
+  VALUE_0490 = 490,
+  VALUE_0491 = 491,
+  VALUE_0492 = 492,
+  VALUE_0493 = 493,
+  VALUE_0494 = 494,
+  VALUE_0495 = 495,
+  VALUE_0496 = 496,
+  VALUE_0497 = 497,
+  VALUE_0498 = 498,
+  VALUE_0499 = 499,
+  VALUE_0500 = 500,
+  VALUE_0501 = 501,
+  VALUE_0502 = 502,
+  VALUE_0503 = 503,
+  VALUE_0504 = 504,
+  VALUE_0505 = 505,
+  VALUE_0506 = 506,
+  VALUE_0507 = 507,
+  VALUE_0508 = 508,
+  VALUE_0509 = 509,
+  VALUE_0510 = 510,
+  VALUE_0511 = 511,
+  VALUE_0512 = 512,
+  VALUE_0513 = 513,
+  VALUE_0514 = 514,
+  VALUE_0515 = 515,
+  VALUE_0516 = 516,
+  VALUE_0517 = 517,
+  VALUE_0518 = 518,
+  VALUE_0519 = 519,
+  VALUE_0520 = 520,
+  VALUE_0521 = 521,
+  VALUE_0522 = 522,
+  VALUE_0523 = 523,
+  VALUE_0524 = 524,
+  VALUE_0525 = 525,
+  VALUE_0526 = 526,
+  VALUE_0527 = 527,
+  VALUE_0528 = 528,
+  VALUE_0529 = 529,
+  VALUE_0530 = 530,
+  VALUE_0531 = 531,
+  VALUE_0532 = 532,
+  VALUE_0533 = 533,
+  VALUE_0534 = 534,
+  VALUE_0535 = 535,
+  VALUE_0536 = 536,
+  VALUE_0537 = 537,
+  VALUE_0538 = 538,
+  VALUE_0539 = 539,
+  VALUE_0540 = 540,
+  VALUE_0541 = 541,
+  VALUE_0542 = 542,
+  VALUE_0543 = 543,
+  VALUE_0544 = 544,
+  VALUE_0545 = 545,
+  VALUE_0546 = 546,
+  VALUE_0547 = 547,
+  VALUE_0548 = 548,
+  VALUE_0549 = 549,
+  VALUE_0550 = 550,
+  VALUE_0551 = 551,
+  VALUE_0552 = 552,
+  VALUE_0553 = 553,
+  VALUE_0554 = 554,
+  VALUE_0555 = 555,
+  VALUE_0556 = 556,
+  VALUE_0557 = 557,
+  VALUE_0558 = 558,
+  VALUE_0559 = 559,
+  VALUE_0560 = 560,
+  VALUE_0561 = 561,
+  VALUE_0562 = 562,
+  VALUE_0563 = 563,
+  VALUE_0564 = 564,
+  VALUE_0565 = 565,
+  VALUE_0566 = 566,
+  VALUE_0567 = 567,
+  VALUE_0568 = 568,
+  VALUE_0569 = 569,
+  VALUE_0570 = 570,
+  VALUE_0571 = 571,
+  VALUE_0572 = 572,
+  VALUE_0573 = 573,
+  VALUE_0574 = 574,
+  VALUE_0575 = 575,
+  VALUE_0576 = 576,
+  VALUE_0577 = 577,
+  VALUE_0578 = 578,
+  VALUE_0579 = 579,
+  VALUE_0580 = 580,
+  VALUE_0581 = 581,
+  VALUE_0582 = 582,
+  VALUE_0583 = 583,
+  VALUE_0584 = 584,
+  VALUE_0585 = 585,
+  VALUE_0586 = 586,
+  VALUE_0587 = 587,
+  VALUE_0588 = 588,
+  VALUE_0589 = 589,
+  VALUE_0590 = 590,
+  VALUE_0591 = 591,
+  VALUE_0592 = 592,
+  VALUE_0593 = 593,
+  VALUE_0594 = 594,
+  VALUE_0595 = 595,
+  VALUE_0596 = 596,
+  VALUE_0597 = 597,
+  VALUE_0598 = 598,
+  VALUE_0599 = 599,
+  VALUE_0600 = 600,
+  VALUE_0601 = 601,
+  VALUE_0602 = 602,
+  VALUE_0603 = 603,
+  VALUE_0604 = 604,
+  VALUE_0605 = 605,
+  VALUE_0606 = 606,
+  VALUE_0607 = 607,
+  VALUE_0608 = 608,
+  VALUE_0609 = 609,
+  VALUE_0610 = 610,
+  VALUE_0611 = 611,
+  VALUE_0612 = 612,
+  VALUE_0613 = 613,
+  VALUE_0614 = 614,
+  VALUE_0615 = 615,
+  VALUE_0616 = 616,
+  VALUE_0617 = 617,
+  VALUE_0618 = 618,
+  VALUE_0619 = 619,
+  VALUE_0620 = 620,
+  VALUE_0621 = 621,
+  VALUE_0622 = 622,
+  VALUE_0623 = 623,
+  VALUE_0624 = 624,
+  VALUE_0625 = 625,
+  VALUE_0626 = 626,
+  VALUE_0627 = 627,
+  VALUE_0628 = 628,
+  VALUE_0629 = 629,
+  VALUE_0630 = 630,
+  VALUE_0631 = 631,
+  VALUE_0632 = 632,
+  VALUE_0633 = 633,
+  VALUE_0634 = 634,
+  VALUE_0635 = 635,
+  VALUE_0636 = 636,
+  VALUE_0637 = 637,
+  VALUE_0638 = 638,
+  VALUE_0639 = 639,
+  VALUE_0640 = 640,
+  VALUE_0641 = 641,
+  VALUE_0642 = 642,
+  VALUE_0643 = 643,
+  VALUE_0644 = 644,
+  VALUE_0645 = 645,
+  VALUE_0646 = 646,
+  VALUE_0647 = 647,
+  VALUE_0648 = 648,
+  VALUE_0649 = 649,
+  VALUE_0650 = 650,
+  VALUE_0651 = 651,
+  VALUE_0652 = 652,
+  VALUE_0653 = 653,
+  VALUE_0654 = 654,
+  VALUE_0655 = 655,
+  VALUE_0656 = 656,
+  VALUE_0657 = 657,
+  VALUE_0658 = 658,
+  VALUE_0659 = 659,
+  VALUE_0660 = 660,
+  VALUE_0661 = 661,
+  VALUE_0662 = 662,
+  VALUE_0663 = 663,
+  VALUE_0664 = 664,
+  VALUE_0665 = 665,
+  VALUE_0666 = 666,
+  VALUE_0667 = 667,
+  VALUE_0668 = 668,
+  VALUE_0669 = 669,
+  VALUE_0670 = 670,
+  VALUE_0671 = 671,
+  VALUE_0672 = 672,
+  VALUE_0673 = 673,
+  VALUE_0674 = 674,
+  VALUE_0675 = 675,
+  VALUE_0676 = 676,
+  VALUE_0677 = 677,
+  VALUE_0678 = 678,
+  VALUE_0679 = 679,
+  VALUE_0680 = 680,
+  VALUE_0681 = 681,
+  VALUE_0682 = 682,
+  VALUE_0683 = 683,
+  VALUE_0684 = 684,
+  VALUE_0685 = 685,
+  VALUE_0686 = 686,
+  VALUE_0687 = 687,
+  VALUE_0688 = 688,
+  VALUE_0689 = 689,
+  VALUE_0690 = 690,
+  VALUE_0691 = 691,
+  VALUE_0692 = 692,
+  VALUE_0693 = 693,
+  VALUE_0694 = 694,
+  VALUE_0695 = 695,
+  VALUE_0696 = 696,
+  VALUE_0697 = 697,
+  VALUE_0698 = 698,
+  VALUE_0699 = 699,
+  VALUE_0700 = 700,
+  VALUE_0701 = 701,
+  VALUE_0702 = 702,
+  VALUE_0703 = 703,
+  VALUE_0704 = 704,
+  VALUE_0705 = 705,
+  VALUE_0706 = 706,
+  VALUE_0707 = 707,
+  VALUE_0708 = 708,
+  VALUE_0709 = 709,
+  VALUE_0710 = 710,
+  VALUE_0711 = 711,
+  VALUE_0712 = 712,
+  VALUE_0713 = 713,
+  VALUE_0714 = 714,
+  VALUE_0715 = 715,
+  VALUE_0716 = 716,
+  VALUE_0717 = 717,
+  VALUE_0718 = 718,
+  VALUE_0719 = 719,
+  VALUE_0720 = 720,
+  VALUE_0721 = 721,
+  VALUE_0722 = 722,
+  VALUE_0723 = 723,
+  VALUE_0724 = 724,
+  VALUE_0725 = 725,
+  VALUE_0726 = 726,
+  VALUE_0727 = 727,
+  VALUE_0728 = 728,
+  VALUE_0729 = 729,
+  VALUE_0730 = 730,
+  VALUE_0731 = 731,
+  VALUE_0732 = 732,
+  VALUE_0733 = 733,
+  VALUE_0734 = 734,
+  VALUE_0735 = 735,
+  VALUE_0736 = 736,
+  VALUE_0737 = 737,
+  VALUE_0738 = 738,
+  VALUE_0739 = 739,
+  VALUE_0740 = 740,
+  VALUE_0741 = 741,
+  VALUE_0742 = 742,
+  VALUE_0743 = 743,
+  VALUE_0744 = 744,
+  VALUE_0745 = 745,
+  VALUE_0746 = 746,
+  VALUE_0747 = 747,
+  VALUE_0748 = 748,
+  VALUE_0749 = 749,
+  VALUE_0750 = 750,
+  VALUE_0751 = 751,
+  VALUE_0752 = 752,
+  VALUE_0753 = 753,
+  VALUE_0754 = 754,
+  VALUE_0755 = 755,
+  VALUE_0756 = 756,
+  VALUE_0757 = 757,
+  VALUE_0758 = 758,
+  VALUE_0759 = 759,
+  VALUE_0760 = 760,
+  VALUE_0761 = 761,
+  VALUE_0762 = 762,
+  VALUE_0763 = 763,
+  VALUE_0764 = 764,
+  VALUE_0765 = 765,
+  VALUE_0766 = 766,
+  VALUE_0767 = 767,
+  VALUE_0768 = 768,
+  VALUE_0769 = 769,
+  VALUE_0770 = 770,
+  VALUE_0771 = 771,
+  VALUE_0772 = 772,
+  VALUE_0773 = 773,
+  VALUE_0774 = 774,
+  VALUE_0775 = 775,
+  VALUE_0776 = 776,
+  VALUE_0777 = 777,
+  VALUE_0778 = 778,
+  VALUE_0779 = 779,
+  VALUE_0780 = 780,
+  VALUE_0781 = 781,
+  VALUE_0782 = 782,
+  VALUE_0783 = 783,
+  VALUE_0784 = 784,
+  VALUE_0785 = 785,
+  VALUE_0786 = 786,
+  VALUE_0787 = 787,
+  VALUE_0788 = 788,
+  VALUE_0789 = 789,
+  VALUE_0790 = 790,
+  VALUE_0791 = 791,
+  VALUE_0792 = 792,
+  VALUE_0793 = 793,
+  VALUE_0794 = 794,
+  VALUE_0795 = 795,
+  VALUE_0796 = 796,
+  VALUE_0797 = 797,
+  VALUE_0798 = 798,
+  VALUE_0799 = 799,
+  VALUE_0800 = 800,
+  VALUE_0801 = 801,
+  VALUE_0802 = 802,
+  VALUE_0803 = 803,
+  VALUE_0804 = 804,
+  VALUE_0805 = 805,
+  VALUE_0806 = 806,
+  VALUE_0807 = 807,
+  VALUE_0808 = 808,
+  VALUE_0809 = 809,
+  VALUE_0810 = 810,
+  VALUE_0811 = 811,
+  VALUE_0812 = 812,
+  VALUE_0813 = 813,
+  VALUE_0814 = 814,
+  VALUE_0815 = 815,
+  VALUE_0816 = 816,
+  VALUE_0817 = 817,
+  VALUE_0818 = 818,
+  VALUE_0819 = 819,
+  VALUE_0820 = 820,
+  VALUE_0821 = 821,
+  VALUE_0822 = 822,
+  VALUE_0823 = 823,
+  VALUE_0824 = 824,
+  VALUE_0825 = 825,
+  VALUE_0826 = 826,
+  VALUE_0827 = 827,
+  VALUE_0828 = 828,
+  VALUE_0829 = 829,
+  VALUE_0830 = 830,
+  VALUE_0831 = 831,
+  VALUE_0832 = 832,
+  VALUE_0833 = 833,
+  VALUE_0834 = 834,
+  VALUE_0835 = 835,
+  VALUE_0836 = 836,
+  VALUE_0837 = 837,
+  VALUE_0838 = 838,
+  VALUE_0839 = 839,
+  VALUE_0840 = 840,
+  VALUE_0841 = 841,
+  VALUE_0842 = 842,
+  VALUE_0843 = 843,
+  VALUE_0844 = 844,
+  VALUE_0845 = 845,
+  VALUE_0846 = 846,
+  VALUE_0847 = 847,
+  VALUE_0848 = 848,
+  VALUE_0849 = 849,
+  VALUE_0850 = 850,
+  VALUE_0851 = 851,
+  VALUE_0852 = 852,
+  VALUE_0853 = 853,
+  VALUE_0854 = 854,
+  VALUE_0855 = 855,
+  VALUE_0856 = 856,
+  VALUE_0857 = 857,
+  VALUE_0858 = 858,
+  VALUE_0859 = 859,
+  VALUE_0860 = 860,
+  VALUE_0861 = 861,
+  VALUE_0862 = 862,
+  VALUE_0863 = 863,
+  VALUE_0864 = 864,
+  VALUE_0865 = 865,
+  VALUE_0866 = 866,
+  VALUE_0867 = 867,
+  VALUE_0868 = 868,
+  VALUE_0869 = 869,
+  VALUE_0870 = 870,
+  VALUE_0871 = 871,
+  VALUE_0872 = 872,
+  VALUE_0873 = 873,
+  VALUE_0874 = 874,
+  VALUE_0875 = 875,
+  VALUE_0876 = 876,
+  VALUE_0877 = 877,
+  VALUE_0878 = 878,
+  VALUE_0879 = 879,
+  VALUE_0880 = 880,
+  VALUE_0881 = 881,
+  VALUE_0882 = 882,
+  VALUE_0883 = 883,
+  VALUE_0884 = 884,
+  VALUE_0885 = 885,
+  VALUE_0886 = 886,
+  VALUE_0887 = 887,
+  VALUE_0888 = 888,
+  VALUE_0889 = 889,
+  VALUE_0890 = 890,
+  VALUE_0891 = 891,
+  VALUE_0892 = 892,
+  VALUE_0893 = 893,
+  VALUE_0894 = 894,
+  VALUE_0895 = 895,
+  VALUE_0896 = 896,
+  VALUE_0897 = 897,
+  VALUE_0898 = 898,
+  VALUE_0899 = 899,
+  VALUE_0900 = 900,
+  VALUE_0901 = 901,
+  VALUE_0902 = 902,
+  VALUE_0903 = 903,
+  VALUE_0904 = 904,
+  VALUE_0905 = 905,
+  VALUE_0906 = 906,
+  VALUE_0907 = 907,
+  VALUE_0908 = 908,
+  VALUE_0909 = 909,
+  VALUE_0910 = 910,
+  VALUE_0911 = 911,
+  VALUE_0912 = 912,
+  VALUE_0913 = 913,
+  VALUE_0914 = 914,
+  VALUE_0915 = 915,
+  VALUE_0916 = 916,
+  VALUE_0917 = 917,
+  VALUE_0918 = 918,
+  VALUE_0919 = 919,
+  VALUE_0920 = 920,
+  VALUE_0921 = 921,
+  VALUE_0922 = 922,
+  VALUE_0923 = 923,
+  VALUE_0924 = 924,
+  VALUE_0925 = 925,
+  VALUE_0926 = 926,
+  VALUE_0927 = 927,
+  VALUE_0928 = 928,
+  VALUE_0929 = 929,
+  VALUE_0930 = 930,
+  VALUE_0931 = 931,
+  VALUE_0932 = 932,
+  VALUE_0933 = 933,
+  VALUE_0934 = 934,
+  VALUE_0935 = 935,
+  VALUE_0936 = 936,
+  VALUE_0937 = 937,
+  VALUE_0938 = 938,
+  VALUE_0939 = 939,
+  VALUE_0940 = 940,
+  VALUE_0941 = 941,
+  VALUE_0942 = 942,
+  VALUE_0943 = 943,
+  VALUE_0944 = 944,
+  VALUE_0945 = 945,
+  VALUE_0946 = 946,
+  VALUE_0947 = 947,
+  VALUE_0948 = 948,
+  VALUE_0949 = 949,
+  VALUE_0950 = 950,
+  VALUE_0951 = 951,
+  VALUE_0952 = 952,
+  VALUE_0953 = 953,
+  VALUE_0954 = 954,
+  VALUE_0955 = 955,
+  VALUE_0956 = 956,
+  VALUE_0957 = 957,
+  VALUE_0958 = 958,
+  VALUE_0959 = 959,
+  VALUE_0960 = 960,
+  VALUE_0961 = 961,
+  VALUE_0962 = 962,
+  VALUE_0963 = 963,
+  VALUE_0964 = 964,
+  VALUE_0965 = 965,
+  VALUE_0966 = 966,
+  VALUE_0967 = 967,
+  VALUE_0968 = 968,
+  VALUE_0969 = 969,
+  VALUE_0970 = 970,
+  VALUE_0971 = 971,
+  VALUE_0972 = 972,
+  VALUE_0973 = 973,
+  VALUE_0974 = 974,
+  VALUE_0975 = 975,
+  VALUE_0976 = 976,
+  VALUE_0977 = 977,
+  VALUE_0978 = 978,
+  VALUE_0979 = 979,
+  VALUE_0980 = 980,
+  VALUE_0981 = 981,
+  VALUE_0982 = 982,
+  VALUE_0983 = 983,
+  VALUE_0984 = 984,
+  VALUE_0985 = 985,
+  VALUE_0986 = 986,
+  VALUE_0987 = 987,
+  VALUE_0988 = 988,
+  VALUE_0989 = 989,
+  VALUE_0990 = 990,
+  VALUE_0991 = 991,
+  VALUE_0992 = 992,
+  VALUE_0993 = 993,
+  VALUE_0994 = 994,
+  VALUE_0995 = 995,
+  VALUE_0996 = 996,
+  VALUE_0997 = 997,
+  VALUE_0998 = 998,
+  VALUE_0999 = 999,
+  VALUE_1000 = 1000,
+  VALUE_1001 = 1001,
+} (hs.pseudoenum = "thriftenum")
diff --git a/test/if/g.thrift b/test/if/g.thrift
new file mode 100644
--- /dev/null
+++ b/test/if/g.thrift
@@ -0,0 +1,14 @@
+// Copyright (c) Facebook, Inc. and its affiliates.
+
+# @nolint
+
+# field/type are entirely ignored due to hs.hidden annotation
+struct Foo {
+  1: some_type bar (hs.hidden);
+  2: some_type bar (hs.lazy, hs.hidden);
+  3: i64 bar (hs.hidden);
+}
+
+service _Service {
+  void doNothing(1: Foo f);
+}
diff --git a/tests/if/A.thrift b/tests/if/A.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/A.thrift
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/B.thrift"
+include "if/C.thrift"
+include "if/D.thrift"
+include "if/E.thrift"
+
+# INCLUSION HIERARCHY
+#
+#        A
+#      /   \
+#     B     C
+#   /   \ /
+#  D     E
+
+struct A {
+  1: B.B bThing = {"dThing": {}, "eThing": {}, "b2Thing": B.B2.X};
+  2: C.C cThing;
+}
+
+const D.D dstruct = {};
diff --git a/tests/if/B.thrift b/tests/if/B.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/B.thrift
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/D.thrift"
+include "if/E.thrift"
+
+# INCLUSION HIERARCHY
+#
+#        B
+#      /   \
+#     D     E
+
+struct B {
+  1: D.D dThing;
+  2: E.E eThing;
+  3: B2 b2Thing;
+}
+
+enum B2 {
+  X = 0,
+  Y = 1,
+}
diff --git a/tests/if/C.thrift b/tests/if/C.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/C.thrift
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/E.thrift"
+
+# INCLUSION HIERARCHY
+#
+#        C
+#        |
+#        E
+
+struct C {
+  1: E.E eThing;
+}
diff --git a/tests/if/D.thrift b/tests/if/D.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/D.thrift
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef i64 (hs.type = "Int") Int
+
+const Int int_val = 123;
+
+struct D {
+  1: Int dInt = int_val;
+}
diff --git a/tests/if/E.thrift b/tests/if/E.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/E.thrift
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct E {
+  1: string eString;
+}
diff --git a/tests/if/EnumConst.thrift b/tests/if/EnumConst.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/EnumConst.thrift
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum X {
+  A = 0,
+  B = 1,
+  C = 2,
+  D = 3,
+  E = 4,
+}
+
+const X idConst = D;
+
+const X intConst = 2;
+
+enum Y {
+}
+
+enum Z {
+  A = 2,
+  B = 3,
+}
+
+const Z zconst = Z.A;
diff --git a/tests/if/bar.thrift b/tests/if/bar.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/bar.thrift
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/foo.thrift"
+
+typedef foo.Bar NewBar
+typedef list<foo.HsString> (hs.type = "Vector") HsStringVector
diff --git a/tests/if/baz.thrift b/tests/if/baz.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/baz.thrift
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/bar.thrift"
+
+struct Baz {
+  1: bar.NewBar theBar;
+  2: bar.HsStringVector theVector;
+}
diff --git a/tests/if/constants.thrift b/tests/if/constants.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/constants.thrift
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+const i32 i32Const = 99;
+
+const bool boolConst = 0;
+
+const float floatConst = 0.5;
+
+enum X {
+  A = 0,
+  B = 1,
+  C = 2,
+  D = 3,
+  E = 4,
+}
+
+const X enumNum = 1;
+
+const X enumConst = D;
+
+const list<X> enumList = [A, B, C, D];
+
+const map<i64, string> mapConst = {0: 'zero', 1: 'one'};
+
+struct Foo {
+  1: optional i32 foo;
+  2: string bar = "X";
+}
+
+const Foo fooConst = {'bar': 'hello world'};
+const Foo partial = {};
+
+typedef i64 Id (hs.newtype)
+
+const Id idConst = 12345;
+
+const list_Id_1134 idVect = [1, 2, 3, 4, 5];
+
+const list_i64_5078 i64VectS = [1, 2, 3, 4, 5];
+
+const map_i64_string_4289 hashmapConst = {0: 'zero', 1: 'one'};
+
+const string_9126 strConst = "string";
+
+const string_9425 byteStrConst = "string";
+
+const i64 negative = -1;
+
+struct NagativeFields {
+  1: required i64 u = negative;
+  2: optional i64 v = -1;
+  3: i64 w = -2;
+}
+
+union NonEmpty {
+  1: i64 ne;
+} (hs.nonempty)
+
+const bool trueConst = true;
+const bool falseConst = false;
+
+// The following were automatically generated and may benefit from renaming.
+typedef list<Id> (hs.type = "Vector") list_Id_1134
+typedef list<i64> (hs.type = "VectorStorable") list_i64_5078
+typedef map<i64, string> (hs.type = "HashMap") map_i64_string_4289
+typedef string (hs.type = "String") string_9126
+typedef string (hs.type = "ByteString") string_9425
diff --git a/tests/if/duplicate.thrift b/tests/if/duplicate.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/duplicate.thrift
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct X {
+  1: string name;
+  2: i64 payload;
+}
+
+struct Y {
+  1: string name;
+  2: bool payload;
+}
diff --git a/tests/if/enum.thrift b/tests/if/enum.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/enum.thrift
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum UnsortedEnum {
+  G = 7,
+  A = 1,
+  D = 4,
+  E = 5,
+  C = 3,
+  B = 2,
+}
+
+enum EnumWithNounknown {
+  U = 0,
+  V = 1,
+} (hs.nounknown)
+
+enum PerfectEnum {
+  W = 0,
+  X = 1,
+  Y = 2,
+  Z = 3,
+}
diff --git a/tests/if/enum_dependee.thrift b/tests/if/enum_dependee.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/enum_dependee.thrift
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/enum.thrift"
+
+// Const of typedef'd enum that was imported from another file
+typedef enum.PerfectEnum PerfectEnum
+const enum.PerfectEnum BOTH_QUALIFIED = enum.PerfectEnum.W;
+const PerfectEnum UNQUALIFIED = PerfectEnum.X;
+const enum.PerfectEnum TYPE_QUALIFIED = PerfectEnum.Y;
+const PerfectEnum IDENT_QUALIFIED = enum.PerfectEnum.Z;
diff --git a/tests/if/exception.thrift b/tests/if/exception.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/exception.thrift
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+exception X {
+  1: string reason;
+}
+
+safe transient client exception Y {
+  1: string reason;
+}
diff --git a/tests/if/flags.thrift b/tests/if/flags.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/flags.thrift
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+const i64 intConst = 100;
+const i64 int2 = intConst;
+
+const map<string, i64> mapConst = {"a": 1, "b": 2};
+
+const set<i64> setConst = [1, 2, 3];
diff --git a/tests/if/foo.thrift b/tests/if/foo.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/foo.thrift
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef i64 X
+
+struct Foo {
+  1: optional i64 foo1;
+  2: required bool foo2;
+  3: Bar foo3;
+  4: X foo4;
+  5: list_i64_6540 foo5;
+  6: list_i64_2857 foo6;
+}
+
+struct Bar {
+  -1: i32 bar1;
+  1: string bar2;
+}
+
+enum Numbers {
+  Zero = 0,
+  One = 1,
+  Three = 3,
+  Four = 4,
+  Five = 5,
+  Seven = 7,
+}
+
+const i32 i32Const = 1;
+
+const bool boolConst = 0;
+
+const Foo fooConst = {
+  "foo2": 1,
+  "foo3": {"bar1": 99, "bar2": "hello world"},
+  "foo4": 0,
+  "foo5": [1, 2, 3],
+  "foo6": [1, 2, 3],
+};
+
+const map<i32, list<i32>> mapConst = {0: [], 1: [1, 2, 3]};
+
+typedef map<i64, i64> (hs.type = "HashMap") NewtypeMap (hs.newtype)
+
+typedef string (hs.type = "String") HsString
+
+// The following were automatically generated and may benefit from renaming.
+typedef list<i64> (hs.type = "VectorStorable") list_i64_2857
+typedef list<i64> (hs.type = "Vector") list_i64_6540
diff --git a/tests/if/hasfield.thrift b/tests/if/hasfield.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/hasfield.thrift
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef i64 X
+
+struct Foo {
+  1: optional i64 foo1;
+  2: bool foo2;
+  3: Bar foo3;
+  4: X foo4;
+  5: list_i64_6026 foo5;
+  7: i64 foo_foo1;
+}
+
+struct Bar {
+  1: i32 bar1;
+  2: string bar2;
+  3: optional i64 foo1;
+  4: i64 foo2;
+}
+
+struct Huge {
+  1: optional i64 foo1;
+  2: bool foo2;
+  3: Bar foo3;
+  4: X foo4;
+  5: list_i64_6026 foo5;
+  7: i64 foo_foo1;
+  10: i64 huge10;
+  11: i64 huge11;
+  12: i64 huge12;
+  13: i64 huge13;
+  14: i64 huge14;
+  15: i64 huge15;
+  16: i64 huge16;
+  17: i64 huge17;
+  18: i64 huge18;
+  19: i64 huge19;
+  20: i64 huge20;
+  21: i64 huge21;
+  22: i64 huge22;
+  23: i64 huge23;
+  24: i64 huge24;
+  25: i64 huge25;
+  26: i64 huge26;
+  27: i64 huge27;
+  28: i64 huge28;
+  29: i64 huge29;
+  30: i64 huge30;
+  31: i64 huge31;
+  32: i64 huge32;
+  33: i64 huge33;
+  34: i64 huge34;
+  35: i64 huge35;
+  36: i64 huge36;
+  37: i64 huge37;
+  38: i64 huge38;
+  39: i64 huge39;
+  40: i64 huge40;
+  41: i64 huge41;
+  42: i64 huge42;
+  43: i64 huge43;
+  44: i64 huge44;
+  45: i64 huge45;
+  46: i64 huge46;
+  47: i64 huge47;
+  48: i64 huge48;
+  49: i64 huge49;
+  50: i64 huge50;
+  51: i64 huge51;
+  52: i64 huge52;
+  53: i64 huge53;
+  54: i64 huge54;
+  55: i64 huge55;
+  56: i64 huge56;
+  57: i64 huge57;
+  58: i64 huge58;
+  59: i64 huge59;
+  60: i64 huge60;
+  61: i64 huge61;
+  62: i64 huge62;
+  63: i64 huge63;
+  64: i64 huge64;
+  65: i64 huge65;
+  66: i64 huge66;
+  67: i64 huge67;
+  68: i64 huge68;
+  69: i64 huge69;
+  70: i64 huge70;
+  71: i64 huge71;
+  72: i64 huge72;
+  73: i64 huge73;
+  74: i64 huge74;
+  75: i64 huge75;
+  76: i64 huge76;
+  77: i64 huge77;
+  78: i64 huge78;
+  79: i64 huge79;
+}
+
+// The following were automatically generated and may benefit from renaming.
+typedef list<i64> (hs.type = "Vector") list_i64_6026
diff --git a/tests/if/hs_prefix.thrift b/tests/if/hs_prefix.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/hs_prefix.thrift
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum E {
+  A = 0,
+  B = 1,
+} (hs.nounknown)
+
+enum PrefixedE {
+  A = 0,
+  B = 1,
+} (hs.prefix = "PE_")
+
+struct S {
+  1: i64 A;
+  2: E B = E.B;
+}
+
+struct PrefixedS {
+  1: i64 A;
+  3: PrefixedE B = PrefixedE.B;
+} (hs.prefix = "ps_")
+
+union U {
+  1: E A;
+  2: S B;
+}
+
+union PrefixedU {
+  1: PrefixedE A;
+  2: PrefixedS B;
+} (hs.prefix = "PU_")
diff --git a/tests/if/hs_test.thrift b/tests/if/hs_test.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/hs_test.thrift
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+hs_include "if/hs_test_instances.hs"
+
+typedef i64 X (hs.newtype)
+typedef X Y
+typedef Y Z (hs.newtype)
+
+struct Foo {
+  5: i32 bar;
+  1: i32 baz;
+}
+
+union tUnion {
+  1: string StringOption;
+  2: i64 I64Option;
+  3: Foo FooOption;
+}
+
+struct TestStruct {
+  1: required bool f_bool;
+  2: byte f_byte;
+  3: double f_double;
+  4: i16 f_i16 = 5;
+  5: i32 f_i32;
+  6: i64 f_i64;
+  7: float f_float;
+  8: list<i16> f_list;
+  9: map<i16, i32> f_map = {1: 2};
+  10: string f_text;
+  11: set<byte> f_set;
+  12: optional i32 o_i32;
+  99: Foo foo = {"bar": 1, "baz": 2};
+  13: map_Number_i64_1522 f_hash_map;
+  14: Z f_newtype;
+  15: tUnion f_union;
+  16: string_5858 f_string;
+  17: binary f_binary;
+  18: optional X f_optional_newtype;
+  19: map<i32, bool> bool_map;
+  20: list<bool> bool_list;
+  21: list_i64_7708 i64_vec;
+  22: list_i64_1894 i64_svec;
+  23: map<binary, i64> binary_key;
+  24: string_1484 f_bytestring;
+}
+
+enum Number {
+  One = 1,
+  Two = 2,
+  Three = 3,
+}
+
+enum Perfect {
+  A = 0,
+  B = 1,
+  C = 2,
+}
+
+enum Void {
+}
+
+// The following were automatically generated and may benefit from renaming.
+typedef list<i64> (hs.type = "VectorStorable") list_i64_1894
+typedef list<i64> (hs.type = "Vector") list_i64_7708
+typedef map<Number, i64> (hs.type = "HashMap") map_Number_i64_1522
+typedef string (hs.type = "ByteString") string_1484
+typedef string (hs.type = "String") string_5858
diff --git a/tests/if/hs_test_instances.hs b/tests/if/hs_test_instances.hs
new file mode 100644
--- /dev/null
+++ b/tests/if/hs_test_instances.hs
@@ -0,0 +1,65 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+-- @nolint
+import qualified Test.QuickCheck as QuickCheck
+import qualified Data.Vector as Vector
+import qualified Data.Vector.Storable as VectorStorable
+import Prelude ((/=), ($))
+
+instance QuickCheck.Arbitrary Foo where
+  arbitrary = Foo <$> QuickCheck.arbitrary <*> QuickCheck.arbitrary
+
+instance QuickCheck.Arbitrary TestStruct where
+  arbitrary = TestStruct
+              <$> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> (Map.fromList <$> QuickCheck.arbitrary)
+              <*> arbitraryText
+              <*> (Set.fromList <$> QuickCheck.arbitrary)
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> (HashMap.fromList <$> QuickCheck.arbitrary)
+              <*> ((Z . X) <$> QuickCheck.arbitrary)
+              <*> QuickCheck.arbitrary
+              <*> arbitraryString
+              <*> arbitraryBS
+              <*> (Prelude.fmap X <$> QuickCheck.arbitrary)
+              <*> QuickCheck.arbitrary
+              <*> QuickCheck.arbitrary
+              <*> (Vector.fromList <$> QuickCheck.arbitrary)
+              <*> (VectorStorable.fromList <$> QuickCheck.arbitrary)
+              <*> arbitraryBSMap
+              <*> (Text.encodeUtf8 <$> arbitraryText)
+
+instance QuickCheck.Arbitrary Number where
+  arbitrary = QuickCheck.oneof $ Prelude.map Prelude.pure
+              [Number_One, Number_Two, Number_Three]
+
+instance QuickCheck.Arbitrary TUnion where
+  arbitrary = QuickCheck.oneof
+              [ TUnion_StringOption <$> arbitraryText
+              , TUnion_I64Option <$> QuickCheck.arbitrary
+              , TUnion_FooOption <$> QuickCheck.arbitrary
+              , Prelude.pure TUnion_EMPTY
+              ]
+
+arbitraryString :: QuickCheck.Gen Prelude.String
+arbitraryString = Prelude.filter (/= '\NUL') <$> QuickCheck.arbitrary
+
+arbitraryText :: QuickCheck.Gen Text.Text
+arbitraryText = Text.pack <$> arbitraryString
+
+arbitraryBS :: QuickCheck.Gen ByteString.ByteString
+arbitraryBS = ByteString.pack <$> QuickCheck.arbitrary
+
+arbitraryBSMap
+  :: QuickCheck.Arbitrary a => QuickCheck.Gen (Map.Map ByteString.ByteString a)
+arbitraryBSMap =
+  Map.fromList . Prelude.map (\(k,v) -> (ByteString.pack k, v)) <$>
+  QuickCheck.arbitrary
diff --git a/tests/if/huge.hs b/tests/if/huge.hs
new file mode 100644
--- /dev/null
+++ b/tests/if/huge.hs
@@ -0,0 +1,6 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+-- @nolint
+instance Prelude.Bounded HsInclude where
+  minBound = hsInclude2_get Prelude.undefined
+  maxBound = hsconst
diff --git a/tests/if/huge.thrift b/tests/if/huge.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/huge.thrift
@@ -0,0 +1,100 @@
+// Copyright (c) Facebook, Inc. and its affiliates.
+
+# @nolint
+
+# This file is gonna be uge
+
+# HIERARCHY OF STUFF
+#
+#     A       G H I J K L M N O P Q R S T U V W
+#    / \                                     / \
+#   B   C                                   X   Y
+#      / \                                 /
+#     D   E                               Z -> W
+#      \ / \
+#       F  foo
+#           |
+#          bar
+
+hs_include "if/huge.hs"
+
+struct A {
+  1: B b;
+  2: C c;
+}
+
+struct B {}
+
+struct C {
+  1: D d;
+  2: E e;
+}
+
+enum F {
+  F = 0,
+}
+
+struct D {
+  1: F f;
+}
+
+const F bar = F.F;
+const list<F> foo = [bar];
+
+struct E {
+  1: list<F> f = foo;
+}
+
+enum G {
+  G = 0,
+}
+enum H {
+  H = 0,
+}
+struct I {}
+struct J {}
+typedef i64 K
+typedef i64 L
+enum M {
+  M = 0,
+}
+enum N {
+  N = 0,
+}
+struct O {}
+struct P {}
+typedef i64 Q
+typedef i64 R
+enum S {
+  S = 0,
+}
+enum T {
+  T = 0,
+}
+struct U {}
+struct V {}
+
+# This stuff is mututally recursive
+typedef map<Y, X> W
+
+typedef Z X
+
+enum Y {
+  Y = 0,
+}
+
+struct Z {
+  1: W w;
+}
+
+service Service {
+  void weNeedThis(1: i64 x);
+  void weDontNeedThis(1: string x);
+}
+
+struct HsInclude {}
+struct HsInclude2 {
+  1: HsInclude get;
+}
+
+const HsInclude hsconst = {};
diff --git a/tests/if/instances.hs b/tests/if/instances.hs
new file mode 100644
--- /dev/null
+++ b/tests/if/instances.hs
@@ -0,0 +1,13 @@
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+-- @nolint
+{-# LANGUAGE RecordWildCards #-}
+import Data.Semigroup (Semigroup(..))
+import Prelude ((++), Monoid(..))
+
+instance Semigroup X where
+  (<>) = mappend
+
+instance Prelude.Monoid X where
+  mempty = X [] []
+  mappend X{..} (X y1 y2) = X (x_intList ++ y1) (x_stringList ++ y2)
diff --git a/tests/if/map.thrift b/tests/if/map.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/map.thrift
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef map<byte, string> Map
+
+typedef string KeyType (hs.newtype)
+
+struct X {
+  1: map<i32, string> intMap;
+  2: Map otherMap;
+  3: optional map<i64, i64> optMap;
+  4: map<i64, map<i64, i64>> nestedMap;
+  5: list<map<i32, i32>> listMap;
+  6: map_Y_string_2031 structMap;
+  7: map<KeyType, i64> newtypeMap;
+} (hs.prefix = "")
+
+struct Y {
+  1: i64 y;
+}
+
+// The following were automatically generated and may benefit from renaming.
+typedef map<Y, string> (hs.type = "HashMap") map_Y_string_2031
diff --git a/tests/if/messed_up_case.thrift b/tests/if/messed_up_case.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/messed_up_case.thrift
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef i64 (hs.type = "Int") intType
+
+const string Str = "";
+
+const string Str2 = Str;
+
+enum numbers {
+  one = 0,
+  two = 1,
+  three = 2,
+}
+
+struct foo {
+  1: intType Field;
+} (hs.prefix = "")
+
+const numbers numberThing = one;
+const numbers otherNumberThing = 1;
+
+const foo fooConst = {"Field": 999};
diff --git a/tests/if/monoid.thrift b/tests/if/monoid.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/monoid.thrift
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+hs_include "if/instances.hs"
+
+struct X {
+  1: list<i64> intList;
+  2: list<string> stringList;
+}
diff --git a/tests/if/namespace.thrift b/tests/if/namespace.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/namespace.thrift
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+include "if/namespace_included.thrift"
+
+namespace hs Thrift.Test
+
+struct X {
+  1: i64 intField;
+}
+
+typedef namespace_included.X Y
+typedef map<namespace_included.Y, list<namespace_included.Z>> Z
diff --git a/tests/if/namespace_included.thrift b/tests/if/namespace_included.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/namespace_included.thrift
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+namespace hs Thrift.Test.Internal
+
+struct X {
+  1: i64 intField;
+}
+
+enum Y {
+  Y1 = 0,
+}
+
+union Z {
+  1: X x;
+  2: Y y;
+}
diff --git a/tests/if/package.thrift b/tests/if/package.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/package.thrift
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+package "meta.com/thrift/test"
+
+struct X {
+  1: i64 intField;
+}
diff --git a/tests/if/parens.thrift b/tests/if/parens.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/parens.thrift
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct X {
+  # both Y and Int include <$> in their type parsers, so we need to insert parens
+  # around these expressions
+  1: map<Y, i64_4156> foo;
+}
+
+enum Y {
+  A = 0,
+  B = 1,
+  C = 2,
+}
+
+// The following were automatically generated and may benefit from renaming.
+typedef i64 (hs.type = "Int") i64_4156
diff --git a/tests/if/pseudoenum.thrift b/tests/if/pseudoenum.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/pseudoenum.thrift
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum PerfectEnum {
+  W = 0,
+  X = 1,
+  Y = 2,
+  Z = 3,
+} (hs.pseudoenum = "thriftenum")
diff --git a/tests/if/scoped_enums.thrift b/tests/if/scoped_enums.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/scoped_enums.thrift
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+enum X {
+  A = 1,
+}
+
+enum Y {
+  A = -1,
+}
+
+enum Z {
+  A = 9,
+} (hs.prefix = "a_")
+
+const X x = X.A;
+const X x2 = A;
+
+const Y y = Y.A;
+
+const Z z = Z.A;
+
+enum A {
+  A = 1,
+} (hs.pseudoenum)
+
+const A pseudo = A.A;
+
+enum B {
+  B = 2,
+} (hs.pseudoenum, hs.prefix = 'enum_')
+
+const B prefix = B.B;
diff --git a/tests/if/service.thrift b/tests/if/service.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/service.thrift
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct Z {
+  1: string name;
+}
+
+const Z z = {"name": "Z"};
+
+service MyService {
+  i64 testFunc(1: i64 arg1, 2: Z arg2 = z);
+
+  void foo() throws (1: Ex ex) (hs.prefix = "x_");
+}
+
+service X {
+  i32 testFunc();
+}
+
+service Y extends X {
+}
+
+struct TestFunc {}
+
+exception Ex {}
+
+service Q {
+  oneway void testFunc1();
+  readonly i32 testFunc2();
+}
diff --git a/tests/if/typedef_annotation.thrift b/tests/if/typedef_annotation.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/typedef_annotation.thrift
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef Foo Bar
+
+struct Foo {}
+
+@Bar
+struct Baz {
+  1: string baz;
+}
diff --git a/tests/if/typedef_struct_const.thrift b/tests/if/typedef_struct_const.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/typedef_struct_const.thrift
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+typedef Foo Bar
+
+struct Foo {
+  1: i16 a;
+}
+
+const Bar BAR = Bar{a = 1};
diff --git a/tests/if/versions.thrift b/tests/if/versions.thrift
new file mode 100644
--- /dev/null
+++ b/tests/if/versions.thrift
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+struct X1 {
+  1: i32 x;
+}
+
+struct X2 {
+  1: string x;
+}
+
+struct Y1 {
+  1: i64 x;
+  2: string y;
+}
+
+struct Y2 {
+  1: i64 x;
+}
+
+union U1 {
+  1: i64 x;
+  2: string y;
+}
+
+union U2 {
+  1: i64 x;
+}
+
+struct L1 {
+  1: list<U1> l;
+}
+
+struct L2 {
+  1: list<U2> l;
+}
diff --git a/thrift-compiler.cabal b/thrift-compiler.cabal
new file mode 100644
--- /dev/null
+++ b/thrift-compiler.cabal
@@ -0,0 +1,146 @@
+cabal-version:       3.6
+
+-- Copyright (c) Facebook, Inc. and its affiliates.
+
+name:                thrift-compiler
+version:             0.1.0.1
+synopsis: A compiler from the Thrift Interface Definition Language (IDL) to Haskell
+homepage:            https://github.com/facebookincubator/hsthrift
+bug-reports:         https://github.com/facebookincubator/hsthrift/issues
+license:             BSD-3-Clause
+license-file:        LICENSE
+author:              Facebook, Inc.
+maintainer:          hsthrift-team@fb.com
+copyright:           (c) Facebook, All Rights Reserved
+category:            Thrift
+build-type:          Simple
+extra-source-files:  CHANGELOG.md,
+                     test/fixtures/**/*.ast,
+                     test/fixtures/gen-hs2/**/*.hs,
+                     test/if/*.thrift,
+                     tests/if/*.thrift,
+                     tests/if/*.hs
+
+description:
+    A compiler from the Thrift Interface Definition Language (IDL) to Haskell.
+
+    NOTE: for build instructions and documentation, see
+    <https://github.com/facebookincubator/hsthrift>
+
+source-repository head
+    type: git
+    location: https://github.com/facebookincubator/hsthrift.git
+
+common fb-haskell
+    default-language: Haskell2010
+    default-extensions:
+        BangPatterns
+        BinaryLiterals
+        DataKinds
+        DeriveDataTypeable
+        DeriveGeneric
+        EmptyCase
+        ExistentialQuantification
+        FlexibleContexts
+        FlexibleInstances
+        GADTs
+        GeneralizedNewtypeDeriving
+        LambdaCase
+        MultiParamTypeClasses
+        MultiWayIf
+        NoMonomorphismRestriction
+        OverloadedStrings
+        PatternSynonyms
+        RankNTypes
+        RecordWildCards
+        ScopedTypeVariables
+        StandaloneDeriving
+        TupleSections
+        TypeFamilies
+        TypeSynonymInstances
+        NondecreasingIndentation
+
+library
+    import: fb-haskell
+    hs-source-dirs: . plugins
+    exposed-modules:
+        Thrift.Compiler
+        Thrift.Compiler.GenClient
+        Thrift.Compiler.GenConst
+        Thrift.Compiler.GenEnum
+        Thrift.Compiler.GenFunction
+        Thrift.Compiler.GenHaskell
+        Thrift.Compiler.GenJSON
+        Thrift.Compiler.GenJSONLoc
+        Thrift.Compiler.GenService
+        Thrift.Compiler.GenStruct
+        Thrift.Compiler.GenTypedef
+        Thrift.Compiler.GenUnion
+        Thrift.Compiler.GenUtils
+        Thrift.Compiler.OptParse
+        Thrift.Compiler.Options
+        Thrift.Compiler.Lexer
+        Thrift.Compiler.Parser
+        Thrift.Compiler.Plugin
+        Thrift.Compiler.Pretty
+        Thrift.Compiler.Typechecker
+        Thrift.Compiler.Typechecker.Monad
+        Thrift.Compiler.Types
+        Thrift.Compiler.Plugins.Haskell
+        Thrift.Compiler.Plugins.Linter
+
+    build-depends:
+        aeson >= 2.0.3 && < 2.3,
+        array >= 0.5.3 && < 0.6,
+        mtl >= 2.2.2 && < 2.4,
+        optparse-applicative >= 0.17 && < 0.19,
+        aeson-pretty >= 0.8.10 && < 0.9,
+        either >= 5.0.2 && < 5.1,
+        extra >= 1.8 && < 1.9,
+        fb-util >= 0.1.0 && < 0.2,
+        some >= 1.0.6 && < 1.1,
+        text-show >= 3.10.5 && < 3.11,
+        haskell-src-exts >=1.20.3 && <1.24,
+        haskell-names < 0.10,
+        base >=4.11.1 && <4.20,
+        async ^>=2.2.1,
+        filepath ^>=1.4.2,
+        containers >=0.5.11 && <0.7,
+        text ^>=1.2.3.0,
+        transformers >= 0.5.6 && < 0.7,
+        bytestring >=0.10.8.2 && <0.13,
+        unordered-containers ^>=0.2.9.0,
+        directory ^>=1.3.1.5,
+        pretty ^>=1.1.3.6
+    build-tool-depends: alex:alex, happy:happy
+
+executable thrift-compiler
+    import: fb-haskell
+    hs-source-dirs: main
+    main-is: Main.hs
+    build-depends:
+        base >=4.11.1 && <4.20,
+        optparse-applicative,
+        thrift-compiler
+
+test-suite thrift-compiler-tests
+  import: fb-haskell
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test, test/github
+  main-is: TestFixtures.hs
+  ghc-options: -threaded -main-is TestFixtures
+  other-modules: Util
+  build-depends: aeson-pretty,
+                 base,
+                 directory,
+                 extra,
+                 filepath,
+                 fb-stubs,
+                 haskell-src-exts >=1.20.3 && <1.24,
+                 hspec,
+                 hspec-contrib,
+                 HUnit ^>= 1.6.1,
+                 process,
+                 temporary,
+                 text,
+                 thrift-compiler
