{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}

module Language.Ginger.Render
where

import Language.Ginger.AST
import Language.Ginger.Value

import Data.Bool (bool)
import Data.Char (isControl, ord)
import Data.List (intersperse)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Lazy as LText
import Data.Text.Lazy.Builder (Builder)
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Vector as V
import Text.Printf (printf)
import qualified Data.Map.Strict as Map

class RenderSyntax a where
  renderSyntax :: a -> Builder

renderSyntaxLText :: RenderSyntax a => a -> LText.Text
renderSyntaxLText :: forall a. RenderSyntax a => a -> Text
renderSyntaxLText = Builder -> Text
Builder.toLazyText (Builder -> Text) -> (a -> Builder) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax

renderSyntaxText :: RenderSyntax a => a -> Text
renderSyntaxText :: forall a. RenderSyntax a => a -> Text
renderSyntaxText = Text -> Text
LText.toStrict (Text -> Text) -> (a -> Text) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. RenderSyntax a => a -> Text
renderSyntaxLText

renderStringLit :: Text -> Builder
renderStringLit :: Text -> Builder
renderStringLit Text
str =
  Builder
"\"" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ((Char -> Builder) -> String -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Builder
renderStringLitChar (String -> [Builder]) -> String -> [Builder]
forall a b. (a -> b) -> a -> b
$ Text -> String
Text.unpack Text
str) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\""

renderStringLitChar :: Char -> Builder
renderStringLitChar :: Char -> Builder
renderStringLitChar Char
'\0' = Builder
"\\0"
renderStringLitChar Char
'\a' = Builder
"\\a"
renderStringLitChar Char
'\b' = Builder
"\\b"
renderStringLitChar Char
'\f' = Builder
"\\f"
renderStringLitChar Char
'\n' = Builder
"\\n"
renderStringLitChar Char
'\r' = Builder
"\\r"
renderStringLitChar Char
'\t' = Builder
"\\t"
renderStringLitChar Char
'\v' = Builder
"\\v"
renderStringLitChar Char
'"' = Builder
"\\\""
renderStringLitChar Char
'\'' = Builder
"\\'"
renderStringLitChar Char
'\\' = Builder
"\\\\"
renderStringLitChar Char
c
  | Char -> Bool
isControl Char
c Bool -> Bool -> Bool
|| Char -> Int
ord Char
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
128
  = Char -> Builder
renderUnicodeEscape Char
c
  | Bool
otherwise = String -> Builder
Builder.fromString [Char
c]

renderUnicodeEscape :: Char -> Builder
renderUnicodeEscape :: Char -> Builder
renderUnicodeEscape Char
c =
  let o :: Int
o = Char -> Int
ord Char
c
      format :: String
format = if Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xFF then
                  String
"\\x%02x"
               else if Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xFFFF then
                  String
"\\u%04x"
               else
                  String
"\\U%08x"
  in
    String -> Builder
Builder.fromString (String -> Builder) -> String -> Builder
forall a b. (a -> b) -> a -> b
$ String -> Int -> String
forall r. PrintfType r => String -> r
printf String
format Int
o

