polyglot-0.1.1.0: src/SyntaxTrees/Scala/FnDef.hs
module SyntaxTrees.Scala.FnDef where
import Data.Foldable (Foldable (fold))
import Data.Monoid.HT (when)
import SyntaxTrees.Scala.Common (Literal, Modifier, QCtor, QCtorOp, QVar,
QVarOp, Var)
import SyntaxTrees.Scala.Pattern (Pattern)
import SyntaxTrees.Scala.Type (ArgList, Type, TypeParam,
UsingArgList (UsingArgList))
import Data.List (intercalate)
import Conversions.ToScala.Pattern (allVars')
import Utils.Foldable (hasSome, wrapMaybe)
import Utils.String
data FnSig
= FnSig
{ typeParams :: [TypeParam]
, argLists :: [ArgList]
, usingArgs :: [UsingArgList]
, returnType :: Maybe Type
}
data ValDef
= ValDef
{ qualifiers :: [Modifier]
, names :: [Var]
, returnType :: Maybe Type
, body :: Maybe FnBody
}
data MethodDef
= MethodDef
{ qualifiers :: [Modifier]
, name :: Var
, sig :: Maybe FnSig
, body :: Maybe FnBody
}
data GivenDef
= GivenDef
{ qualifiers :: [Modifier]
, name :: Maybe Var
, typeParams :: [TypeParam]
, usingArgs :: [UsingArgList]
, returnType :: Type
, bodyOrDefs :: Either FnBody [InternalFnDef]
}
data FnBody
= FnApply
{ fn :: FnBody
, args :: [FnBody]
}
| NamedFnApply
{ fn :: FnBody
, namedArgs :: [(Var, FnBody)]
}
| InfixFnApply
{ fnOps :: [FnOp]
, args :: [FnBody]
}
| LambdaExpr
{ patterns :: [Pattern]
, body :: FnBody
}
| LetExpr
{ fnBindings :: [InternalFnDef]
, body :: FnBody
}
| IfExpr
{ cond :: FnBody
, ifBranch :: FnBody
, elseBranch :: FnBody
}
| CondExpr
{ whenBranches :: [WhenExpr]
, elseBranch :: FnBody
}
| ForExpr
{ steps :: [ForStep]
, yield :: FnBody
}
| MatchExpr
{ matchee :: FnBody
, cases :: [CaseBinding]
}
| TopLevelMatchExpr
{ cases :: [CaseBinding]
}
| BodySelection FnBody [Var]
| Tuple [FnBody]
| FnOp' FnOp
| FnVar' FnVar
| Literal' Literal
data FnVar
= Selection QVar [Var]
| Var' QVar
| Ctor' QCtor
data FnOp
= VarOp' QVarOp
| CtorOp' QCtorOp
data ForStep
= ForBinding [Var] FnBody
| LetBinding [InternalFnDef]
| Condition FnBody
data CaseBinding
= CaseBinding
{ pattern' :: Pattern
, guard :: Maybe FnBody
, body :: FnBody
}
data InternalFnDef
= FnVal ValDef
| FnMethod MethodDef
| FnGiven GivenDef
data WhenExpr
= WhenExpr
{ cond :: FnBody
, body :: FnBody
}
instance Show FnSig where
show (FnSig x y z t) =
("" `joinMaybe`
(Wrapper <$> wrapMaybe (joinWords [wrapSquareCsv x,
str " " y,
str " " z])))
++ ":" `joinMaybe` t
instance Show ValDef where
show (ValDef x y z t) =
joinWords [str " " x,
"val",
showVal y z t]
instance Show MethodDef where
show (MethodDef x y z t) =
joinWords [str " " x,
"def",
showDef y z t]
instance Show GivenDef where
show (GivenDef x y z t u v) =
joinWords [str " " x,
"given",
showGiven y z t u v]
instance Show FnBody where
show (FnApply x y)
| (FnVar' (Ctor' _)) <- x = joinWords [show x, wrapParensCsv y]
| otherwise = joinWords [show x,
joinWords $ wrapParens . show <$> y]
show (NamedFnApply x y) = joinWords [show x, wrapParensCsv $ Wrapper .
(\(a, b) -> show a +++ "=" +++ show b) <$> y]
show (InfixFnApply x [y]) = showForInfix y +++ foldMap show x
show (InfixFnApply x y) = strs (wrapSpaces . show <$> x)
(showForInfix <$> y)
show (BodySelection x y) = intercalate "." (show x : (show <$> y))
show (LambdaExpr [] y) = wrapParens $ show y
show (LambdaExpr [x] y)
| allVars' [x] = wrapParens $ joinWords [show x, "=>", show y]
show (LambdaExpr x y)
| allVars' x = wrapParens $ joinWords [wrapParensCsv x, "=>", show y]
| otherwise = wrapCurly $ joinWords ["case", wrapParensCsv x,
"=>", show y]
show (LetExpr x y) = wrapLetContext x y
show (Tuple [x]) = show x
show (Tuple x) = wrapParensCsv x
show (FnOp' x) = wrapParens $ show x
show (FnVar' x) = show x
show (Literal' x) = show x
show (IfExpr x y z) = joinWords ["if", show x,
"then", show y,
"else", show z]
show (CondExpr x y) = str ("\n" +++ wrapSpaces "else")
(Wrapper <$> ((show <$> x) ++ [show y]))
show (ForExpr x y) = joinWords ["for",
wrapBlock x,
"yield",
show y]
show (MatchExpr x y) = joinWords [show x,
"match",
wrapBlock y]
show (TopLevelMatchExpr x) = wrapBlock x
instance Show ForStep where
show (ForBinding x y) = joinWords [showTuple x, "<-", show y]
show (LetBinding x) = unlines (showBinding <$> x)
show (Condition x) = joinWords ["if", show x]
instance Show CaseBinding where
show (CaseBinding x y z) = joinWords ["case", show x,
"if" `joinMaybe` y,
"=>", show z]
instance Show WhenExpr where
show (WhenExpr x y) = joinWords ["if", show x,
"then", show y]
instance Show FnVar where
show (Selection x y) = intercalate "." (show x : (show <$> y))
show (Var' x) = show x
show (Ctor' x) = show x
instance Show FnOp where
show (VarOp' x) = show x
show (CtorOp' x) = show x
instance Show InternalFnDef where
show (FnVal x) = show x
show (FnMethod x) = show x
show (FnGiven x) = show x
showBinding :: InternalFnDef -> String
showBinding (FnVal (ValDef _ y _ t)) = showVal y Nothing t
showBinding (FnMethod (MethodDef _ y _ t)) = showDef y Nothing t
showBinding (FnGiven (GivenDef _ y z t u v)) = showGiven y z t u v
showForInfix :: FnBody -> String
showForInfix x@(InfixFnApply _ _) = wrapParens $ show x
showForInfix x = show x
showVal :: [Var] -> Maybe Type -> Maybe FnBody -> String
showVal x y z = showTuple x ++ ":" `joinMaybe` y
+++ "=" `joinMaybe` z
showDef :: Var -> Maybe FnSig -> Maybe FnBody -> String
showDef x y z = show x ++ (fold $ show <$> y)
+++ "=" `joinMaybe` (Wrapper . wrapSingleBlock <$> z)
showGiven :: Maybe Var -> [TypeParam] -> [UsingArgList]
-> Type -> Either FnBody [InternalFnDef] -> String
showGiven x y z t u = joinWords [foldMap show x,
wrapSquareCsv y,
str " " z,
when displaySep ":",
show t]
++ case u of
Left body -> joinWords ["=",
show body]
Right defs -> joinWords ["with",
wrapSpacedBlock defs]
where
displaySep = hasSome x || hasSome y || hasSome (foldMap fields z)
fields (UsingArgList h) = h
showTuple :: Show a => [a] -> String
showTuple [x] = show x
showTuple x = wrapParens $ str ", " x