packages feed

hydra-0.15.0: src/main/haskell/Hydra/Serialization.hs

-- Note: this is an automatically generated file. Do not edit.
-- | Utilities for constructing generic program code ASTs, used for the serialization phase of source code generation.

module Hydra.Serialization where
import qualified Hydra.Ast as Ast
import qualified Hydra.Lib.Equality as Equality
import qualified Hydra.Lib.Lists as Lists
import qualified Hydra.Lib.Literals as Literals
import qualified Hydra.Lib.Logic as Logic
import qualified Hydra.Lib.Math as Math
import qualified Hydra.Lib.Maybes as Maybes
import qualified Hydra.Lib.Pairs as Pairs
import qualified Hydra.Lib.Strings as Strings
import qualified Hydra.Util as Util
import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci
angleBraces :: Ast.Brackets
angleBraces =
    Ast.Brackets {
      Ast.bracketsOpen = (Ast.Symbol "<"),
      Ast.bracketsClose = (Ast.Symbol ">")}
angleBracesList :: Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
angleBracesList style els = Logic.ifElse (Lists.null els) (cst "<>") (brackets angleBraces style (commaSep style els))
-- | Produce a bracketed list which separates elements by spaces or newlines depending on the estimated width of the expression.
bracesListAdaptive :: [Ast.Expr] -> Ast.Expr
bracesListAdaptive els =

      let inlineList = curlyBracesList Nothing inlineStyle els
      in (Logic.ifElse (Equality.gt (expressionLength inlineList) 70) (curlyBracesList Nothing halfBlockStyle els) inlineList)
bracketList :: Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
bracketList style els = Logic.ifElse (Lists.null els) (cst "[]") (brackets squareBrackets style (commaSep style els))
-- | Produce a bracketed list which separates elements by spaces or newlines depending on the estimated width of the expression.
bracketListAdaptive :: [Ast.Expr] -> Ast.Expr
bracketListAdaptive els =

      let inlineList = bracketList inlineStyle els
      in (Logic.ifElse (Equality.gt (expressionLength inlineList) 70) (bracketList halfBlockStyle els) inlineList)
brackets :: Ast.Brackets -> Ast.BlockStyle -> Ast.Expr -> Ast.Expr
brackets br style e =
    Ast.ExprBrackets (Ast.BracketExpr {
      Ast.bracketExprBrackets = br,
      Ast.bracketExprEnclosed = e,
      Ast.bracketExprStyle = style})
commaSep :: Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
commaSep = symbolSep ","
cst :: String -> Ast.Expr
cst s = Ast.ExprConst (sym s)
curlyBlock :: Ast.BlockStyle -> Ast.Expr -> Ast.Expr
curlyBlock style e = curlyBracesList Nothing style [
  e]
curlyBraces :: Ast.Brackets
curlyBraces =
    Ast.Brackets {
      Ast.bracketsOpen = (Ast.Symbol "{"),
      Ast.bracketsClose = (Ast.Symbol "}")}
curlyBracesList :: Maybe String -> Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
curlyBracesList msymb style els =
    Logic.ifElse (Lists.null els) (cst "{}") (brackets curlyBraces style (symbolSep (Maybes.fromMaybe "," msymb) style els))
-- | Indent every non-empty line of `s` by `idt`. Empty lines stay empty (no trailing whitespace) so downstream byte-identity checks don't care about indent depth.
customIndent :: String -> String -> String
customIndent idt s =
    Strings.cat (Lists.intersperse "\n" (Lists.map (\line -> Logic.ifElse (Equality.equal line "") line (Strings.cat2 idt line)) (Strings.lines s)))
customIndentBlock :: String -> [Ast.Expr] -> Ast.Expr
customIndentBlock idt els =

      let idtOp =
              Ast.Op {
                Ast.opSymbol = (sym ""),
                Ast.opPadding = Ast.Padding {
                  Ast.paddingLeft = Ast.WsSpace,
                  Ast.paddingRight = (Ast.WsBreakAndIndent idt)},
                Ast.opPrecedence = (Ast.Precedence 0),
                Ast.opAssociativity = Ast.AssociativityNone}
      in (Maybes.maybe (cst "") (\head -> Logic.ifElse (Equality.equal (Lists.length els) 1) head (ifx idtOp head (newlineSep (Lists.drop 1 els)))) (Lists.maybeHead els))
