packages feed

hydra-0.1.1: src/main/haskell/Hydra/CoreEncoding.hs

-- | Encoding of types as terms

module Hydra.CoreEncoding where

import Hydra.Core
import Hydra.Compute
import Hydra.Mantle
import Hydra.Monads
import Hydra.Impl.Haskell.Dsl.Terms

import Prelude hiding (map)
import qualified Data.Map as M
import qualified Data.Set as S


encodeApplication :: Ord m => Application m -> Term m
encodeApplication (Application lhs rhs) = record _Application [
  Field _Application_function $ encodeTerm lhs,
  Field _Application_argument $ encodeTerm rhs]

encodeApplicationType :: ApplicationType m -> Term m
encodeApplicationType (ApplicationType lhs rhs) = record _ApplicationType [
  Field _ApplicationType_function $ encodeType lhs,
  Field _ApplicationType_argument $ encodeType rhs]

encodeCaseStatement :: Ord m => CaseStatement m -> Term m
encodeCaseStatement (CaseStatement name cases) = record _CaseStatement [
  Field _CaseStatement_typeName $ string (unName name),
  Field _CaseStatement_cases $ list $ encodeField <$> cases]

encodeElimination :: Ord m => Elimination m -> Term m
encodeElimination e = case e of
  EliminationElement -> unitVariant _Elimination _Elimination_element
  EliminationList f -> variant _Elimination _Elimination_list $ encodeTerm f
  EliminationNominal (Name name) -> variant _Elimination _Elimination_nominal $ string name
  EliminationOptional cases -> variant _Elimination _Elimination_optional $ encodeOptionalCases cases
  EliminationRecord p -> variant _Elimination _Elimination_record $ encodeProjection p
  EliminationUnion c -> variant _Elimination _Elimination_union $ encodeCaseStatement c

encodeField :: Ord m => Field m -> Term m
encodeField (Field (FieldName name) term) = record _Field [
  Field _Field_name $ string name,
  Field _Field_term $ encodeTerm term]

encodeFieldType :: FieldType m -> Term m
encodeFieldType (FieldType (FieldName fname) t) = record _FieldType [
  Field _FieldType_name $ string fname,
  Field _FieldType_type $ encodeType t]

encodeFloatType :: FloatType -> Term m
encodeFloatType ft = unitVariant _FloatType $ case ft of
  FloatTypeBigfloat -> _FloatType_bigfloat
  FloatTypeFloat32 -> _FloatType_float32
  FloatTypeFloat64 -> _FloatType_float64

encodeFunction :: Ord m => Function m -> Term m
encodeFunction f = case f of
  FunctionCompareTo other -> variant _Function _Function_compareTo $ encodeTerm other
  FunctionElimination e -> variant _Function _Function_compareTo $ encodeElimination e
  FunctionLambda l -> variant _Function _Function_lambda $ encodeLambda l
  FunctionPrimitive (Name name) -> variant _Function _Function_primitive $ string name

encodeFunctionType :: FunctionType m -> Term m
encodeFunctionType (FunctionType dom cod) = record _FunctionType [
  Field _FunctionType_domain $ encodeType dom,
  Field _FunctionType_codomain $ encodeType cod]

encodeIntegerType :: IntegerType -> Term m
encodeIntegerType it = unitVariant _IntegerType $ case it of
  IntegerTypeBigint -> _IntegerType_bigint
  IntegerTypeInt8 -> _IntegerType_int8
  IntegerTypeInt16 -> _IntegerType_int16
  IntegerTypeInt32 -> _IntegerType_int32
  IntegerTypeInt64 -> _IntegerType_int64
  IntegerTypeUint8 -> _IntegerType_uint8
  IntegerTypeUint16 -> _IntegerType_uint16
  IntegerTypeUint32 -> _IntegerType_uint32
  IntegerTypeUint64 -> _IntegerType_uint64

encodeLambda :: Ord m => Lambda m -> Term m
encodeLambda (Lambda (Variable v) b) = record _Lambda [
  Field _Lambda_parameter $ string v,
  Field _Lambda_body $ encodeTerm b]

encodeLambdaType :: LambdaType m -> Term m
encodeLambdaType (LambdaType (VariableType var) body) = record _LambdaType [
  Field _LambdaType_parameter $ string var,
  Field _LambdaType_body $ encodeType body]

encodeLiteralType :: LiteralType -> Term m
encodeLiteralType at = case at of
  LiteralTypeBinary -> unitVariant _LiteralType _LiteralType_binary
  LiteralTypeBoolean -> unitVariant _LiteralType _LiteralType_boolean
  LiteralTypeFloat ft -> variant _LiteralType _LiteralType_float $ encodeFloatType ft
  LiteralTypeInteger it -> variant _LiteralType _LiteralType_integer $ encodeIntegerType it
  LiteralTypeString -> unitVariant _LiteralType _LiteralType_string

encodeLiteral :: Literal -> Term m
encodeLiteral = literal

encodeLiteralVariant :: LiteralVariant -> Term m
encodeLiteralVariant av = unitVariant _LiteralVariant $ case av of
  LiteralVariantBinary -> _LiteralVariant_binary
  LiteralVariantBoolean -> _LiteralVariant_boolean
  LiteralVariantFloat -> _LiteralVariant_float
  LiteralVariantInteger -> _LiteralVariant_integer
  LiteralVariantString -> _LiteralVariant_string

