packages feed

polyglot-0.1.1.0: src/Conversions/ToScala/Type.hs

module Conversions.ToScala.Type where

import qualified SyntaxTrees.Haskell.Type as H
import qualified SyntaxTrees.Scala.Common as S
import qualified SyntaxTrees.Scala.Type   as S

import Conversions.ToScala.Common (find, qClass, qualifier')

import Data.Char (toUpper)
import Data.Map  (Map)
import Data.Set  (Set)

import qualified Data.Map as Map
import qualified Data.Set as Set



typeParam :: H.TypeParam -> S.TypeParam
typeParam (H.TypeParam x) = S.TypeParam $ toUpper <$> x

typeVar :: H.TypeVar -> S.TypeVar
typeVar (H.TypeVar x) = S.TypeVar $ convertTypeVar x
typeVar H.UnitType    = S.TypeVar "Unit"

typeCtor :: H.TypeCtor -> S.TypeCtor
typeCtor H.Arrow        = S.Arrow
typeCtor H.TupleType    = S.TupleType
typeCtor (H.TypeCtor x) = S.TypeCtor $ convertTypeCtor x
typeCtor H.ListType     = S.TypeCtor "List"

anyKindedType :: H.AnyKindedType -> S.Type
anyKindedType (H.TypeValue x) = type' x
anyKindedType (H.TypeFn (H.QTypeCtor _ H.ListType)) =
  S.CtorTypeApply (S.QTypeCtor Nothing $ S.TypeCtor "List") [S.ExistentialType]
anyKindedType (H.TypeFn (H.QTypeCtor _ H.Arrow)) =
  S.CtorTypeApply (S.QTypeCtor Nothing $ S.TypeCtor "Function2")
                                             [S.ExistentialType, S.ExistentialType]
anyKindedType (H.TypeFn (H.QTypeCtor _ H.TupleType)) =
  S.CtorTypeApply (S.QTypeCtor Nothing $ S.TypeCtor "Tuple2")
                                             [S.ExistentialType, S.ExistentialType]
anyKindedType (H.TypeFn x@(H.QTypeCtor _ _)) = S.CtorTypeApply (qTypeCtor x)
                                             [S.ExistentialType]


classConstraint :: H.ClassConstraint -> S.ClassConstraint
classConstraint (H.ClassConstraint x y) = S.ClassConstraint (qClass x) (type' <$> y)


type' :: H.Type -> S.Type
type' (H.CtorTypeApply x y)   = S.CtorTypeApply (qTypeCtor x) (type' <$> y)
type' (H.ParamTypeApply x y)  = S.ParamTypeApply (typeParam x) (type' <$> y)
type' (H.NestedTypeApply x y) = S.NestedTypeApply (type' x) (type' <$> y)
type' (H.TypeVar' x)          = S.TypeVar' $ qTypeVar x
type' (H.TypeParam' x)        = S.TypeParam' $ typeParam x
type' (H.TypeScope x y)       = S.TypeScope (typeParam <$> x) (type' y)
type' (H.ClassScope x y)      = S.ClassScope (classConstraint <$> x) (type' y)


typeSplit :: Int -> H.Type -> ([S.Type], S.Type)
typeSplit 0 tpe = ([], type' tpe)
typeSplit n tpe = (args, S.CtorTypeApply (S.QTypeCtor Nothing S.Arrow) ret)
  where
    (args, ret) = splitAt (min n (length types - 1)) (type' <$> types)
    types = extractTypes tpe


classScopeSplit :: H.Type -> ([S.ClassConstraint], H.Type)
classScopeSplit (H.ClassScope x y) = (classConstraint <$> x, y)
classScopeSplit x                  = ([], x)


findAnyKindedTypeParams :: H.AnyKindedType -> Set H.TypeParam
findAnyKindedTypeParams (H.TypeValue x) = findTypeParams x
findAnyKindedTypeParams _               = Set.empty


findTypeParams :: H.Type -> Set H.TypeParam
findTypeParams (H.CtorTypeApply _ y)   = mconcat $ findTypeParams <$> y
findTypeParams (H.ParamTypeApply x y)  = (Set.singleton x) <>
                                         (mconcat $ findTypeParams <$> y)
findTypeParams (H.NestedTypeApply x y) = mconcat $ findTypeParams <$> (x : y)
findTypeParams (H.TypeVar' _)          = Set.empty
findTypeParams (H.TypeParam' x)        = Set.singleton x
findTypeParams (H.TypeScope _ _)       = Set.empty
findTypeParams (H.ClassScope _ y)      = findTypeParams y


extractTypes :: H.Type -> [H.Type]
extractTypes (H.CtorTypeApply (H.QTypeCtor _ H.Arrow) y) = y
extractTypes (H.TypeScope _ y)                           = extractTypes y
extractTypes (H.ClassScope _ y)                          = extractTypes y
extractTypes _                                           = []


argLists :: [S.Var] -> [S.Type] -> [S.ArgList]
argLists args argTypes =
  S.ArgList . pure . uncurry (S.ArgField []) <$> zip args argTypes


usingArgList :: [S.ClassConstraint] -> S.UsingArgList
usingArgList constraints =
  S.UsingArgList $ (S.UsingArgField [] Nothing) <$> constraints


qTypeVar :: H.QTypeVar -> S.QTypeVar
qTypeVar (H.QTypeVar x y) = S.QTypeVar (qualifier' <$> x) (typeVar y)

qTypeCtor :: H.QTypeCtor -> S.QTypeCtor
qTypeCtor (H.QTypeCtor x y) = S.QTypeCtor (qualifier' <$> x) (typeCtor y)




convertTypeCtor :: String -> String
convertTypeCtor x =  find typeCtorMap x

convertTypeVar :: String -> String
convertTypeVar x =  find typeVarMap x

typeCtorMap :: Map String String
typeCtorMap = Map.fromList [("Maybe", "Option")]

typeVarMap :: Map String String
typeVarMap = Map.fromList [("Type", "Typex")]