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 :: ModuleDef -> PackageDef
moduleDef (H.ModuleDef Module
x Maybe ModuleExport
_ [ModuleImport]
z [InternalDef]
t) =
  Package -> [PackageImport] -> [InternalDef] -> PackageDef
S.PackageDef (Module -> Package
module' Module
x) (ModuleImport -> [PackageImport]
moduleImport forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [ModuleImport]
z) ([InternalDef] -> [InternalDef]
internalDefs [InternalDef]
t)


moduleImport :: H.ModuleImport -> [S.PackageImport]
moduleImport :: ModuleImport -> [PackageImport]
moduleImport (H.ModuleImport Bool
True Module
x Maybe Module
Nothing Bool
_ [ModuleImportDef]
y) =
  ModuleImport -> [PackageImport]
moduleImport forall a b. (a -> b) -> a -> b
$ Bool
-> Module
-> Maybe Module
-> Bool
-> [ModuleImportDef]
-> ModuleImport
H.ModuleImport Bool
True Module
x (forall a. a -> Maybe a
Just Module
x) Bool
False [ModuleImportDef]
y
moduleImport (H.ModuleImport Bool
x Module
y Maybe Module
z Bool
_ []) =
  [Package -> Maybe Package -> Maybe PackageImportDef -> PackageImport
S.PackageImport (Module -> Package
module' Module
y) (Module -> Package
qualifier' forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Module
z)
   (forall a. Bool -> a -> Maybe a
cond (Bool -> Bool
not Bool
x) PackageImportDef
S.FullImport)]
moduleImport (H.ModuleImport Bool
x Module
y Maybe Module
z Bool
_ [ModuleImportDef]
t) =
  Package -> Maybe Package -> Maybe PackageImportDef -> PackageImport
S.PackageImport (Module -> Package
module' Module
y) (Module -> Package
qualifier' forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Module
z) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bool -> a -> Maybe a
cond (Bool -> Bool
not Bool
x))
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ModuleImportDef] -> [PackageImportDef]
moduleImportDefs [ModuleImportDef]
t

moduleImportDefs :: [H.ModuleImportDef] -> [S.PackageImportDef]
moduleImportDefs :: [ModuleImportDef] -> [PackageImportDef]
moduleImportDefs [ModuleImportDef]
importDefs = forall a. Maybe a -> [a]
maybeToList Maybe PackageImportDef
combined forall a. [a] -> [a] -> [a]
++ [PackageImportDef]
singles
  where
    combined :: Maybe PackageImportDef
combined = [PackageMember] -> PackageImportDef
S.MembersImport forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) a. Foldable t => t a -> Maybe (t a)
wrapMaybe (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ModuleImportDef -> Maybe PackageMember
singleImportDef [ModuleImportDef]
importDefs)
    singles :: [PackageImportDef]
singles = forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ModuleImportDef -> Maybe PackageImportDef
complexImportDef [ModuleImportDef]
importDefs


complexImportDef :: H.ModuleImportDef -> Maybe S.PackageImportDef
complexImportDef :: ModuleImportDef -> Maybe PackageImportDef
complexImportDef (H.ModuleImportDef (H.FullData TypeVar
x)) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ TypeVar -> PackageImportDef
S.FullObjectImport forall a b. (a -> b) -> a -> b
$ TypeVar -> TypeVar
typeVar TypeVar
x
complexImportDef (H.ModuleImportDef (H.FilteredData TypeVar
x [ModuleMember]
y)) =
  TypeVar -> [PackageMember] -> PackageImportDef
S.FilteredObjectImport (TypeVar -> TypeVar
typeVar TypeVar
x) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) a. Foldable t => t a -> Maybe (t a)
wrapMaybe (ModuleMember -> PackageMember
moduleMember forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ModuleMember]
y)
complexImportDef ModuleImportDef
_ = forall a. Maybe a
Nothing


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


internalDefs :: [H.InternalDef] -> [S.InternalDef]
internalDefs :: [InternalDef] -> [InternalDef]
internalDefs [InternalDef]
defs =
  (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe InternalDef -> Maybe InternalDef
internalDef [InternalDef]
others) forall a. [a] -> [a] -> [a]
++
  (InternalFnDef -> InternalDef
S.Fn forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe FnSig, Maybe [FnDef]) -> InternalFnDef
fnDefs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FnDefOrSig] -> [(Maybe FnSig, Maybe [FnDef])]
fnDefOrSigs [FnDefOrSig]
fns)

  where
    fns :: [FnDefOrSig]
fns    = forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\case (H.FnDefOrSig' FnDefOrSig
x) -> forall a. a -> Maybe a
Just FnDefOrSig
x
                             InternalDef
_                 -> forall a. Maybe a
Nothing) [InternalDef]
defs

    others :: [InternalDef]
others = forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\case (H.FnDefOrSig' FnDefOrSig
_) -> forall a. Maybe a
Nothing
                             InternalDef
x                 -> forall a. a -> Maybe a
Just InternalDef
x) [InternalDef]
defs

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

moduleMember :: H.ModuleMember -> S.PackageMember
moduleMember :: ModuleMember -> PackageMember
moduleMember (H.VarMember Var
x)   = Var -> PackageMember
S.VarMember forall a b. (a -> b) -> a -> b
$ Var -> Var
var Var
x
moduleMember (H.VarOpMember VarOp
x) = VarOp -> PackageMember
S.VarOpMember forall a b. (a -> b) -> a -> b
$ VarOp -> VarOp
varOp VarOp
x
moduleMember (H.DataMember TypeVar
x)  = TypeVar -> PackageMember
S.DataMember forall a b. (a -> b) -> a -> b
$ TypeVar -> TypeVar
typeVar TypeVar
x