{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE OverloadedStrings #-} module Descript.BasicInj.Data.Source ( Query (..) , AModule (..) , BModule (..) , Program (..) , Source (..) , Dep , DepResult , DepResultT , DirtyDep , DirtyDepT , Depd , DirtyDepd , DepResolver , DFile , sourceToProgram , sourceBModule , sourceBModule_ , sourceAModule , sourceAModule_ , sourceScope , moduleScope , dsourceAModule , dmodule , dquery ) where import Descript.BasicInj.Data.Reducer import qualified Descript.BasicInj.Data.Value.Reg as Reg import Descript.BasicInj.Data.Type import Descript.BasicInj.Data.Import import Descript.Misc import Data.Semigroup as S import Data.Monoid as M import Data.List import Prelude hiding (mod) -- | The "main" value in a program. A program is interpreted by reducing -- its query - this reduced is the output of a program. data Query an = Query { queryAnn :: an , queryVal :: Reg.Value an } deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable) -- | Anonymous module - no scope. Defines how a program is interpreted. -- When a module imports another, the other's 'AModule' is appended. data AModule an = AModule { amoduleAnn :: an , recordCtx :: RecordCtx an , reduceCtx :: ReduceCtx an } deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable) -- | A module with a scope and imports, which allows it to import other -- modules. data BModule an = BModule { bmoduleAnn :: an , importCtx :: ImportCtx an , amodule :: AModule an } deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable) -- | Parsed from a source file and interpreted. To interpret, the query -- is reduced using the module. data Program an = Program { programAnn :: an , module' :: BModule an , query :: Query an } deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable) -- | Every source file gets parsed into one of these. data Source an = SourceModule (BModule an) | SourceProgram (Program an) deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable) type Dep = AModule () type DepResult = GenDepResult Dep type DepResultT u = GenDepResultT u Dep type DirtyDep an = GenDirtyDep an Dep type DirtyDepT an u = GenDirtyDepT an u Dep type Depd a an = GenDepd Dep (a an) type DirtyDepd a an = GenDepd (DirtyDep an) (a an) type DepResolver u = GenDepResolver u (AModule ()) type DFile u = GenDFile u (AModule ()) instance (Semigroup an) => Semigroup (AModule an) where x <> y = AModule { amoduleAnn = amoduleAnn x S.<> amoduleAnn y , recordCtx = recordCtx x S.<> recordCtx y , reduceCtx = reduceCtx x S.<> reduceCtx y } instance (Monoid an) => Monoid (AModule an) where mempty = AModule { amoduleAnn = mempty , recordCtx = mempty , reduceCtx = mempty } x `mappend` y = AModule { amoduleAnn = amoduleAnn x M.<> amoduleAnn y , recordCtx = recordCtx x M.<> recordCtx y , reduceCtx = reduceCtx x M.<> reduceCtx y } instance Ann Source where getAnn (SourceModule mod) = getAnn mod getAnn (SourceProgram prog) = getAnn prog instance Ann Program where getAnn = programAnn instance Ann BModule where getAnn = bmoduleAnn instance Ann AModule where getAnn = amoduleAnn instance Ann Query where getAnn = queryAnn instance Printable Source where aprintRec sub (SourceModule mod) = sub mod aprintRec sub (SourceProgram prog) = sub prog instance Printable Program where aprintRec sub prog = pintercal "\n\n" $ filter (/= mempty) [ sub $ module' prog , sub $ query prog ] instance Printable BModule where aprintRec sub mod = pintercal "\n\n" $ filter (/= mempty) [ sub $ importCtx mod , sub $ amodule mod ] instance Printable AModule where aprintRec sub mod = pintercal "\n\n" $ filter (/= mempty) [ sub $ recordCtx mod , sub $ reduceCtx mod ] instance Printable Query where aprintRec sub (Query _ val) = sub val M.<> "?" instance (Show an) => Summary (Source an) where summaryRec = pprintSummaryRec instance (Show an) => Summary (Program an) where summaryRec = pprintSummaryRec instance (Show an) => Summary (BModule an) where summaryRec = pprintSummaryRec instance (Show an) => Summary (AModule an) where summaryRec = pprintSummaryRec instance (Show an) => Summary (Query an) where summaryRec = pprintSummaryRec -- | If the source is a program, returns it. -- If it's a module, returns 'Nothing'. sourceToProgram :: Source an -> Maybe (Program an) sourceToProgram (SourceModule _) = Nothing sourceToProgram (SourceProgram prog) = Just prog -- | The source's bound module. sourceBModule :: Source an -> BModule an sourceBModule (SourceModule mod) = mod sourceBModule (SourceProgram prog) = module' prog -- | The source's bound module without annotations. sourceBModule_ :: Source an -> BModule () sourceBModule_ = remAnns . sourceBModule -- | Contains the source's anonymous module. sourceAModule :: Source an -> AModule an sourceAModule = amodule . sourceBModule -- | Contains the source's anonymous module, without annotations. sourceAModule_ :: Source an -> AModule () sourceAModule_ = remAnns . sourceAModule -- | The source's scope - the scope of the source's module, which is -- also used by the query if the source is a program. sourceScope :: Source an -> AbsScope sourceScope = moduleScope . sourceBModule -- | The scope of the module. moduleScope :: BModule an -> AbsScope moduleScope = moduleDeclScope . moduleDecl . importCtx -- | The full module of a source, including its dependencies. dsourceAModule :: Depd Source an -> AModule () dsourceAModule (Depd extra src) = sourceAModule_ src M.<> extra -- | The full module of a program, including its dependencies. dmodule :: Depd Program an -> AModule () dmodule (Depd extra prog) = remAnns (amodule $ module' prog) M.<> extra -- | The query of a program with dependencies. dquery :: Depd Program an -> Query an dquery = query . depdVal