valueToExpr :: Value m -> Expr
valueToExpr :: forall (m :: * -> *). Value m -> Expr
valueToExpr (StringV Text
v) = Text -> Expr
StringLitE Text
v
valueToExpr Value m
TrueV = Expr
TrueE
valueToExpr Value m
FalseV = Expr
FalseE
valueToExpr (IntV Integer
i) = Integer -> Expr
IntLitE Integer
i
valueToExpr (FloatV Double
f) = Double -> Expr
FloatLitE Double
f
valueToExpr Value m
NoneV = Expr
NoneE
valueToExpr (ScalarV Scalar
s) = String -> Expr
forall a. HasCallStack => String -> a
error (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String
"Not matched: scalar " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Scalar -> String
forall a. Show a => a -> String
show Scalar
s
valueToExpr (ListV Vector (Value m)
items) = Vector Expr -> Expr
ListE (Vector Expr -> Expr) -> Vector Expr -> Expr
forall a b. (a -> b) -> a -> b
$ (Value m -> Expr) -> Vector (Value m) -> Vector Expr
forall a b. (a -> b) -> Vector a -> Vector b
V.map Value m -> Expr
forall (m :: * -> *). Value m -> Expr
valueToExpr Vector (Value m)
items
valueToExpr (DictV Map Scalar (Value m)
xs) =
  [(Expr, Expr)] -> Expr
DictE
    [ (Value Any -> Expr
forall (m :: * -> *). Value m -> Expr
valueToExpr (Scalar -> Value Any
forall (m :: * -> *). Scalar -> Value m
ScalarV Scalar
k), Value m -> Expr
forall (m :: * -> *). Value m -> Expr
valueToExpr Value m
v)
    | (Scalar
k, Value m
v) <- Map Scalar (Value m) -> [(Scalar, Value m)]
forall k a. Map k a -> [(k, a)]
Map.toAscList Map Scalar (Value m)
xs
    ]
valueToExpr (NativeV NativeObject m
_) = Text -> Expr
StringLitE Text
"<<native>>"
valueToExpr (ProcedureV Procedure m
_) = Text -> Expr
StringLitE Text
"<<procedure>>"
valueToExpr (TestV Test m
_) = Text -> Expr
StringLitE Text
"<<test>>"
valueToExpr (FilterV Filter m
_) = Text -> Expr
StringLitE Text
"<<filter>>"
valueToExpr (MutableRefV (RefID Int
i)) = Text -> Expr
StringLitE (Text -> Expr) -> Text -> Expr
forall a b. (a -> b) -> a -> b
$ Text
"<<ref" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
Text.show Int
i Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
">>"

instance RenderSyntax (Value m) where
  renderSyntax :: Value m -> Builder
renderSyntax = Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax (Expr -> Builder) -> (Value m -> Expr) -> Value m -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value m -> Expr
forall (m :: * -> *). Value m -> Expr
valueToExpr

instance RenderSyntax SetTarget where
  renderSyntax :: SetTarget -> Builder
renderSyntax (SetVar Identifier
name) = Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name
  renderSyntax (SetMutable Identifier
name Identifier
attr) =
    Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"." Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
attr

instance RenderSyntax Expr where
  renderSyntax :: Expr -> Builder
renderSyntax (PositionedE SourcePosition
_ Expr
e) = Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
e
  renderSyntax Expr
NoneE = Builder
"none"
  renderSyntax Expr
TrueE = Builder
"true"
  renderSyntax Expr
FalseE = Builder
"false"
  renderSyntax (StatementE (InterpolationS Expr
e)) =
    Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
e
  renderSyntax (StatementE (IfS Expr
cond Statement
yes Maybe Statement
noMay)) =
    Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax (Expr -> Expr -> Expr -> Expr
TernaryE Expr
cond (Statement -> Expr
StatementE Statement
yes) (Expr -> (Statement -> Expr) -> Maybe Statement -> Expr
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Expr
NoneE Statement -> Expr
StatementE Maybe Statement
noMay))
  renderSyntax (StatementE (ImmediateS (Encoded Text
txt))) =
    Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax (Expr -> Expr -> [Expr] -> [(Identifier, Expr)] -> Expr
FilterE (Text -> Expr
StringLitE Text
txt) (Identifier -> Expr
VarE Identifier
"encode") [] [])
  renderSyntax (StatementE Statement
x) =
    String -> Builder
forall a. HasCallStack => String -> a
error (String -> Builder) -> String -> Builder
forall a b. (a -> b) -> a -> b
$ String
"Cannot render statement expression " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Text -> String
LText.unpack (Text -> String) -> (Builder -> Text) -> Builder -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText (Builder -> String) -> Builder -> String
forall a b. (a -> b) -> a -> b
$ Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
x)
  renderSyntax (StringLitE Text
str) = Text -> Builder
renderStringLit Text
str
  renderSyntax (IntLitE Integer
i) = Text -> Builder
Builder.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Integer -> Text
forall a. Show a => a -> Text
Text.show Integer
i
  renderSyntax (FloatLitE Double
f) = Text -> Builder
Builder.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Double -> Text
forall a. Show a => a -> Text
Text.show Double
f
  renderSyntax (ListE Vector Expr
xs) =
    Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ([Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> (Vector Expr -> [Builder]) -> Vector Expr -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> [Builder])
-> (Vector Expr -> [Builder]) -> Vector Expr -> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Expr -> Builder) -> [Expr] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax ([Expr] -> [Builder])
-> (Vector Expr -> [Expr]) -> Vector Expr -> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Expr -> [Expr]
forall a. Vector a -> [a]
V.toList (Vector Expr -> Builder) -> Vector Expr -> Builder
forall a b. (a -> b) -> a -> b
$ Vector Expr
xs) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
  renderSyntax (DictE [(Expr, Expr)]
xs) =
    Builder
