module Hydra.Langs.Scala.Utils where

import Hydra.Kernel
import qualified Hydra.Langs.Scala.Meta as Scala
import qualified Hydra.Lib.Strings as Strings
import Hydra.Langs.Scala.Language

import qualified Data.List as L
import qualified Data.Set as S
import qualified Data.Maybe as Y


nameOfType :: Graph -> Type -> Y.Maybe Name
nameOfType :: Graph -> Type -> Maybe Name
nameOfType Graph
cx Type
t = case Type -> Type
stripType Type
t of
  TypeVariable Name
name -> Name -> Maybe Name
forall a. a -> Maybe a
Just Name
name
  TypeLambda (LambdaType Name
_ Type
body) -> Graph -> Type -> Maybe Name
nameOfType Graph
cx Type
body
  Type
_ -> Maybe Name
forall a. Maybe a
Nothing

qualifyUnionFieldName :: String -> Y.Maybe Name -> Name -> String
qualifyUnionFieldName :: String -> Maybe Name -> Name -> String
qualifyUnionFieldName String
dlft Maybe Name
sname (Name String
fname) = (String -> (Name -> String) -> Maybe Name -> String
forall b a. b -> (a -> b) -> Maybe a -> b
Y.maybe String
dlft (\Name
n -> Bool -> Name -> String
scalaTypeName Bool
True Name
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".") Maybe Name
sname) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fname

scalaTypeName :: Bool -> Name -> String
scalaTypeName :: Bool -> Name -> String
scalaTypeName Bool
qualify name :: Name
name@(Name String
n) = if Bool
qualify Bool -> Bool -> Bool
|| String -> Set String -> Bool
forall a. Ord a => a -> Set a -> Bool
S.member String
local Set String
reservedWords
    then String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
L.intercalate String
"." ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String -> String -> [String]
Strings.splitOn String
"/" String
n
    else String
local
  where
    local :: String
local = Name -> String
localNameOfLazy Name
name

sapply :: Scala.Data -> [Scala.Data] -> Scala.Data
sapply :: Data -> [Data] -> Data
sapply Data
fun [Data]
args = Data_Apply -> Data
Scala.DataApply (Data_Apply -> Data) -> Data_Apply -> Data
forall a b. (a -> b) -> a -> b
$ Data -> [Data] -> Data_Apply
Scala.Data_Apply Data
fun [Data]
args

sassign :: Scala.Data -> Scala.Data -> Scala.Data
sassign :: Data -> Data -> Data
sassign Data
lhs Data
rhs = Data_Assign -> Data
Scala.DataAssign (Data_Assign -> Data) -> Data_Assign -> Data
forall a b. (a -> b) -> a -> b
$ Data -> Data -> Data_Assign
Scala.Data_Assign Data
lhs Data
rhs

slambda :: String -> Scala.Data -> Y.Maybe Scala.Type -> Scala.Data
slambda :: String -> Data -> Maybe Type -> Data
slambda String
v Data
body Maybe Type
sdom = Data_FunctionData -> Data
Scala.DataFunctionData (Data_FunctionData -> Data) -> Data_FunctionData -> Data
forall a b. (a -> b) -> a -> b
$ Data_Function -> Data_FunctionData
Scala.Data_FunctionDataFunction
    (Data_Function -> Data_FunctionData)
-> Data_Function -> Data_FunctionData
forall a b. (a -> b) -> a -> b
$ [Data_Param] -> Data -> Data_Function
Scala.Data_Function [[Mod] -> Name -> Maybe Type -> Maybe Data -> Data_Param
Scala.Data_Param [Mod]
forall {a}. [a]
mods Name
name Maybe Type
sdom Maybe Data
forall a. Maybe a
def] Data
body
  where
    mods :: [a]
mods = []
    name :: Name
name = String -> Name
Scala.NameValue String
v
    def :: Maybe a
