mirror of
https://github.com/zap-proto/haskell.git
synced 2026-10-30 15:05:00 +00:00
200 lines
5.1 KiB
Haskell
200 lines
5.1 KiB
Haskell
{-# 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]
|
|
, funDeps :: [(T.Text, T.Text)]
|
|
, 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
|
|
| TKindAnnotated Type Type
|
|
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"
|