hydra-0.12.0: src/main/haskell/Hydra/Sources/Kernel/Terms/Decoding.hs
module Hydra.Sources.Kernel.Terms.Decoding where
-- Standard imports for term-level kernel modules
import Hydra.Kernel
import Hydra.Sources.Libraries
import qualified Hydra.Dsl.Accessors as Accessors
import qualified Hydra.Dsl.Ast as Ast
import qualified Hydra.Dsl.Coders as Coders
import qualified Hydra.Dsl.Compute as Compute
import qualified Hydra.Dsl.Core as Core
import qualified Hydra.Dsl.Grammar as Grammar
import qualified Hydra.Dsl.Graph as Graph
import qualified Hydra.Dsl.Json as Json
import qualified Hydra.Dsl.Lib.Chars as Chars
import qualified Hydra.Dsl.Lib.Equality as Equality
import qualified Hydra.Dsl.Lib.Flows as Flows
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 Hydra.Dsl.Phantoms as Phantoms
import qualified Hydra.Dsl.Lib.Sets as Sets
import Hydra.Dsl.Lib.Strings as Strings
import qualified Hydra.Dsl.Mantle as Mantle
import qualified Hydra.Dsl.Module as Module
import qualified Hydra.Dsl.TTerms as TTerms
import qualified Hydra.Dsl.TTypes as TTypes
import qualified Hydra.Dsl.Terms as Terms
import qualified Hydra.Dsl.Topology as Topology
import qualified Hydra.Dsl.Types as Types
import qualified Hydra.Dsl.Typing as Typing
import Hydra.Sources.Kernel.Types.All
import Prelude hiding ((++))
import qualified Data.Int as I
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 qualified Hydra.Sources.Kernel.Terms.Rewriting as Rewriting
module_ :: Module
module_ = Module (Namespace "hydra.decoding") elements
[Rewriting.module_]
kernelTypesModules $
Just "A module for decoding terms to native objects"
where
elements = [
el bigfloatDef,
el bigfloatValueDef,
el bigintDef,
el bigintValueDef,
el binaryDef,
el binaryLiteralDef,
el booleanDef,
el booleanLiteralDef,
el caseFieldDef,
el casesDef,
el fieldDef,
el float32Def,
el float32ValueDef,
el float64Def,
el float64ValueDef,
el floatLiteralDef,
el int16Def,
el int16ValueDef,
el int32Def,
el int32ValueDef,
el int64Def,
el int64ValueDef,
el int8Def,
el int8ValueDef,
el integerLiteralDef,
el lambdaDef,
el letBindingDef,
el letBindingWithKeyDef,
el letTermDef,
el listDef,
el literalDef,
el mapDef,
el nameDef,
el nominalDef,
el optionalDef,
el pairDef,
el recordDef,
el setDef,
el stringDef,
el stringLiteralDef,
el uint16Def,
el uint16ValueDef,
el uint32Def,
el uint32ValueDef,
el uint64Def,
el uint64ValueDef,
el uint8Def,
el uint8ValueDef,
el unitDef,
el unitVariantDef,
el variableDef,
el variantDef,
el wrapDef]
define :: String -> TTerm a -> TBinding a
define = definitionInModule module_
bigfloatDef :: TBinding (Term -> Maybe Float)
bigfloatDef = define "bigfloat" $
compose3 (ref literalDef) (ref floatLiteralDef) (ref bigfloatValueDef)
bigfloatValueDef :: TBinding (FloatValue -> Maybe Float)
bigfloatValueDef = define "bigfloatValue" $
matchVariant _FloatValue _FloatValue_bigfloat
bigintDef :: TBinding (Term -> Maybe Int)
bigintDef = define "bigint" $
compose3 (ref literalDef) (ref integerLiteralDef) (ref bigintValueDef)
bigintValueDef :: TBinding (IntegerValue -> Maybe Int)
bigintValueDef = define "bigintValue" $
matchVariant _IntegerValue _IntegerValue_bigint
binaryDef :: TBinding (Term -> Maybe String)
binaryDef = define "binary" $
compose2 (ref literalDef) (ref binaryLiteralDef)
binaryLiteralDef :: TBinding (Literal -> Maybe String)
binaryLiteralDef = define "binaryLiteral" $
matchVariant _Literal _Literal_binary
booleanDef :: TBinding (Term -> Maybe Bool)
booleanDef = define "boolean" $
compose2 (ref literalDef) (ref booleanLiteralDef)
booleanLiteralDef :: TBinding (Literal -> Maybe Bool)
booleanLiteralDef = define "booleanLiteral" $
matchVariant _Literal _Literal_boolean
casesDef :: TBinding (Name -> Term -> Maybe [Field])
casesDef = define "cases" $
lets [
"matchFunction">: matchTermVariant _Term_function,
"matchElimination">: matchVariant _Function _Function_elimination,
"matchUnion">: matchVariant _Elimination _Elimination_union]
$ ref nominalDef
@@ (unaryFunction Core.caseStatementTypeName)
@@ (unaryFunction Core.caseStatementCases)
@@ compose3 (var "matchFunction") (var "matchElimination") (var "matchUnion")
caseFieldDef :: TBinding (Name -> Name -> Term -> Y.Maybe Term)
caseFieldDef = define "caseField" $
lambda "tname" $ lambda "fname" $
compose2
(ref casesDef @@ var "tname" )
(ref fieldDef @@ var "fname")
fieldDef :: TBinding (Name -> [Field] -> Maybe Term)
fieldDef = define "field" $
lambdas ["fname", "fields"] $ lets [
"matches">: Lists.filter
(lambda "f" $ Equality.equal (Core.fieldName $ var "f") $ var "fname")
(var "fields")]
$ Logic.ifElse (Equality.equal (int32 1) (Lists.length $ var "matches"))
(just (Core.fieldTerm $ (Lists.head $ var "matches")))
nothing
float32Def :: TBinding (Term -> Maybe Float)
float32Def = define "float32" $
compose3
(ref literalDef)
(ref floatLiteralDef)
(ref float32ValueDef)
float32ValueDef :: TBinding (FloatValue -> Maybe Float)
float32ValueDef = define "float32Value" $
matchVariant _FloatValue _FloatValue_float32
float64Def :: TBinding (Term -> Maybe Float)
float64Def = define "float64" $
compose3
(ref literalDef)
(ref floatLiteralDef)
(ref float64ValueDef)
float64ValueDef :: TBinding (FloatValue -> Maybe Float)
float64ValueDef = define "float64Value" $
matchVariant _FloatValue _FloatValue_float64
floatLiteralDef = define "floatLiteral" $
matchVariant _Literal _Literal_float
int8Def :: TBinding (Term -> Maybe Int)
int8Def = define "int8" $
compose3
(ref literalDef)
(ref integerLiteralDef)
(ref int8ValueDef)
int8ValueDef :: TBinding (IntegerValue -> Maybe Int)
int8ValueDef = define "int8Value" $
matchVariant _IntegerValue _IntegerValue_int8
int16Def :: TBinding (Term -> Maybe Int)
int16Def = define "int16" $
compose3
(ref literalDef)
(ref integerLiteralDef)
(ref int16ValueDef)
int16ValueDef :: TBinding (IntegerValue -> Maybe Int)
int16ValueDef = define "int16Value" $
matchVariant _IntegerValue _IntegerValue_int16
int32Def :: TBinding (Term -> Maybe Int)
int32Def = define "int32" $
compose3
(ref literalDef)
(ref integerLiteralDef)
(ref int32ValueDef)
int32ValueDef :: TBinding (IntegerValue -> Maybe Int)
int32ValueDef = define "int32Value" $
matchVariant _IntegerValue _IntegerValue_int32
int64Def :: TBinding (Term -> Maybe Int)
int64Def = define "int64" $
compose3
(ref literalDef)
(ref integerLiteralDef)
(ref int64ValueDef)
int64ValueDef :: TBinding (IntegerValue -> Maybe Int)
int64ValueDef = define "int64Value" $
matchVariant _IntegerValue _IntegerValue_int64
integerLiteralDef :: TBinding (Literal -> Maybe IntegerValue)
integerLiteralDef = define "integerLiteral" $
matchVariant _Literal _Literal_integer
lambdaDef :: TBinding (Term -> Maybe Lambda)
lambdaDef = define "lambda" $
lets [
"matchFunction">: matchTermVariant _Term_function,
"matchLambda">: matchVariant _Function _Function_lambda]
$ compose2 (var "matchFunction") (var "matchLambda")
letBindingDef :: TBinding (Name -> Term -> Maybe Binding)
letBindingDef = define "letBinding" $
lambda "fname" $ lambda "term" $ Optionals.bind
(Optionals.map
(unaryFunction Core.letBindings)
(ref letTermDef @@ var "term"))
(ref letBindingWithKeyDef @@ var "fname")
letBindingWithKeyDef :: TBinding (Name -> [Binding] -> Maybe Binding)
letBindingWithKeyDef = define "letBindingWithKey" $
lambda "fname" $ lambda "bindings" $ lets [
"matches">: Lists.filter
(lambda "b" $ Equality.equal (Core.bindingName $ var "b") $ var "fname")
(var "bindings")]
$ Logic.ifElse (Equality.equal (int32 1) (Lists.length $ var "matches"))
(just (Lists.head $ var "matches"))
nothing
letTermDef :: TBinding (Term -> Maybe Let)
letTermDef = define "letTerm" $
matchTermVariant _Term_let
listDef :: TBinding (Term -> Maybe [Term])
listDef = define "list" $
matchTermVariant _Term_list
literalDef :: TBinding (Term -> Maybe Literal)
literalDef = define "literal" $
matchTermVariant _Term_literal
mapDef :: TBinding (Term -> Maybe (M.Map Term Term))
mapDef = define "map" $
matchTermVariant _Term_map
nameDef :: TBinding (Term -> Maybe Name)
nameDef = define "name" $
lambda "term" $ Optionals.map nm
(Optionals.bind
(ref wrapDef @@ Core.nameLift _Name @@ var "term")
(ref stringDef))
where
nm :: TTerm (String -> Name)
nm = TTerm $ Terms.lambda "s" $ TermWrap $ WrappedTerm _Name $ Terms.var "s"
nominalDef :: TBinding ((a -> Name) -> (a -> b) -> (c -> Maybe a) -> Name -> c -> Maybe b)
nominalDef = define "nominal" $
lambda "getName" $ lambda "getB" $ lambda "getA" $ lambda "expected" $
lets [
"namesEqual">: lambda "n1" $ lambda "n2" $ Equality.equal (Core.unName $ var "n1") (Core.unName $ var "n2")] $
compose2
(var "getA")
(lambda "a" $ (Logic.ifElse (var "namesEqual" @@ (var "getName" @@ var "a") @@ (var "expected")))
(just (var "getB" @@ var "a"))
nothing)
optionalDef :: TBinding (Term -> Maybe (Maybe Term))
optionalDef = define "optional" $
matchTermVariant _Term_optional
pairDef :: TBinding (Term -> Maybe (Term, Term))
pairDef = define "pair" $
lets [
"matchProduct">: matchTermVariant _Term_product]
$ compose2
(var "matchProduct")
(lambda "l" $ Logic.ifElse (Equality.equal (int32 2) (Lists.length $ var "l"))
(just $ pair (Lists.at (int32 0) $ var "l") (Lists.at (int32 1) $ var "l"))
nothing)
recordDef :: TBinding (Name -> Term -> Maybe [Field])
recordDef = define "record" $
matchNominal _Term_record
(unaryFunction Core.recordTypeName)
(unaryFunction Core.recordFields)
setDef :: TBinding (Term -> Maybe (S.Set Term))
setDef = define "set" $
matchTermVariant _Term_set
stringDef :: TBinding (Term -> Maybe String)
stringDef = define "string" $
compose2 (ref literalDef) (ref stringLiteralDef)
stringLiteralDef :: TBinding (Literal -> Maybe String)
stringLiteralDef = define "stringLiteral" $
matchVariant _Literal _Literal_string
uint8Def :: TBinding (Term -> Maybe Int)
uint8Def = define "uint8" $
compose3 (ref literalDef) (ref integerLiteralDef) (ref uint8ValueDef)
uint8ValueDef :: TBinding (IntegerValue -> Maybe Int)
uint8ValueDef = define "uint8Value" $
matchVariant _IntegerValue _IntegerValue_uint8
uint16Def :: TBinding (Term -> Maybe Int)
uint16Def = define "uint16" $
compose3 (ref literalDef) (ref integerLiteralDef) (ref uint16ValueDef)
uint16ValueDef :: TBinding (IntegerValue -> Maybe Int)
uint16ValueDef = define "uint16Value" $
matchVariant _IntegerValue _IntegerValue_uint16
uint32Def :: TBinding (Term -> Maybe Int)
uint32Def = define "uint32" $
compose3 (ref literalDef) (ref integerLiteralDef) (ref uint32ValueDef)
uint32ValueDef :: TBinding (IntegerValue -> Maybe Int)
uint32ValueDef = define "uint32Value" $
matchVariant _IntegerValue _IntegerValue_uint32
uint64Def :: TBinding (Term -> Maybe Int)
uint64Def = define "uint64" $
compose3 (ref literalDef) (ref integerLiteralDef) (ref uint64ValueDef)
uint64ValueDef :: TBinding (IntegerValue -> Maybe Int)
uint64ValueDef = define "uint64Value" $
matchVariant _IntegerValue _IntegerValue_uint64
unitDef :: TBinding (Term -> Maybe ())
unitDef = define "unit" $
lambda "term" $ cases _Term (var "term") (Just nothing) [
_Term_unit>>: constant $ just unit]
unitVariantDef :: TBinding (Name -> Term -> Maybe Name)
unitVariantDef = define "unitVariant" $
lambda "tname" $ lambda "term" $ Optionals.map
(unaryFunction Core.fieldName)
(ref variantDef @@ var "tname" @@ var "term")
variableDef :: TBinding (Term -> Y.Maybe Name)
variableDef = define "variable" $
matchTermVariant _Term_variable
variantDef :: TBinding (Name -> Term -> Maybe Field)
variantDef = define "variant" $
matchNominal _Term_union
(unaryFunction Core.injectionTypeName)
(unaryFunction Core.injectionField)
wrapDef :: TBinding (Name -> Term -> Maybe Term)
wrapDef = define "wrap" $
matchNominal _Term_wrap
(unaryFunction Core.wrappedTermTypeName)
(unaryFunction Core.wrappedTermObject)
--
compose2 :: TTerm (a -> Maybe b) -> TTerm (b -> Maybe c) -> TTerm (a -> Maybe c)
compose2 = Optionals.compose
compose3 :: TTerm (a -> Maybe b) -> TTerm (b -> Maybe c) -> TTerm (c -> Maybe d) -> TTerm (a -> Maybe d)
compose3 f g h = Optionals.compose (Optionals.compose f g) h
matchNominal :: Name -> TTerm (a -> Name) -> TTerm (a -> b) -> TTerm (Name -> Term -> Maybe b)
matchNominal fname getName getB = ref nominalDef @@ getName @@ getB @@ matchTermVariant fname
matchTermVariant :: Name -> TTerm (Term -> Maybe a)
matchTermVariant fname = matchVariant _Term fname <.> ref Rewriting.deannotateTermDef
matchVariant :: Name -> Name -> TTerm (a -> Maybe b)
matchVariant tname fname = match tname (Just nothing) [
fname>>: lambda "matched_" $ Optionals.pure $ var "matched_"]