module Hydra.Langs.Scala.Serde where
import Hydra.Ast
import Hydra.Tools.Serialization
import qualified Hydra.Lib.Literals as Literals
import qualified Hydra.Langs.Scala.Meta as Scala
import qualified Data.List as L
import qualified Data.Maybe as Y
dotOp :: Op
dotOp :: Op
dotOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
Symbol String
".") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsNone) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityLeft
functionArrowOp :: Op
functionArrowOp :: Op
functionArrowOp = String -> Int -> Associativity -> Op
op String
"=>" (Int -> Int
forall a. Num a => a -> a
negate Int
1) Associativity
AssociativityRight
matchOp :: Op
matchOp :: Op
matchOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
Symbol String
"match") (Ws -> Ws -> Padding
Padding Ws
WsSpace (Ws -> Padding) -> Ws -> Padding
forall a b. (a -> b) -> a -> b
$ String -> Ws
WsBreakAndIndent String
" ") (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
writeCase :: Scala.Case -> Expr
writeCase :: Case -> Expr
writeCase (Scala.Case Pat
pat Maybe Data
_ Data
term) = [Expr] -> Expr
spaceSep [String -> Expr
cst String
"case", Pat -> Expr
writePat Pat
pat, String -> Expr
cst String
"=>", Data -> Expr
writeTerm Data
term]
writeDefn :: Scala.Defn -> Expr
writeDefn :: Defn -> Expr
writeDefn Defn
def = case Defn
def of
Scala.DefnDef (Scala.Defn_Def [Mod]
_ Data_Name
name [Type_Param]
tparams [[Data_Param]
params] Maybe Type
scod Data
body) -> [Expr] -> Expr
spaceSep [
String -> Expr
cst String
"def", Expr
nameAndParams, String -> Expr
cst String
"=", Data -> Expr
writeTerm Data
body]
where
nameAndParams :: Expr
nameAndParams = [Expr] -> Expr
noSep ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ [Maybe Expr] -> [Expr]
forall a. [Maybe a] -> [a]
Y.catMaybes [
Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ Data_Name -> Expr
writeData_Name Data_Name
name,
if [Type_Param] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
L.null [Type_Param]
tparams then Maybe Expr
forall a. Maybe a
Nothing else Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
bracketList BlockStyle
inlineStyle (Type_Param -> Expr
writeType_Param (Type_Param -> Expr) -> [Type_Param] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type_Param]
tparams),
Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ Bool -> [Expr] -> Expr
parenList Bool
False (Data_Param -> Expr
writeData_Param (Data_Param -> Expr) -> [Data_Param] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Data_Param]
params),
(Type -> Expr) -> Maybe Type -> Maybe Expr
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Type
t -> [Expr] -> Expr
spaceSep [String -> Expr
cst String
":", Type -> Expr
writeType Type
t]) Maybe Type
scod]
Scala.DefnVal (Scala.Defn_Val [Mod]
_ [Scala.PatVar (Scala.Pat_Var (Scala.Data_Name (Scala.PredefString String
name)))] Maybe Type
typ Data
term) -> [Expr] -> Expr
spaceSep [
String -> Expr
cst String
"val", Expr
nameAndType, String -> Expr
cst String
"=", Data -> Expr
writeTerm Data
term]
where
nameAndType :: Expr
nameAndType = Expr -> (Type -> Expr) -> Maybe Type -> Expr
forall b a. b -> (a -> b) -> Maybe a -> b
Y.maybe (String -> Expr
cst String
name) (\Type
t -> [Expr] -> Expr
spaceSep [String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", Type -> Expr
writeType Type
t]) Maybe Type
typ
writeImportExportStat :: Scala.ImportExportStat -> Expr
writeImportExportStat :: ImportExportStat -> Expr
writeImportExportStat ImportExportStat
ie = case ImportExportStat
ie of
Scala.ImportExportStatImport (Scala.Import [Importer]
importers) -> [Expr] -> Expr
newlineSep (Importer -> Expr
writeImporter (Importer -> Expr) -> [Importer] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Importer]
importers)
writeImporter :: Scala.Importer -> Expr
writeImporter :: Importer -> Expr
writeImporter (Scala.Importer (Scala.Data_RefName (Scala.Data_Name (Scala.PredefString String
ref))) [Importee]
importees) = [Expr] -> Expr
spaceSep [
String -> Expr
cst String
"import", [Expr] -> Expr
noSep [String -> Expr
cst String
ref, [Importee] -> Expr
forImportees [Importee]
importees]]
where
forImportee :: Importee -> Expr
forImportee Importee
it = String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ case Importee
it of
Importee
Scala.ImporteeWildcard -> String
"*"
Scala.ImporteeName (Scala.Importee_Name (Scala.NameValue String
name)) -> String
name
forImportees :: [Importee] -> Expr
forImportees [Importee]
its = if [Importee] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
L.null [Importee]
its
then String -> Expr
cst String
""
else if [Importee] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
L.length [Importee]
its Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
then [Expr] -> Expr
noSep [String -> Expr
cst String
".", Importee -> Expr
forImportee (Importee -> Expr) -> Importee -> Expr
forall a b. (a -> b) -> a -> b
$ [Importee] -> Importee
forall a. HasCallStack => [a] -> a
L.head [Importee]
its]
else [Expr] -> Expr
noSep [String -> Expr
cst String
".", Maybe String -> BlockStyle -> [Expr] -> Expr
curlyBracesList Maybe String
forall a. Maybe a
Nothing BlockStyle
inlineStyle (Importee -> Expr
forImportee (Importee -> Expr) -> [Importee] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Importee]
its)]
writeLit :: Scala.Lit -> Expr
writeLit :: Lit -> Expr
writeLit Lit
lit = case Lit
lit of
Scala.LitInt Int
i -> String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ Int -> String
Literals.showInt32 Int
i
Scala.LitBoolean Bool
b -> String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ if Bool
b then String
"true" else String
"false"
Lit
Scala.LitUnit -> String -> Expr
cst String
"()"
Scala.LitString String
s -> String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String -> String
Literals.showString String
s
Lit
_ -> String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String -> String
Literals.showString (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"TODO:literal:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Lit -> String
forall a. Show a => a -> String
show Lit
lit
writeName :: Scala.Name -> Expr
writeName :: Name -> Expr
writeName Name
name = case Name
name of
Scala.NameValue String
s -> String -> Expr
cst String
s
writePat :: Scala.Pat -> Expr
writePat :: Pat -> Expr
writePat Pat
pat = case Pat
pat of
Scala.PatExtract (Scala.Pat_Extract Data
fun [Pat]
args) -> [Expr] -> Expr
noSep [Data -> Expr
writeTerm Data
fun, Bool -> [Expr] -> Expr
parenList Bool
False (Pat -> Expr
writePat (Pat -> Expr) -> [Pat] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Pat]
args)]
Scala.PatVar (Scala.Pat_Var Data_Name
tname) -> Data_Name -> Expr
writeData_Name Data_Name
tname
writePkg :: Scala.Pkg -> Expr
writePkg :: Pkg -> Expr
writePkg (Scala.Pkg Data_Name
name Data_Ref
_ [Stat]
stats) = [Expr] -> Expr
doubleNewlineSep ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ Expr
packageExpr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
:(Stat -> Expr
writeStat (Stat -> Expr) -> [Stat] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Stat]
stats)
where
package :: Expr
package = [Expr] -> Expr
spaceSep [String -> Expr
cst String
"package", Data_Name -> Expr
writeData_Name Data_Name
name]
writeStat :: Scala.Stat -> Expr
writeStat :: Stat -> Expr
writeStat Stat
stat = case Stat
stat of
Scala.StatDefn Defn
def -> Defn -> Expr
writeDefn Defn
def
Scala.StatImportExport ImportExportStat
ie -> ImportExportStat -> Expr
writeImportExportStat ImportExportStat
ie
writeTerm :: Scala.Data -> Expr
writeTerm :: Data -> Expr
writeTerm Data
term = case Data
term of
Scala.DataLit Lit
lit -> Lit -> Expr
writeLit Lit
lit
Scala.DataRef Data_Ref
ref -> Data_Ref -> Expr
writeData_Ref Data_Ref
ref
Scala.DataApply (Scala.Data_Apply Data
fun [Data]
args) -> [Expr] -> Expr
noSep [Data -> Expr
writeTerm Data
fun, Bool -> [Expr] -> Expr
parenList Bool
False (Data -> Expr
writeTerm (Data -> Expr) -> [Data] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Data]
args)]
Scala.DataAssign Data_Assign
assign -> String -> Expr
cst String
">ASSIGN"
Scala.DataTuple (Scala.Data_Tuple [Data]
args) -> Bool -> [Expr] -> Expr
parenList Bool
False (Data -> Expr
writeTerm (Data -> Expr) -> [Data] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Data]
args)
Scala.DataMatch (Scala.Data_Match Data
expr [Case]
cases) -> Op -> Expr -> Expr -> Expr
ifx Op
matchOp (Data -> Expr
writeTerm Data
expr) (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ [Expr] -> Expr
newlineSep (Case -> Expr
writeCase (Case -> Expr) -> [Case] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Case]
cases)
Scala.DataFunctionData Data_FunctionData
ft -> Data_FunctionData -> Expr
writeData_FunctionData Data_FunctionData
ft
writeData_FunctionData :: Scala.Data_FunctionData -> Expr
writeData_FunctionData :: Data_FunctionData -> Expr
writeData_FunctionData Data_FunctionData
ft = case Data_FunctionData
ft of
Scala.Data_FunctionDataFunction (Scala.Data_Function [Data_Param]
params Data
body) ->
[Expr] -> Expr
spaceSep [Bool -> [Expr] -> Expr
parenList Bool
False (Data_Param -> Expr
writeData_Param (Data_Param -> Expr) -> [Data_Param] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Data_Param]
params), String -> Expr
cst String
"=>", Data -> Expr
writeTerm Data
body]
writeData_Name :: Scala.Data_Name -> Expr
writeData_Name :: Data_Name -> Expr
writeData_Name (Scala.Data_Name (Scala.PredefString String
name)) = String -> Expr
cst String
name
writeData_Param :: Scala.Data_Param -> Expr
writeData_Param :: Data_Param -> Expr
writeData_Param (Scala.Data_Param [Mod]
_ Name
name Maybe Type
stype Maybe Data
_) = [Expr] -> Expr
noSep ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ [Maybe Expr] -> [Expr]
forall a. [Maybe a] -> [a]
Y.catMaybes [
Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ Name -> Expr
writeName Name
name,
(Type -> Expr) -> Maybe Type -> Maybe Expr
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Type
t -> [Expr] -> Expr
spaceSep [String -> Expr
cst String
":", Type -> Expr
writeType Type
t]) Maybe Type
stype]
writeData_Ref :: Scala.Data_Ref -> Expr
writeData_Ref :: Data_Ref -> Expr
writeData_Ref Data_Ref
ref = case Data_Ref
ref of
Scala.Data_RefName Data_Name
name -> Data_Name -> Expr
writeData_Name Data_Name
name
Scala.Data_RefSelect Data_Select
sel -> Data_Select -> Expr
writeData_Select Data_Select
sel
writeData_Select :: Scala.Data_Select -> Expr
writeData_Select :: Data_Select -> Expr
writeData_Select (Scala.Data_Select Data
arg Data_Name
name) = Op -> Expr -> Expr -> Expr
ifx Op
dotOp (Data -> Expr
writeTerm Data
arg) (Data -> Expr
writeTerm Data
proj)
where
proj :: Data
proj = Data_Ref -> Data
Scala.DataRef (Data_Ref -> Data) -> Data_Ref -> Data
forall a b. (a -> b) -> a -> b
$ Data_Name -> Data_Ref
Scala.Data_RefName Data_Name
name
writeType :: Scala.Type -> Expr
writeType :: Type -> Expr
writeType Type
typ = case Type
typ of
Scala.TypeRef (Scala.Type_RefName Type_Name
name) -> Type_Name -> Expr
writeType_Name Type_Name
name
Scala.TypeApply (Scala.Type_Apply Type
fun [Type]
args) -> [Expr] -> Expr
noSep [Type -> Expr
writeType Type
fun, BlockStyle -> [Expr] -> Expr
bracketList BlockStyle
inlineStyle (Type -> Expr
writeType (Type -> Expr) -> [Type] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type]
args)]
Scala.TypeFunctionType (Scala.Type_FunctionTypeFunction (Scala.Type_Function [Type
dom] Type
cod)) -> Op -> Expr -> Expr -> Expr
ifx Op
functionArrowOp (Type -> Expr
writeType Type
dom) (Type -> Expr
writeType Type
cod)
Scala.TypeLambda (Scala.Type_Lambda [Type_Param]
params Type
body) -> [Expr] -> Expr
noSep [Type -> Expr
writeType Type
body, BlockStyle -> [Expr] -> Expr
bracketList BlockStyle
inlineStyle (Type_Param -> Expr
writeType_Param (Type_Param -> Expr) -> [Type_Param] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type_Param]
params)]
Scala.TypeVar (Scala.Type_Var Type_Name
name) -> Type_Name -> Expr
writeType_Name Type_Name
name
Type
_ -> String -> Expr
cst (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String
"UNKNOWN TYPE: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
forall a. Show a => a -> String
show Type
typ
writeType_Name :: Scala.Type_Name -> Expr
writeType_Name :: Type_Name -> Expr
writeType_Name (Scala.Type_Name String
name) = String -> Expr
cst String
name
writeType_Param :: Scala.Type_Param -> Expr
writeType_Param :: Type_Param -> Expr
writeType_Param (Scala.Type_Param [] Name
n [] [] [] []) = Name -> Expr
writeName Name
n