encodeMapType :: MapType m -> Term m
encodeMapType (MapType kt vt) = record _MapType [
  Field _MapType_keys $ encodeType kt,
  Field _MapType_values $ encodeType vt]

encodeNamed :: Ord m => Named m -> Term m
encodeNamed (Named (Name name) term) = record _Named [
  Field _Named_typeName $ string name,
  Field _Named_term $ encodeTerm term]

encodeOptionalCases :: Ord m => OptionalCases m -> Term m
encodeOptionalCases (OptionalCases nothing just) = record _OptionalCases [
  Field _OptionalCases_nothing $ encodeTerm nothing,
  Field _OptionalCases_just $ encodeTerm just]

encodeProjection :: Projection -> Term m
encodeProjection (Projection name fname) = record _Projection [
  Field _Projection_typeName $ string (unName name),
  Field _Projection_field $ string (unFieldName fname)]

encodeRowType :: RowType m -> Term m
encodeRowType (RowType name extends fields) = record _RowType [
  Field _RowType_typeName $ string (unName name),
  Field _RowType_extends $ optional (string . unName <$> extends),
  Field _RowType_fields $ list $ encodeFieldType <$> fields]

encodeSum :: Ord m => Sum m -> Term m
encodeSum (Sum i l term) = record _Sum [
  Field _Sum_index $ int32 i,
  Field _Sum_size $ int32 l,
  Field _Sum_term $ encodeTerm term]

encodeTerm :: Ord m => Term m -> Term m
encodeTerm term = case term of
  TermAnnotated (Annotated t ann) -> variant _Term _Term_annotated $ TermAnnotated $ Annotated (encodeTerm t) ann
  TermApplication a -> variant _Term _Term_application $ encodeApplication a
  TermLiteral av -> variant _Term _Term_literal $ encodeLiteral av
  TermElement (Name name) -> variant _Term _Term_element $ string name
  TermFunction f -> variant _Term _Term_function $ encodeFunction f
  TermList terms -> variant _Term _Term_list $ list $ encodeTerm <$> terms
  TermMap m -> variant _Term _Term_map $ map $ M.fromList $ encodePair <$> M.toList m
    where encodePair (k, v) = (encodeTerm k, encodeTerm v)
  TermNominal ntt -> variant _Term _Term_nominal $ encodeNamed ntt
  TermOptional m -> variant _Term _Term_optional $ optional $ encodeTerm <$> m
  TermProduct terms -> variant _Term _Term_product $ list (encodeTerm <$> terms)
  TermRecord (Record _ fields) -> variant _Term _Term_record $ list $ encodeField <$> fields
  TermSet terms -> variant _Term _Term_set $ set $ S.fromList $ encodeTerm <$> S.toList terms
  TermSum s -> variant _Term _Term_sum $ encodeSum s
  TermUnion (Union _ field) -> variant _Term _Term_union $ encodeField field
  TermVariable (Variable var) -> variant _Term _Term_variable $ string var

encodeType :: Type m -> Term m
encodeType typ = case typ of
  TypeAnnotated (Annotated t ann) -> TermAnnotated (Annotated (encodeType t) ann)
  TypeApplication a -> variant _Type _Type_application $ encodeApplicationType a
  TypeElement t -> variant _Type _Type_element $ encodeType t
  TypeFunction ft -> variant _Type _Type_function $ encodeFunctionType ft
  TypeLambda ut -> variant _Type _Type_lambda $ encodeLambdaType ut
  TypeList t -> variant _Type _Type_list $ encodeType t
  TypeLiteral at -> variant _Type _Type_literal $ encodeLiteralType at
  TypeMap mt -> variant _Type _Type_map $ encodeMapType mt
  TypeNominal name -> variant _Type _Type_nominal $ element name
  TypeOptional t -> variant _Type _Type_optional $ encodeType t
  TypeProduct types -> variant _Type _Type_product $ list (encodeType <$> types)
  TypeRecord rt -> variant _Type _Type_record $ encodeRowType rt
  TypeSet t -> variant _Type _Type_set $ encodeType t
  TypeSum types -> variant _Type _Type_sum $ list (encodeType <$> types)
  TypeUnion rt -> variant _Type _Type_union $ encodeRowType rt
  TypeVariable (VariableType var) -> variant _Type _Type_variable $ string var

encodeTypeVariant :: TypeVariant -> Term m
encodeTypeVariant tv = unitVariant _TypeVariant $ case tv of
  TypeVariantAnnotated -> _TypeVariant_annotated
  TypeVariantLiteral -> _TypeVariant_literal
  TypeVariantElement -> _TypeVariant_element
  TypeVariantFunction -> _TypeVariant_function
  TypeVariantList -> _TypeVariant_list
  TypeVariantMap -> _TypeVariant_map
  TypeVariantNominal -> _TypeVariant_nominal
  TypeVariantOptional -> _TypeVariant_optional
  TypeVariantProduct -> _TypeVariant_product
  TypeVariantRecord -> _TypeVariant_record
  TypeVariantSet -> _TypeVariant_set
  TypeVariantSum -> _TypeVariant_sum
  TypeVariantUnion -> _TypeVariant_union
  TypeVariantLambda -> _TypeVariant_lambda
  TypeVariantVariable -> _TypeVariant_variable