descript-lang-0.2.0.0: src/Descript/BasicInj/Data/Source.hs
{-# 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