"{" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ([Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Builder] -> [Builder]) -> [Builder] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$ [ Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
k Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
": " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
v | (Expr
k, Expr
v) <- [(Expr, Expr)]
xs ]) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
  renderSyntax (NotE Expr
expr) =
    Builder
"(not " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
expr Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (NegateE Expr
expr) =
    Builder
"-" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
expr
  renderSyntax (IndexE Expr
a Expr
b) =
    Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
a Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
b Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
  renderSyntax (BinaryE BinaryOperator
op Expr
a Expr
b) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
a Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> BinaryOperator -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax BinaryOperator
op Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
b Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (DotE (VarE Identifier
a) Identifier
b) =
    Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
a Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"." Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
b
  renderSyntax (DotE Expr
a Identifier
b) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
a Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")." Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
b
  renderSyntax (SliceE Expr
slicee Maybe Expr
start Maybe Expr
end) =
    Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
slicee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Expr -> Builder) -> Maybe Expr -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Maybe Expr
start Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
":" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Expr -> Builder) -> Maybe Expr -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Maybe Expr
end Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
  renderSyntax (IsE Expr
scrutinee Expr
test [Expr]
args [(Identifier, Expr)]
kwargs) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
scrutinee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" is " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
test Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (CallE Expr
callee [Expr]
args [(Identifier, Expr)]
kwargs) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
callee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (FilterE Expr
arg0 Expr
f [Expr]
args [(Identifier, Expr)]
kwargs) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
arg0 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"|" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
f Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (TernaryE Expr
c Expr
y Expr
n) =
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
y Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" if " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
c Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" else " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
n Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
  renderSyntax (VarE Identifier
ident) =
    Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
ident
  renderSyntax BoolE {} = Builder
"BoolE ???"
  renderSyntax UnaryE {} = Builder
"UnaryE ???"

instance RenderSyntax Identifier where
  renderSyntax :: Identifier -> Builder
renderSyntax (Identifier Text
i) = Text -> Builder
Builder.fromText Text
i

instance RenderSyntax IncludeMissingPolicy where
  renderSyntax :: IncludeMissingPolicy -> Builder
renderSyntax IncludeMissingPolicy
RequireMissing = Builder
"require missing"
  renderSyntax IncludeMissingPolicy
IgnoreMissing = Builder
"ignore missing"

instance RenderSyntax IncludeContextPolicy where
  renderSyntax :: IncludeContextPolicy -> Builder
renderSyntax IncludeContextPolicy
WithContext = Builder
"with context"
  renderSyntax IncludeContextPolicy
WithoutContext = Builder
"without context"

instance RenderSyntax Scoped where
  renderSyntax :: Scoped -> Builder
renderSyntax Scoped
Scoped = Builder
"scoped"
  renderSyntax Scoped
