morloc-0.33.0: library/Morloc/Frontend/Namespace.hs
{-|
Module : Morloc.Frontend.Namespace
Description : All frontend types and datastructures
Copyright : (c) Zebulun Arendsee, 2020
License : GPL-3
Maintainer : zbwrnz@gmail.com
Stability : experimental
-}
module Morloc.Frontend.Namespace
( module Morloc.Namespace
, Expr(..)
, Import(..)
, Stack
, StackState(..)
, StackConfig(..)
-- ** DAG and associated types
, ParserNode(..)
, ParserDag
, PreparedNode(..)
, PreparedDag
, TypedNode(..)
, TypedDag
-- ** Typechecking
, Gamma
, GammaIndex(..)
, EType(..)
, TypeSet(..)
, Indexable(..)
-- ** ModuleGamma paraphernalia
, ModularGamma
-- rifraf
, resolve
, substituteT
) where
import Morloc.Namespace
import Data.Set (Set)
import Data.Map.Strict (Map)
import Control.Monad.Except (ExceptT)
import Control.Monad.Reader (ReaderT)
import Control.Monad.State (StateT)
import Control.Monad.Writer (WriterT)
import Data.Scientific (Scientific)
import Data.Text (Text)
-- This functions removes qualified and existential types.
-- * all qualified terms are replaced with UnkT
-- * all existentials are replaced with default values if a possible
-- FIXME: should I really just take the first in the list???
resolve :: UnresolvedType -> Type
resolve (VarU v) = VarT v
resolve (FunU t1 t2) = FunT (resolve t1) (resolve t2)
resolve (ArrU v ts) = ArrT v (map resolve ts)
resolve (NamU r v ps rs) =
let ts' = map (resolve . snd) rs
ps' = map resolve ps
in NamT r v ps' (zip (map fst rs) ts')
resolve (ExistU _ _ []) = error "UnsolvedExistentialTerm"
resolve (ExistU _ _ (t:_)) = resolve t
resolve (ForallU v t) = substituteT v (UnkT v) (resolve t)
-- | substitute all appearances of a given variable with a given new type
substituteT :: TVar -> Type -> Type -> Type
substituteT v0 r0 t0 = sub t0
where
sub :: Type -> Type
sub t@(UnkT _) = t
sub t@(VarT v)
| v0 == v = r0
| otherwise = t
sub (FunT t1 t2) = FunT (sub t1) (sub t2)
sub (ArrT v ts) = ArrT v (map sub ts)
sub (NamT r v ts rs) = NamT r v (map sub ts) [(x, sub t) | (x, t) <- rs]
-- | Terms, see Dunfield Figure 1
data Expr
= SrcE [Source]
-- ^ import "c" from "foo.c" ("f" as yolo)
| Signature EVar EType
-- ^ x :: A; e
| Declaration EVar Expr
-- ^ x=e1; e2
| UniE
-- ^ (())
| VarE EVar
-- ^ (x)
| AccE Expr EVar
-- ^ person@age - access a field in a record
| ListE [Expr]
-- ^ [e]
| TupleE [Expr]
-- ^ (e1), (e1,e2), ... (e1,e2,...,en)
| LamE EVar Expr
-- ^ (\x -> e)
| AppE Expr Expr
-- ^ (e e)
| AnnE Expr [UnresolvedType]
-- ^ (e : A)
| NumE Scientific
-- ^ number of arbitrary size and precision
| LogE Bool
-- ^ boolean primitive
| StrE Text
-- ^ literal string
| RecE [(EVar, Expr)]
deriving (Show, Ord, Eq)
-- | Extended Type that may represent a language specific type as well as sets
-- of properties and constrains.
data EType =
EType
{ etype :: UnresolvedType
, eprop :: Set Property
, econs :: Set Constraint
}
deriving (Show, Eq, Ord)
instance HasOneLanguage EType where
langOf e = langOf (etype e)
data Import =
Import
{ importModuleName :: MVar
, importInclude :: Maybe [(EVar, EVar)]
, importExclude :: [EVar]
, importNamespace :: Maybe EVar -- currently not used
}
deriving (Ord, Eq, Show)
-- | A context, see Dunfield Figure 6
data GammaIndex
= VarG TVar
-- ^ (G,a)
| AnnG Expr TypeSet
-- ^ (G,x:A) looked up in the (Var) and cut in (-->I)
| ExistG TVar [UnresolvedType] [UnresolvedType]
-- ^ (G,a^) unsolved existential variable
| SolvedG TVar UnresolvedType
-- ^ (G,a^=t) Store a solved existential variable
| MarkG TVar
-- ^ (G,>a^) Store a type variable marker bound under a forall
| MarkEG EVar
-- ^ ...
| SrcG Source
-- ^ source
| UnsolvedConstraint UnresolvedType UnresolvedType
-- ^ Store an unsolved serialization constraint containing one or more
-- existential variables. When the existential variables are solved, the
-- constraint will be written into the Stack state.
deriving (Ord, Eq, Show)
type Gamma = [GammaIndex]
data TypeSet =
TypeSet (Maybe EType) [EType]
deriving (Show, Eq, Ord)
type ModularGamma = Map MVar (Map EVar TypeSet)
class Indexable a where
index :: a -> GammaIndex
instance Indexable GammaIndex where
index = id
instance Indexable UnresolvedType where
index (ExistU t ts ds) = ExistG t ts ds
index t = error $ "Can only index ExistT, found: " <> show t
type GeneralStack c e l s a
= ReaderT c (ExceptT e (WriterT l (StateT s IO))) a
type Stack a = GeneralStack StackConfig MorlocError [Text] StackState a
data StackConfig =
StackConfig
{ stackConfigVerbosity :: Int
}
data StackState =
StackState
{ stateVar :: Int
, stateQul :: Int
, stateSer :: [(UnresolvedType, UnresolvedType)]
, stateDepth :: Int
}
deriving (Ord, Eq, Show)
-- | The type returned from the Parser. It contains all the information in a
-- single module but knows NOTHING about other modules.
data ParserNode = ParserNode {
parserNodePath :: Maybe Path
, parserNodeBody :: [Expr]
, parserNodeSourceMap :: Map (EVar, Lang) Source
, parserNodeTypedefs :: Map TVar (UnresolvedType, [TVar])
, parserNodeExports :: Set EVar
} deriving (Show, Ord, Eq)
type ParserDag = DAG MVar Import ParserNode
-- | Node description after desugaring (substitute type aliases and resolve
-- imports/exports)
data PreparedNode = PreparedNode {
preparedNodePath :: Maybe Path
, preparedNodeBody :: [Expr]
, preparedNodeSourceMap :: Map (EVar, Lang) Source
, preparedNodeExports :: Set EVar
, preparedNodeTypedefs :: Map TVar (UnresolvedType, [TVar])
, preparedNodePackers :: Map (TVar, Int) [UnresolvedPacker]
-- ^ The (un)packers available in this module scope.
} deriving (Show, Ord, Eq)
type PreparedDag = DAG MVar [(EVar, EVar)] ParserNode
-- | Node description after type checking. This will later be fed into
-- `treeify` to make the SAnno objects that will be passed to Generator.
data TypedNode = TypedNode {
typedNodeModuleName :: MVar
, typedNodePath :: Maybe Path
, typedNodeBody :: [Expr]
, typedNodeTypeMap :: Map EVar TypeSet
, typedNodeSourceMap :: Map (EVar, Lang) Source
, typedNodeExports :: Set EVar
, typedNodeTypedefs :: Map TVar (Type, [TVar])
, typedNodePackers :: Map (TVar, Int) [UnresolvedPacker]
, typedNodeConstructors :: Map TVar Source
-- ^ The (un)packers available in this module scope.
} deriving (Show, Ord, Eq)
type TypedDag = DAG MVar [(EVar, EVar)] TypedNode