hydra-0.8.0: src/main/haskell/Hydra/Sources/Tier2/Tier2.hs
{-# LANGUAGE OverloadedStrings #-}
module Hydra.Sources.Tier2.Tier2 where
-- Standard Tier-2 imports
import Prelude hiding ((++))
import qualified Data.List as L
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Maybe as Y
import Hydra.Dsl.Base as Base
import qualified Hydra.Dsl.Core as Core
import qualified Hydra.Dsl.Graph as Graph
import qualified Hydra.Dsl.Lib.Equality as Equality
import qualified Hydra.Dsl.Lib.Flows as Flows
import qualified Hydra.Dsl.Lib.Io as Io
import qualified Hydra.Dsl.Lib.Lists as Lists
import qualified Hydra.Dsl.Lib.Literals as Literals
import qualified Hydra.Dsl.Lib.Logic as Logic
import qualified Hydra.Dsl.Lib.Maps as Maps
import qualified Hydra.Dsl.Lib.Math as Math
import qualified Hydra.Dsl.Lib.Optionals as Optionals
import qualified Hydra.Dsl.Lib.Sets as Sets
import Hydra.Dsl.Lib.Strings as Strings
import qualified Hydra.Dsl.Module as Module
import qualified Hydra.Dsl.Terms as Terms
import qualified Hydra.Dsl.Types as Types
import Hydra.Sources.Tier1.All
tier2Definition :: String -> TTerm a -> TElement a
tier2Definition = definitionInModule hydraTier2Module
hydraTier2Module :: Module
hydraTier2Module = Module (Namespace "hydra/tier2") elements
[hydraGraphModule, hydraMantleModule, hydraComputeModule, hydraStripModule] tier0Modules $
Just ("A module for miscellaneous tier-2 functions and constants.")
where
elements = [
el getStateDef,
el getTermTypeDef,
el putStateDef,
el requireElementTypeDef,
el requireTermTypeDef,
el unexpectedDef
]
getStateDef :: TElement (Flow s s)
getStateDef = tier2Definition "getState" $
doc "Get the state of the current flow" $
typed flowSST $
wrap _Flow (lambda "s0" $ lambda "t0" $ (
(lambda "v" $ lambda "s" $ lambda "t" $ (
(matchOpt
(Flows.flowState nothing (var "s") (var "t"))
(constant (Flows.flowState (just $ var "s") (var "s") (var "t"))))
@@ var "v"))
@@ (Flows.flowStateValue @@ var "fs1") @@ (Flows.flowStateState @@ var "fs1") @@ (Flows.flowStateTrace @@ var "fs1"))
`with` [
"fs1">:
typed (Types.apply (Types.apply (TypeVariable _FlowState) sT) unitT) $
Flows.unFlow @@ (Flows.pure @@ unit) @@ var "s0" @@ var "t0"])
getTermTypeDef :: TElement (Term -> Flow Graph (Maybe Type))
getTermTypeDef = tier2Definition "getTermType" $
doc "Get the annotated type of a given term, if any" $
function termT (optionalT typeT) $
match _Term (Just nothing) [
"annotated">: ref getTermTypeDef <.> project _AnnotatedTerm _AnnotatedTerm_subject,
"typed">: lambda "tt" $ just (project _TypedTerm _TypedTerm_type @@ var "tt")]
putStateDef :: TElement (s -> Flow s ())
putStateDef = tier2Definition "putState" $
doc "Set the state of a flow" $
function sT (flowT sT unitT) $
lambda "cx" $ wrap _Flow $ lambda "s0" $ lambda "t0" (
(Flows.flowState
(Flows.flowStateValue @@ var "f1")
(var "cx")
(Flows.flowStateTrace @@ var "f1"))
`with` [
"f1">: Flows.unFlow @@ (Flows.pure @@ unit) @@ var "s0" @@ var "t0"])
requireElementTypeDef :: TElement (Element -> Flow Graph Type)
requireElementTypeDef = tier2Definition "requireElementType" $
doc "Get the annotated type of a given element, or fail if it is missing" $
function elementT (flowT graphT typeT) $
lambda "el" $ ((var "withType" @@ (ref getTermTypeDef @@ (project _Element _Element_data @@ var "el")))
`with` [
"withType">: matchOpt
(Flows.fail @@ ("missing type annotation for element " ++ (unwrap _Name @@ (project _Element _Element_name @@ var "el"))))
Flows.pure])
requireTermTypeDef :: TElement (Term -> Flow Graph Type)
requireTermTypeDef = tier2Definition "requireTermType" $
doc "Get the annotated type of a given term, or fail if it is missing" $
function termT (flowT graphT typeT) $
(var "withType" <.> ref getTermTypeDef)
`with` [
"withType">: matchOpt
(Flows.fail @@ "missing type annotation")
Flows.pure]
unexpectedDef :: TElement (String -> String -> Flow s x)
unexpectedDef = tier2Definition "unexpected" $
doc "Fail if an actual value does not match an expected value" $
function stringT (funT stringT (flowT sT xT)) $
lambda "expected" $ lambda "actual" $ Flows.fail @@ ("expected " ++ var "expected" ++ " but found: " ++ var "actual")