dotSep :: [Ast.Expr] -> Ast.Expr
dotSep =
    sep (Ast.Op {
      Ast.opSymbol = (sym "."),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsNone,
        Ast.paddingRight = Ast.WsNone},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
doubleNewlineSep :: [Ast.Expr] -> Ast.Expr
doubleNewlineSep =
    sep (Ast.Op {
      Ast.opSymbol = (sym ""),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsBreak,
        Ast.paddingRight = Ast.WsBreak},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
doubleSpace :: String
doubleSpace = "  "
-- | Find the approximate length (number of characters, including spaces and newlines) of an expression without actually printing it.
expressionLength :: Ast.Expr -> Int
expressionLength e =

      let symbolLength = \s -> Strings.length (Ast.unSymbol s)
          wsLength =
                  \ws -> case ws of
                    Ast.WsNone -> 0
                    Ast.WsSpace -> 1
                    Ast.WsBreak -> 10000
                    Ast.WsBreakAndIndent _ -> 10000
                    Ast.WsDoubleBreak -> 10000
          blockStyleLength =
                  \style ->
                    let mindentLen = Maybes.maybe 0 Strings.length (Ast.blockStyleIndent style)
                        nlBeforeLen = Logic.ifElse (Ast.blockStyleNewlineBeforeContent style) 1 0
                        nlAfterLen = Logic.ifElse (Ast.blockStyleNewlineAfterContent style) 1 0
                    in (Math.add mindentLen (Math.add nlBeforeLen nlAfterLen))
          bracketsLength =
                  \brackets -> Math.add (symbolLength (Ast.bracketsOpen brackets)) (symbolLength (Ast.bracketsClose brackets))
          bracketExprLength =
                  \be -> Math.add (bracketsLength (Ast.bracketExprBrackets be)) (Math.add (expressionLength (Ast.bracketExprEnclosed be)) (blockStyleLength (Ast.bracketExprStyle be)))
          indentedExpressionLength =
                  \ie ->
                    let baseLen = expressionLength (Ast.indentedExpressionExpr ie)
                        indentLen =
                                case (Ast.indentedExpressionStyle ie) of
                                  Ast.IndentStyleAllLines v0 -> Strings.length v0
                                  Ast.IndentStyleSubsequentLines v0 -> Strings.length v0
                    in (Math.add baseLen indentLen)
          opLength =
                  \op ->
                    let symLen = symbolLength (Ast.opSymbol op)
                        padding = Ast.opPadding op
                        leftLen = wsLength (Ast.paddingLeft padding)
                        rightLen = wsLength (Ast.paddingRight padding)
                    in (Math.add symLen (Math.add leftLen rightLen))
          opExprLength =
                  \oe ->
                    let opLen = opLength (Ast.opExprOp oe)
                        leftLen = expressionLength (Ast.opExprLhs oe)
                        rightLen = expressionLength (Ast.opExprRhs oe)
                    in (Math.add opLen (Math.add leftLen rightLen))
          seqExprLength =
                  \se ->
                    let sopLen = opLength (Ast.seqExprOp se)
                        elementLens = Lists.map expressionLength (Ast.seqExprElements se)
                        totalElLen = Lists.foldl Math.add 0 elementLens
                        numSeps = Math.sub (Lists.length (Ast.seqExprElements se)) 1
                    in (Math.add totalElLen (Math.mul sopLen (Logic.ifElse (Equality.gt numSeps 0) numSeps 0)))
      in case e of
        Ast.ExprConst v0 -> symbolLength v0
        Ast.ExprIndent v0 -> indentedExpressionLength v0
        Ast.ExprOp v0 -> opExprLength v0
        Ast.ExprBrackets v0 -> bracketExprLength v0
        Ast.ExprSeq v0 -> seqExprLength v0
fullBlockStyle :: Ast.BlockStyle
fullBlockStyle =
    Ast.BlockStyle {
      Ast.blockStyleIndent = (Just doubleSpace),
      Ast.blockStyleNewlineBeforeContent = True,
      Ast.blockStyleNewlineAfterContent = True}
halfBlockStyle :: Ast.BlockStyle
halfBlockStyle =
    Ast.BlockStyle {
      Ast.blockStyleIndent = (Just doubleSpace),
      Ast.blockStyleNewlineBeforeContent = True,
      Ast.blockStyleNewlineAfterContent = False}
ifx :: Ast.Op -> Ast.Expr -> Ast.Expr -> Ast.Expr
ifx op lhs rhs =
    Ast.ExprOp (Ast.OpExpr {
      Ast.opExprOp = op,
      Ast.opExprLhs = lhs,
      Ast.opExprRhs = rhs})
indent :: String -> String
indent = customIndent doubleSpace
indentBlock :: [Ast.Expr] -> Ast.Expr
indentBlock = customIndentBlock doubleSpace
indentSubsequentLines :: String -> Ast.Expr -> Ast.Expr
indentSubsequentLines idt e =
    Ast.ExprIndent (Ast.IndentedExpression {
      Ast.indentedExpressionStyle = (Ast.IndentStyleSubsequentLines idt),
      Ast.indentedExpressionExpr = e})
infixWs :: String -> Ast.Expr -> Ast.Expr -> Ast.Expr
infixWs op l r =
    spaceSep [
      l,
      (cst op),
      r]
infixWsList :: String -> [Ast.Expr] -> Ast.Expr
infixWsList op opers =

      let opExpr = cst op
          foldFun = \e -> \r -> Logic.ifElse (Lists.null e) [
                r] (Lists.cons r (Lists.cons opExpr e))
      in (spaceSep (Lists.foldl foldFun [] (Lists.reverse opers)))
inlineStyle :: Ast.BlockStyle
inlineStyle =
    Ast.BlockStyle {
      Ast.blockStyleIndent = Nothing,
      Ast.blockStyleNewlineBeforeContent = False,
      Ast.blockStyleNewlineAfterContent = False}
newlineSep :: [Ast.Expr] -> Ast.Expr
newlineSep =
    sep (Ast.Op {
      Ast.opSymbol = (sym ""),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsNone,
        Ast.paddingRight = Ast.WsBreak},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
noPadding :: Ast.Padding
noPadding =
    Ast.Padding {
      Ast.paddingLeft = Ast.WsNone,
      Ast.paddingRight = Ast.WsNone}
noSep :: [Ast.Expr] -> Ast.Expr
noSep =
    sep (Ast.Op {
      Ast.opSymbol = (sym ""),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsNone,
        Ast.paddingRight = Ast.WsNone},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
num :: Int -> Ast.Expr
num i = cst (Literals.showInt32 i)
op :: String -> Int -> Ast.Associativity -> Ast.Op
op s p assoc =
    Ast.Op {
      Ast.opSymbol = (sym s),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsSpace,
        Ast.paddingRight = Ast.WsSpace},
      Ast.opPrecedence = (Ast.Precedence p),
      Ast.opAssociativity = assoc}
orOp :: Bool -> Ast.Op
orOp newlines =
    Ast.Op {
      Ast.opSymbol = (sym "|"),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsSpace,
        Ast.paddingRight = (Logic.ifElse newlines Ast.WsBreak Ast.WsSpace)},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone}
orSep :: Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
orSep style l =

      let newlines = Ast.blockStyleNewlineBeforeContent style
      in (Maybes.maybe (cst "") (\h -> Lists.foldl (\acc -> \el -> ifx (orOp newlines) acc el) h (Lists.drop 1 l)) (Lists.maybeHead l))
parenList :: Bool -> [Ast.Expr] -> Ast.Expr
parenList newlines els =

      let style = Logic.ifElse (Logic.and newlines (Equality.gt (Lists.length els) 1)) halfBlockStyle inlineStyle
      in (Logic.ifElse (Lists.null els) (cst "()") (brackets parentheses style (commaSep style els)))
parens :: Ast.Expr -> Ast.Expr
parens = brackets parentheses inlineStyle
parentheses :: Ast.Brackets
parentheses =
    Ast.Brackets {
      Ast.bracketsOpen = (Ast.Symbol "("),
      Ast.bracketsClose = (Ast.Symbol ")")}
parenthesize :: Ast.Expr -> Ast.Expr
parenthesize exp =

      let assocLeft =
              \a -> case a of
                Ast.AssociativityRight -> False
                _ -> True
          assocRight =
                  \a -> case a of
                    Ast.AssociativityLeft -> False
                    _ -> True
      in case exp of
        Ast.ExprBrackets v0 -> Ast.ExprBrackets (Ast.BracketExpr {
          Ast.bracketExprBrackets = (Ast.bracketExprBrackets v0),
          Ast.bracketExprEnclosed = (parenthesize (Ast.bracketExprEnclosed v0)),
          Ast.bracketExprStyle = (Ast.bracketExprStyle v0)})
        Ast.ExprConst _ -> exp
        Ast.ExprIndent v0 -> Ast.ExprIndent (Ast.IndentedExpression {
          Ast.indentedExpressionStyle = (Ast.indentedExpressionStyle v0),
          Ast.indentedExpressionExpr = (parenthesize (Ast.indentedExpressionExpr v0))})
        Ast.ExprSeq v0 -> Ast.ExprSeq (Ast.SeqExpr {
          Ast.seqExprOp = (Ast.seqExprOp v0),
          Ast.seqExprElements = (Lists.map parenthesize (Ast.seqExprElements v0))})
        Ast.ExprOp v0 ->
          let op = Ast.opExprOp v0
              prec = Ast.unPrecedence (Ast.opPrecedence op)
              assoc = Ast.opAssociativity op
              lhs = Ast.opExprLhs v0
              rhs = Ast.opExprRhs v0
              lhs_ = parenthesize lhs
              rhs_ = parenthesize rhs
              lhs2 =
                      case lhs_ of
                        Ast.ExprOp v1 ->
                          let lop = Ast.opExprOp v1
                              lprec = Ast.unPrecedence (Ast.opPrecedence lop)
                              lassoc = Ast.opAssociativity lop
                              comparison = Equality.compare prec lprec
                          in case comparison of
                            Util.ComparisonLessThan -> lhs_
                            Util.ComparisonGreaterThan -> parens lhs_
                            Util.ComparisonEqualTo -> Logic.ifElse (Logic.and (assocLeft assoc) (assocLeft lassoc)) lhs_ (parens lhs_)
                        _ -> lhs_
              rhs2 =
                      case rhs_ of
                        Ast.ExprOp v1 ->
                          let rop = Ast.opExprOp v1
                              rprec = Ast.unPrecedence (Ast.opPrecedence rop)
                              rassoc = Ast.opAssociativity rop
                              comparison = Equality.compare prec rprec
                          in case comparison of
                            Util.ComparisonLessThan -> rhs_
                            Util.ComparisonGreaterThan -> parens rhs_
                            Util.ComparisonEqualTo -> Logic.ifElse (Logic.and (assocRight assoc) (assocRight rassoc)) rhs_ (parens rhs_)
                        _ -> rhs_
          in (Ast.ExprOp (Ast.OpExpr {
            Ast.opExprOp = op,
            Ast.opExprLhs = lhs2,
            Ast.opExprRhs = rhs2}))
prefix :: String -> Ast.Expr -> Ast.Expr
prefix p expr =

      let preOp =
              Ast.Op {
                Ast.opSymbol = (sym p),
                Ast.opPadding = Ast.Padding {
                  Ast.paddingLeft = Ast.WsNone,
                  Ast.paddingRight = Ast.WsNone},
                Ast.opPrecedence = (Ast.Precedence 0),
                Ast.opAssociativity = Ast.AssociativityNone}
      in (ifx preOp (cst "") expr)
printExpr :: Ast.Expr -> String
printExpr e =

      let pad =
              \ws -> case ws of
                Ast.WsNone -> ""
                Ast.WsSpace -> " "
                Ast.WsBreak -> "\n"
                Ast.WsBreakAndIndent _ -> "\n"
                Ast.WsDoubleBreak -> "\n\n"
          idt =
                  \ws -> \s -> case ws of
                    Ast.WsBreakAndIndent v0 -> customIndent v0 s
                    _ -> s
      in case e of
        Ast.ExprConst v0 -> Ast.unSymbol v0
        Ast.ExprIndent v0 ->
          let style = Ast.indentedExpressionStyle v0
              expr = Ast.indentedExpressionExpr v0
              lns = Strings.lines (printExpr expr)
              indentLine = \idt2 -> \line -> Logic.ifElse (Equality.equal line "") line (Strings.cat2 idt2 line)
              ilns =
                      case style of
                        Ast.IndentStyleAllLines v1 -> Lists.map (indentLine v1) lns
                        Ast.IndentStyleSubsequentLines v1 -> Logic.ifElse (Equality.equal (Lists.length lns) 1) lns (Maybes.fromMaybe lns (Maybes.map (\uc -> Lists.cons (Pairs.first uc) (Lists.map (indentLine v1) (Pairs.second uc))) (Lists.uncons lns)))
          in (Strings.intercalate "\n" ilns)
        Ast.ExprSeq v0 ->
          let sop = Ast.seqExprOp v0
              ssym = Ast.unSymbol (Ast.opSymbol sop)
              spadding = Ast.opPadding sop
              spadl = Ast.paddingLeft spadding
              spadr = Ast.paddingRight spadding
              selements = Ast.seqExprElements v0
              printedElements = Lists.map (\el -> idt spadr (printExpr el)) selements
              isNewlineWs =
                      \ws -> case ws of
                        Ast.WsBreak -> True
                        Ast.WsBreakAndIndent _ -> True
                        Ast.WsDoubleBreak -> True
                        _ -> False
              spadlIsNewline = isNewlineWs spadl
              spadrIsNewline = isNewlineWs spadr
              joinElements =
                      \acc -> \el ->
                        let elStartsWithNewline = Maybes.maybe False (\c -> Equality.equal c 10) (Strings.maybeCharAt 0 el)
                            elIsEmpty = Equality.equal el ""
                            padlEff =
                                    Logic.ifElse (Logic.or (Logic.and elStartsWithNewline (Logic.not spadlIsNewline)) (Logic.and elIsEmpty (Equality.equal ssym ""))) "" (pad spadl)
                            padrEff =
                                    Logic.ifElse (Logic.or (Logic.and elStartsWithNewline (Logic.not spadrIsNewline)) (Logic.and elIsEmpty (Equality.equal ssym ""))) "" (pad spadr)
                        in (Strings.cat [
                          acc,
                          padlEff,
                          ssym,
                          padrEff,
                          el])
          in (Maybes.maybe "" (\h -> Lists.foldl joinElements h (Lists.drop 1 printedElements)) (Lists.maybeHead printedElements))
        Ast.ExprOp v0 ->
          let op = Ast.opExprOp v0
              sym = Ast.unSymbol (Ast.opSymbol op)
              padding = Ast.opPadding op
              padl = Ast.paddingLeft padding
              padr = Ast.paddingRight padding
              l = Ast.opExprLhs v0
              r = Ast.opExprRhs v0
              lhs = idt padl (printExpr l)
              rhs = idt padr (printExpr r)
              padrIsNewline =
                      case padr of
                        Ast.WsBreak -> True
                        Ast.WsBreakAndIndent _ -> True
                        Ast.WsDoubleBreak -> True
                        _ -> False
              padlEffective = Logic.ifElse (Logic.and (Equality.equal sym "") (Logic.or padrIsNewline (Equality.equal rhs ""))) "" (pad padl)
              padrPad = pad padr
              rhsStartsWithNewline = Maybes.maybe False (\c -> Equality.equal c 10) (Strings.maybeCharAt 0 rhs)
              padrEffective = Logic.ifElse (Logic.and rhsStartsWithNewline (Logic.not padrIsNewline)) "" padrPad
          in (Strings.cat2 (Strings.cat2 (Strings.cat2 (Strings.cat2 lhs padlEffective) sym) padrEffective) rhs)
        Ast.ExprBrackets v0 ->
          let brs = Ast.bracketExprBrackets v0
              l = Ast.unSymbol (Ast.bracketsOpen brs)
              r = Ast.unSymbol (Ast.bracketsClose brs)
              e = Ast.bracketExprEnclosed v0
              style = Ast.bracketExprStyle v0
              body = printExpr e
              doIndent = Ast.blockStyleIndent style
              nlBefore = Ast.blockStyleNewlineBeforeContent style
              nlAfter = Ast.blockStyleNewlineAfterContent style
              ibody = Maybes.maybe body (\idt2 -> customIndent idt2 body) doIndent
              pre = Logic.ifElse nlBefore "\n" ""
              suf = Logic.ifElse nlAfter "\n" ""
          in (Strings.cat2 (Strings.cat2 (Strings.cat2 (Strings.cat2 l pre) ibody) suf) r)
semicolonSep :: [Ast.Expr] -> Ast.Expr
semicolonSep = symbolSep ";" inlineStyle
sep :: Ast.Op -> [Ast.Expr] -> Ast.Expr
sep op els =
    Maybes.maybe (cst "") (\h -> Lists.foldl (\acc -> \el -> ifx op acc el) h (Lists.drop 1 els)) (Lists.maybeHead els)
spaceSep :: [Ast.Expr] -> Ast.Expr
spaceSep =
    sep (Ast.Op {
      Ast.opSymbol = (sym ""),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsSpace,
        Ast.paddingRight = Ast.WsNone},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
squareBrackets :: Ast.Brackets
squareBrackets =
    Ast.Brackets {
      Ast.bracketsOpen = (Ast.Symbol "["),
      Ast.bracketsClose = (Ast.Symbol "]")}
-- | Like sep, but produces a SeqExpr instead of an OpExpr chain. SeqExpr is treated as structural layout and is not subject to parenthesization.
structuralSep :: Ast.Op -> [Ast.Expr] -> Ast.Expr
structuralSep op els =
    Logic.ifElse (Lists.null els) (cst "") (Logic.ifElse (Equality.equal (Lists.length els) 1) (Maybes.fromMaybe (cst "") (Lists.maybeHead els)) (Ast.ExprSeq (Ast.SeqExpr {
      Ast.seqExprOp = op,
      Ast.seqExprElements = els})))
-- | Like spaceSep, but produces a SeqExpr. Use for structural layout that should not trigger parenthesization of children.
structuralSpaceSep :: [Ast.Expr] -> Ast.Expr
structuralSpaceSep =
    structuralSep (Ast.Op {
      Ast.opSymbol = (sym ""),
      Ast.opPadding = Ast.Padding {
        Ast.paddingLeft = Ast.WsSpace,
        Ast.paddingRight = Ast.WsNone},
      Ast.opPrecedence = (Ast.Precedence 0),
      Ast.opAssociativity = Ast.AssociativityNone})
-- | Append a suffix string to an expression
suffix :: String -> Ast.Expr -> Ast.Expr
suffix s expr =

      let sufOp =
              Ast.Op {
                Ast.opSymbol = (sym s),
                Ast.opPadding = Ast.Padding {
                  Ast.paddingLeft = Ast.WsNone,
                  Ast.paddingRight = Ast.WsNone},
                Ast.opPrecedence = (Ast.Precedence 0),
                Ast.opAssociativity = Ast.AssociativityNone}
      in (ifx sufOp expr (cst ""))
sym :: String -> Ast.Symbol
sym s = Ast.Symbol s
symbolSep :: String -> Ast.BlockStyle -> [Ast.Expr] -> Ast.Expr
symbolSep symb style l =

      let breakCount =
              Lists.length (Lists.filter (\x_ -> x_) [
                Ast.blockStyleNewlineBeforeContent style,
                (Ast.blockStyleNewlineAfterContent style)])
          break =
                  Logic.ifElse (Equality.equal breakCount 0) Ast.WsSpace (Logic.ifElse (Equality.equal breakCount 1) Ast.WsBreak Ast.WsDoubleBreak)
          commaOp =
                  Ast.Op {
                    Ast.opSymbol = (sym symb),
                    Ast.opPadding = Ast.Padding {
                      Ast.paddingLeft = Ast.WsNone,
                      Ast.paddingRight = break},
                    Ast.opPrecedence = (Ast.Precedence 0),
                    Ast.opAssociativity = Ast.AssociativityNone}
      in (Maybes.maybe (cst "") (\h -> Lists.foldl (\acc -> \el -> ifx commaOp acc el) h (Lists.drop 1 l)) (Lists.maybeHead l))
tabIndent :: Ast.Expr -> Ast.Expr
tabIndent e =
    Ast.ExprIndent (Ast.IndentedExpression {
      Ast.indentedExpressionStyle = (Ast.IndentStyleAllLines "    "),
      Ast.indentedExpressionExpr = e})
tabIndentDoubleSpace :: [Ast.Expr] -> Ast.Expr
tabIndentDoubleSpace exprs = tabIndent (doubleNewlineSep exprs)
tabIndentSingleSpace :: [Ast.Expr] -> Ast.Expr
tabIndentSingleSpace exprs = tabIndent (newlineSep exprs)
unsupportedType :: String -> Ast.Expr
unsupportedType label = cst (Strings.cat2 (Strings.cat2 "[" label) "]")
unsupportedVariant :: String -> String -> Ast.Expr
unsupportedVariant label obj =
    cst (Strings.cat2 (Strings.cat2 (Strings.cat2 (Strings.cat2 "[unsupported " label) ": ") (Literals.showString obj)) "]")
withComma :: Ast.Expr -> Ast.Expr
withComma e =
    noSep [
      e,
      (cst ",")]
withSemi :: Ast.Expr -> Ast.Expr
withSemi e =
    noSep [
      e,
      (cst ";")]