NotScoped = Builder
""

instance RenderSyntax Required where
  renderSyntax :: Required -> Builder
renderSyntax Required
Required = Builder
"required"
  renderSyntax Required
Optional = Builder
""

instance RenderSyntax BinaryOperator where
  renderSyntax :: BinaryOperator -> Builder
renderSyntax BinaryOperator
BinopPlus = Builder
" + "
  renderSyntax BinaryOperator
BinopMinus = Builder
" - "
  renderSyntax BinaryOperator
BinopDiv = Builder
" / "
  renderSyntax BinaryOperator
BinopIntDiv = Builder
" // "
  renderSyntax BinaryOperator
BinopMod = Builder
" % "
  renderSyntax BinaryOperator
BinopMul = Builder
" * "
  renderSyntax BinaryOperator
BinopPower = Builder
" ** "
  renderSyntax BinaryOperator
BinopEqual = Builder
" == "
  renderSyntax BinaryOperator
BinopNotEqual = Builder
" != "
  renderSyntax BinaryOperator
BinopGT = Builder
" > "
  renderSyntax BinaryOperator
BinopGTE = Builder
" >= "
  renderSyntax BinaryOperator
BinopLT = Builder
" < "
  renderSyntax BinaryOperator
BinopLTE = Builder
" <= "
  renderSyntax BinaryOperator
BinopAnd = Builder
" and "
  renderSyntax BinaryOperator
BinopOr = Builder
" or "
  renderSyntax BinaryOperator
BinopIn = Builder
" in "
  renderSyntax BinaryOperator
BinopIndex = Builder
" [] "
  renderSyntax BinaryOperator
BinopConcat = Builder
" ~ "

renderFlow :: Builder -> Builder
renderFlow :: Builder -> Builder
renderFlow Builder
inner = Builder
"{% " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
inner Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" %}\n"

-- | Most 'Encoded's can actually be converted as-is, but if there are any
-- curly braces, we need to handle them specially.
renderEncoded :: Encoded -> Builder
renderEncoded :: Encoded -> Builder
renderEncoded (Encoded Text
txt) =
  Text -> Builder
Builder.fromText (Text -> Builder) -> (Text -> Text) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"{{" Text
"{{'{{'}}" (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$
  HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"{%" Text
"{{'{%'}}" (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$
  HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"{#" Text
"{{'{#'}}" (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$
  Text
txt

instance RenderSyntax Statement where
  renderSyntax :: Statement -> Builder
renderSyntax (PositionedS SourcePosition
_ Statement
s) = Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
s
  renderSyntax (ImmediateS Encoded
e) = Encoded -> Builder
renderEncoded Encoded
e
  renderSyntax (InterpolationS Expr
e) = Builder
"{{ " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
e Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" }}"
  renderSyntax (CommentS Text
msg) = Builder
"{# " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Builder.fromText Text
msg Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" #}\n"
  renderSyntax (ForS Maybe Identifier
kMay Identifier
v Expr
iteree Maybe Expr
condMay Recursivity
recursivity Statement
body Maybe Statement
elseBranchMay) =
    Builder -> Builder
renderFlow (
      Builder
"for " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Identifier -> Builder) -> Maybe Identifier -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Identifier
k -> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
k Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
", ") Maybe Identifier
kMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
v Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" in " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
iteree Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Expr -> Builder) -> Maybe Expr -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Expr
cond -> Builder
" if " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
cond) Maybe Expr
condMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> Builder -> Bool -> Builder
forall a. a -> a -> Bool -> a
bool Builder
"" Builder
" recursive" (Recursivity -> Bool
forall a. Boolish a => a -> Bool
is Recursivity
recursivity)
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> (Statement -> Builder) -> Maybe Statement -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Statement
elseBranch -> Builder -> Builder
renderFlow Builder
"else" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
elseBranch) Maybe Statement
elseBranchMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endfor"
  renderSyntax (IfS Expr
cond Statement
yes Maybe Statement
noMay) =
    Builder -> Builder
