capnp-0.4.0.0: cmd/capnpc-haskell/IR/Haskell.hs
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
-- A last-leg intermediate form, before emitting actually Haskell source code.
--
-- This module contains a *simplified* Haskell AST; it only includes the
-- features we actually need. We roll our own for two reasons:
--
-- 1. Full Haskell ASTs are actually quite complex, and the data types exposed
-- by libraries for working with Haskell source reflect this. What we need
-- is much simpler.
-- 2. At some point we'll want to inject Haddock comments into the source (see
-- #32), and I(zenhack) don't see a good way to do that with the libraries
-- I looked at.
module IR.Haskell
( modFilePath
, DataArgs(..)
, DataDecl(..)
, DataVariant(..)
, ClassDecl(..)
, Decl(..)
, Do(..)
, Exp(..)
, Export(..)
, Import(..)
, InstanceDef(..)
, Module(..)
, Pattern(..)
, Type(..)
, TypeAlias(..)
, ValueDef(..)
) where
import Data.List (intercalate)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text as T
import qualified IR.Common as Common
import qualified IR.Name as Name
-- | A Haskell module
data Module = Module
{ modName :: [Name.UnQ]
-- ^ The parts of the module path
, modLangPragmas :: [T.Text]
-- ^ The language extensions enabled in this module.
, modExports :: Maybe [Export]
-- ^ The export list. If it is 'Nothing' that means there is no export
-- list (and therefore everything is exported).
, modDecls :: [Decl]
-- ^ The declarations in the module.
, modImports :: [Import]
-- ^ Modules to import.
}
deriving(Show, Read, Eq)
data Export
= ExportMod [Name.UnQ] -- module Foo.Bar
| ExportGCtors Name.GlobalQ -- Foo.Bar.Baz(..)
| ExportLCtors Name.LocalQ -- Baz(..)
| ExportGName Name.GlobalQ -- Foo.Bar.Baz
| ExportLName Name.LocalQ -- Baz
deriving(Show, Read, Eq)
data Import
= ImportAs -- import qualified Foo.Bar as Bar
{ importAs :: Name.UnQ
, parts :: [Name.UnQ]
}
| ImportQual -- import qualified Foo.Bar
{ parts :: [Name.UnQ]
}
| ImportAll -- import Foo.Bar
{ parts :: [Name.UnQ]
}
deriving(Show, Read, Eq)
-- | A declaration.
data Decl
= DcData DataDecl
| DcValue
{ typ :: Type
, def :: ValueDef
}
| DcInstance
{ ctx :: [Type]
, typ :: Type
, defs :: [InstanceDef]
}
| DcClass
{ ctx :: [Type]
, name :: Name.LocalQ
, params :: [Name.UnQ]
, decls :: [ClassDecl]
}
deriving(Show, Read, Eq)
data DataDecl = Data
{ dataName :: Name.UnQ
-- ^ The name of the declared type.
, typeArgs :: [Type]
, dataVariants :: [DataVariant]
-- ^ The variants/data constructors for the type.
, derives :: [Name.UnQ]
-- ^ A list of type classes to include in the deriving clause.
, dataNewtype :: !Bool
-- ^ Whether the declarationis a "newtype" or "data" declaration.
}
deriving(Show, Read, Eq)
data ClassDecl
= CdValueDecl Name.UnQ Type
| CdValueDef ValueDef
| CdMinimal [Name.UnQ]
-- ^ A MINIMAL pragma.
deriving(Show, Read, Eq)
data InstanceDef
= IdValue ValueDef
| IdData DataDecl
| IdType TypeAlias
deriving(Show, Read, Eq)
data TypeAlias = TypeAlias Name.UnQ [Type] Type
deriving(Show, Read, Eq)
data ValueDef = DfValue
{ name :: Name.UnQ
, value :: Exp
, params :: [Pattern]
}
deriving(Show, Read, Eq)
-- | A data constructor
data DataVariant = DataVariant
{ dvCtorName :: Name.UnQ
-- ^ The name of the constructor.
, dvArgs :: DataArgs
}
deriving(Show, Read, Eq)
-- | Arguments to a data constructor
data DataArgs
= APos [Type]
| ARec [(Name.UnQ, Type)]
deriving(Show, Read, Eq)
data Type
= TGName Name.GlobalQ
| TLName Name.LocalQ
| TVar T.Text
| TApp Type [Type]
| TFn [Type]
| TCtx [Type] Type
| TPrim Common.PrimWord
| TUnit
deriving(Show, Read, Eq)
data Exp
= EApp Exp [Exp]
| EFApp Exp [Exp]
-- ^ "Functorial" application, i.e. f <$> x <*> y <*> z.
| EGName Name.GlobalQ
| ELName Name.LocalQ
| EInt Integer
| EDo [Do] Exp
| EBind Exp Exp
-- ^ A call to (>>=)
| ETup [Exp]
| EBytes LBS.ByteString
| ECase Exp [(Pattern, Exp)]
| ETypeAnno Exp Type
| ELambda [Pattern] Exp
| ERecord Exp [(Name.UnQ, Exp)]
deriving(Show, Read, Eq)
data Do
= DoBind Name.UnQ Exp
| DoE Exp
deriving(Show, Read, Eq)
data Pattern
= PVar T.Text
| PLCtor Name.LocalQ [Pattern]
| PGCtor Name.GlobalQ [Pattern]
| PInt Integer
-- | Name{..}
| PLRecordWildCard Name.LocalQ
deriving(Show, Read, Eq)
-- | Get the file path for a module. For example, the module @Foo.Bar.Baz@ will
-- have a file path of @Foo/Bar/Baz.hs@.
modFilePath :: Module -> FilePath
modFilePath Module{modName} =
intercalate "/" (map (T.unpack . Name.renderUnQ) modName) ++ ".hs"