packages feed

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

module Conversions.ToScala.ModuleDef where

import qualified SyntaxTrees.Haskell.ModuleDef as H
import qualified SyntaxTrees.Scala.DataDef     as S
import qualified SyntaxTrees.Scala.FnDef       as S
import qualified SyntaxTrees.Scala.PackageDef  as S

import Conversions.ToScala.ClassDef (classDef, derivingDef, instanceDef)
import Conversions.ToScala.Common   (module', qualifier', var, varOp)
import Conversions.ToScala.DataDef  (dataDef, newtypeDef, typeDef)
import Conversions.ToScala.FnDef    (fnDefOrSigs, fnDefs)
import Conversions.ToScala.Type     (typeVar)

import Data.Maybe     (mapMaybe, maybeToList)
import Utils.Foldable (wrapMaybe)
import Utils.Maybe    (cond)



moduleDef :: H.ModuleDef -> S.PackageDef
moduleDef (H.ModuleDef x _ z t) =
  S.PackageDef (module' x) (moduleImport =<< z) (internalDefs t)


moduleImport :: H.ModuleImport -> [S.PackageImport]
moduleImport (H.ModuleImport True x Nothing _ y) =
  moduleImport $ H.ModuleImport True x (Just x) False y
moduleImport (H.ModuleImport x y z _ []) =
  [S.PackageImport (module' y) (qualifier' <$> z)
   (cond (not x) S.FullImport)]
moduleImport (H.ModuleImport x y z _ t) =
  S.PackageImport (module' y) (qualifier' <$> z) . (cond (not x))
  <$> moduleImportDefs t

moduleImportDefs :: [H.ModuleImportDef] -> [S.PackageImportDef]
moduleImportDefs importDefs = maybeToList combined ++ singles
  where
    combined = S.MembersImport <$> wrapMaybe (mapMaybe singleImportDef importDefs)
    singles = mapMaybe complexImportDef importDefs


complexImportDef :: H.ModuleImportDef -> Maybe S.PackageImportDef
complexImportDef (H.ModuleImportDef (H.FullData x)) =
  Just $ S.FullObjectImport $ typeVar x
complexImportDef (H.ModuleImportDef (H.FilteredData x y)) =
  S.FilteredObjectImport (typeVar x) <$> wrapMaybe (moduleMember <$> y)
complexImportDef _ = Nothing


singleImportDef :: H.ModuleImportDef -> Maybe S.PackageMember
singleImportDef (H.ModuleImportDef (H.Member x)) = Just $ moduleMember x
singleImportDef _                                = Nothing


internalDefs :: [H.InternalDef] -> [S.InternalDef]
internalDefs defs =
  (mapMaybe internalDef others) ++
  (S.Fn . fnDefs <$> fnDefOrSigs fns)

  where
    fns    = mapMaybe (\case (H.FnDefOrSig' x) -> Just x
                             _                 -> Nothing) defs

    others = mapMaybe (\case (H.FnDefOrSig' _) -> Nothing
                             x                 -> Just x) defs

internalDef :: H.InternalDef -> Maybe S.InternalDef
internalDef (H.TypeDef' x)           = Just $ S.TypeAlias $ typeDef x
internalDef (H.NewTypeDef' x)        = Just $ S.OpaqueType $ newtypeDef x
internalDef (H.DataDef' x)           = Just $ S.Enum $ dataDef x
internalDef (H.ClassDef' x)          = Just $ S.Trait $ classDef x
internalDef (H.InstanceDef' x)       = Just $ S.Fn $ S.FnGiven $ instanceDef x
internalDef (H.DerivingDef' x)       = Just $ S.Fn $ S.FnGiven $ derivingDef x
internalDef (H.FnDefOrSig' _)        = Nothing
internalDef (H.InfixFnAnnotation' _) = Nothing

moduleMember :: H.ModuleMember -> S.PackageMember
moduleMember (H.VarMember x)   = S.VarMember $ var x
moduleMember (H.VarOpMember x) = S.VarOpMember $ varOp x
moduleMember (H.DataMember x)  = S.DataMember $ typeVar x