def = Maybe a
forall a. Maybe a
Nothing

sname :: String -> Scala.Data
sname :: String -> Data
sname = Data_Ref -> Data
Scala.DataRef (Data_Ref -> Data) -> (String -> Data_Ref) -> String -> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Data_Name -> Data_Ref
Scala.Data_RefName (Data_Name -> Data_Ref)
-> (String -> Data_Name) -> String -> Data_Ref
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PredefString -> Data_Name
Scala.Data_Name (PredefString -> Data_Name)
-> (String -> PredefString) -> String -> Data_Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PredefString
Scala.PredefString

sprim :: Name -> Scala.Data
sprim :: Name -> Data
sprim Name
name = String -> Data
sname (String -> Data) -> String -> Data
forall a b. (a -> b) -> a -> b
$ String
prefix String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ QualifiedName -> String
qualifiedNameLocal QualifiedName
qname
  where
    qname :: QualifiedName
qname = Name -> QualifiedName
qualifyNameLazy Name
name
    prefix :: String
prefix = [String] -> String
forall a. HasCallStack => [a] -> a
L.last ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String -> String -> [String]
Strings.splitOn String
"/" (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ Namespace -> String
unNamespace (Namespace -> String) -> Namespace -> String
forall a b. (a -> b) -> a -> b
$ Maybe Namespace -> Namespace
forall a. HasCallStack => Maybe a -> a
Y.fromJust (Maybe Namespace -> Namespace) -> Maybe Namespace -> Namespace
forall a b. (a -> b) -> a -> b
$ QualifiedName -> Maybe Namespace
qualifiedNameNamespace QualifiedName
qname

stapply :: Scala.Type -> [Scala.Type] -> Scala.Type
stapply :: Type -> [Type] -> Type
stapply Type
t [Type]
args = Type_Apply -> Type
Scala.TypeApply (Type_Apply -> Type) -> Type_Apply -> Type
forall a b. (a -> b) -> a -> b
$ Type -> [Type] -> Type_Apply
Scala.Type_Apply Type
t [Type]
args

stapply1 :: Scala.Type -> Scala.Type -> Scala.Type
stapply1 :: Type -> Type -> Type
stapply1 Type
t1 Type
t2 = Type -> [Type] -> Type
stapply Type
t1 [Type
t2]

stapply2 :: Scala.Type -> Scala.Type -> Scala.Type -> Scala.Type
stapply2 :: Type -> Type -> Type -> Type
stapply2 Type
t1 Type
t2 Type
t3 = Type -> [Type] -> Type
stapply Type
t1 [Type
t2, Type
t3]

stparam :: Name -> Scala.Type_Param
stparam :: Name -> Type_Param
stparam (Name String
v) = [Mod]
-> Name
-> [Type_Param]
-> [Type_Bounds]
-> [Type]
-> [Type]
-> Type_Param
Scala.Type_Param [] (String -> Name
Scala.NameValue String
v) [] [] [] []

stref :: String -> Scala.Type
stref :: String -> Type
stref = Type_Ref -> Type
Scala.TypeRef (Type_Ref -> Type) -> (String -> Type_Ref) -> String -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type_Name -> Type_Ref
Scala.Type_RefName (Type_Name -> Type_Ref)
-> (String -> Type_Name) -> String -> Type_Ref
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Type_Name
Scala.Type_Name

svar :: Name -> Scala.Pat
svar :: Name -> Pat
svar (Name String
v) = (Pat_Var -> Pat
Scala.PatVar (Pat_Var -> Pat) -> (String -> Pat_Var) -> String -> Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Data_Name -> Pat_Var
Scala.Pat_Var (Data_Name -> Pat_Var)
-> (String -> Data_Name) -> String -> Pat_Var
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PredefString -> Data_Name
Scala.Data_Name (PredefString -> Data_Name)
-> (String -> PredefString) -> String -> Data_Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PredefString
Scala.PredefString) String
v