renderFlow (
      Builder
"if " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
cond
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
yes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> (Statement -> Builder) -> Maybe Statement -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Statement
no -> Builder -> Builder
renderFlow Builder
"else" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
no) Maybe Statement
noMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endif"
  renderSyntax (MacroS Identifier
name [MacroArg]
args Statement
body) =
    Builder -> Builder
renderFlow (
      Builder
"macro " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      [MacroArg] -> Builder
renderArgSpec [MacroArg]
args
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endmacro"
  renderSyntax (CallS Identifier
name [Expr]
args [(Identifier, Expr)]
kwargs Statement
body) =
    Builder -> Builder
renderFlow (
      Builder
"call " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endcall"
  renderSyntax (FilterS Identifier
name [Expr]
args [(Identifier, Expr)]
kwargs Statement
body) =
    Builder -> Builder
renderFlow (
      Builder
"filter " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endfilter"
  renderSyntax (SetS SetTarget
name Expr
val) =
    Builder -> Builder
renderFlow (
      Builder
"set " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      SetTarget -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax SetTarget
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" = " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
val
    )
  renderSyntax (SetBlockS SetTarget
name Statement
body Maybe Expr
filterMay) =
    Builder -> Builder
renderFlow (
      Builder
"set " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      SetTarget -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax SetTarget
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Expr -> Builder) -> Maybe Expr -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Expr
f -> Builder
"|" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
f) Maybe Expr
filterMay
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endset"
  renderSyntax (IncludeS Expr
includee IncludeMissingPolicy
missingPolicy IncludeContextPolicy
contextPolicy) =
    Builder -> Builder
renderFlow (
      Builder
"include " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
includee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeMissingPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeMissingPolicy
missingPolicy Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeContextPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeContextPolicy
contextPolicy
    )
  renderSyntax (ImportS Expr
importee Maybe Identifier
aliasMay Maybe [(Identifier, Maybe Identifier)]
Nothing IncludeMissingPolicy
missingPolicy IncludeContextPolicy
contextPolicy) =
    Builder -> Builder
renderFlow (
      Builder
"import " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
importee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Identifier -> Builder) -> Maybe Identifier -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Identifier
alias -> Builder
" as " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
alias) Maybe Identifier
aliasMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeMissingPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeMissingPolicy
missingPolicy Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeContextPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeContextPolicy
contextPolicy
    )
  renderSyntax (ImportS Expr
importee Maybe Identifier
aliasMay (Just [(Identifier, Maybe Identifier)]
imports) IncludeMissingPolicy
missingPolicy IncludeContextPolicy
contextPolicy) =
    Builder -> Builder
renderFlow (
      Builder
"from " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
importee Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder -> (Identifier -> Builder) -> Maybe Identifier -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
" " (\Identifier
alias -> Builder
" as " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
alias) Maybe Identifier
aliasMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
"import " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      [(Identifier, Maybe Identifier)] -> Builder
renderImports [(Identifier, Maybe Identifier)]
imports Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeMissingPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeMissingPolicy
missingPolicy Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      IncludeContextPolicy -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax IncludeContextPolicy
contextPolicy
    )
  renderSyntax (BlockS Identifier
name (Block Statement
body Scoped
scopedness Required
requiredness)) =
    Builder -> Builder
renderFlow (
      Builder
"block " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Scoped -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Scoped
scopedness Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      Required -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Required
requiredness
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endblock"
  renderSyntax (WithS [(Identifier, Expr)]
defs Statement
body) =
    Builder -> Builder
renderFlow (
      Builder
"with " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
      [(Identifier, Expr)] -> Builder
renderWithDefs [(Identifier, Expr)]
defs
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder -> Builder
renderFlow Builder
"endwith"
  renderSyntax (GroupS [Statement]
ss) =
    [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Statement] -> [Builder]) -> [Statement] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Statement -> Builder) -> [Statement] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax ([Statement] -> Builder) -> [Statement] -> Builder
forall a b. (a -> b) -> a -> b
$ [Statement]
ss

renderImports :: [(Identifier, Maybe Identifier)] -> Builder
renderImports :: [(Identifier, Maybe Identifier)] -> Builder
renderImports = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([(Identifier, Maybe Identifier)] -> [Builder])
-> [(Identifier, Maybe Identifier)]
-> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> [Builder])
-> ([(Identifier, Maybe Identifier)] -> [Builder])
-> [(Identifier, Maybe Identifier)]
-> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Identifier, Maybe Identifier) -> Builder)
-> [(Identifier, Maybe Identifier)] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (Identifier, Maybe Identifier) -> Builder
renderImport

renderImport :: (Identifier, Maybe Identifier) -> Builder
renderImport :: (Identifier, Maybe Identifier) -> Builder
renderImport (Identifier
i, Maybe Identifier
Nothing) = Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
i
renderImport (Identifier
i, Just Identifier
a) = Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
i Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" as " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
a

renderWithDefs :: [(Identifier, Expr)] -> Builder
renderWithDefs :: [(Identifier, Expr)] -> Builder
renderWithDefs [(Identifier, Expr)]
args =
  [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Builder] -> [Builder]) -> [Builder] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$
    [ Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
k Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
v | (Identifier
k, Expr
v) <- [(Identifier, Expr)]
args ]

renderArgs :: [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs :: [Expr] -> [(Identifier, Expr)] -> Builder
renderArgs [Expr]
args [(Identifier, Expr)]
kwargs =
  let allArgs :: [(Maybe Identifier, Expr)]
allArgs = (Expr -> (Maybe Identifier, Expr))
-> [Expr] -> [(Maybe Identifier, Expr)]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Identifier
forall a. Maybe a
Nothing ,) [Expr]
args [(Maybe Identifier, Expr)]
-> [(Maybe Identifier, Expr)] -> [(Maybe Identifier, Expr)]
forall a. [a] -> [a] -> [a]
++ [(Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
k, Expr
v) | (Identifier
k, Expr
v) <- [(Identifier, Expr)]
kwargs]
  in
    Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    ([Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Builder] -> [Builder]) -> [Builder] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$
        [ Builder -> (Identifier -> Builder) -> Maybe Identifier -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Identifier
k -> Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
k Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"=") Maybe Identifier
kMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
v
        | (Maybe Identifier
kMay, Expr
v) <- [(Maybe Identifier, Expr)]
allArgs
        ]
    ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Builder
")"

renderArgSpec :: [(Identifier, Maybe Expr)] -> Builder
renderArgSpec :: [MacroArg] -> Builder
renderArgSpec [MacroArg]
args =
  Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  ([Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Builder] -> [Builder]) -> [Builder] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
", " ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$
      [ Identifier -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Identifier
k Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder -> (Expr -> Builder) -> Maybe Expr -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (\Expr
v -> Builder
"=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Expr
v) Maybe Expr
vMay
      | (Identifier
k, Maybe Expr
vMay) <- [MacroArg]
args
      ]
  ) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
  Builder
")"

instance RenderSyntax Template where
  renderSyntax :: Template -> Builder
renderSyntax (Template Maybe Text
parentMay Statement
body) =
    Builder -> (Text -> Builder) -> Maybe Text -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" (Builder -> Builder
renderFlow (Builder -> Builder) -> (Text -> Builder) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder
"extends " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>) (Builder -> Builder) -> (Text -> Builder) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax (Expr -> Builder) -> (Text -> Expr) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Expr
StringLitE) Maybe Text
parentMay Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
    Statement -> Builder
forall a. RenderSyntax a => a -> Builder
renderSyntax Statement
body