{-# LANGUAGE LambdaCase #-}

-- |
-- Module      : Jikka.RestrictedPython.Format
-- Description : converts AST of the restricted Python to strings. / 制限された Python の抽象構文木を文字列に変換します。
-- Copyright   : (c) Kimiyuki Onaka, 2020
-- License     : Apache License 2.0
-- Maintainer  : kimiyuki95@gmail.com
-- Stability   : experimental
-- Portability : portable
--
-- TODO: add parens with considering precedences.
module Jikka.RestrictedPython.Format
  ( run,
    run',
    formatType,
    formatOperator,
    formatBuiltin,
    formatAttribute,
    formatExpr,
    formatTarget,
  )
where

import Data.List (intercalate)
import Data.Text (Text, pack)
import Jikka.Common.Format.AutoIndent
import Jikka.RestrictedPython.Language.Builtin
import Jikka.RestrictedPython.Language.Expr

formatType :: Type -> String
formatType :: Type -> String
formatType Type
t = case Type
t of
  VarTy TypeName
x -> TypeName -> String
unTypeName TypeName
x
  Type
IntTy -> String
"int"
  Type
BoolTy -> String
"bool"
  ListTy Type
t -> String
"List[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  Type
NoneTy -> String
"None"
  TupleTy [Type]
ts -> String
"Tuple[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Type -> String) -> [Type] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Type -> String
formatType [Type]
ts) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  CallableTy [Type]
ts Type
ret -> String
"Callable[[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Type -> String) -> [Type] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Type -> String
formatType [Type]
ts) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"], " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
ret String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  Type
StringTy -> String
"str"
  Type
SideEffectTy -> String
"side-effect"

formatConstant :: Constant -> String
formatConstant :: Constant -> String
formatConstant = \case
  Constant
ConstNone -> String
"None"
  ConstInt Integer
n -> Integer -> String
forall a. Show a => a -> String
show Integer
n
  ConstBool Bool
p -> Bool -> String
forall a. Show a => a -> String
show Bool
p
  ConstBuiltin Builtin
b -> Builtin -> String
formatBuiltin Builtin
b

formatBoolOp :: BoolOp -> String
formatBoolOp :: BoolOp -> String
formatBoolOp = \case
  BoolOp
And -> String
"and"
  BoolOp
Or -> String
"or"
  BoolOp
Implies -> String
"implies"

formatOperator :: Operator -> String
formatOperator :: Operator -> String
formatOperator = \case
  Operator
Add -> String
"+"
  Operator
Sub -> String
"-"
  Operator
Mult -> String
"*"
  Operator
MatMult -> String
"@"
  Operator
Div -> String
"/"
  Operator
FloorDiv -> String
"//"
  Operator
FloorMod -> String
"%"
  Operator
CeilDiv -> String
"/^"
  Operator
CeilMod -> String
"%^"
  Operator
Pow -> String
"**"
  Operator
BitLShift -> String
"<<"
  Operator
BitRShift -> String
">>"
  Operator
BitOr -> String
"|"
  Operator
BitXor -> String
"^"
  Operator
BitAnd -> String
"&"
  Operator
Max -> String
">?"
  Operator
Min -> String
"<?"

formatUnaryOp :: UnaryOp -> String
formatUnaryOp :: UnaryOp -> String
formatUnaryOp = \case
  UnaryOp
Invert -> String
"~"
  UnaryOp
Not -> String
"not"
  UnaryOp
UAdd -> String
"+"
  UnaryOp
USub -> String
"-"

formatCmpOp :: CmpOp' -> String
formatCmpOp :: CmpOp' -> String
formatCmpOp (CmpOp' CmpOp
op Type
_) = case CmpOp
op of
  CmpOp
Eq' -> String
"=="
  CmpOp
NotEq -> String
"!="
  CmpOp
Lt -> String
"<"
  CmpOp
LtE -> String
"<="
  CmpOp
Gt -> String
">"
  CmpOp
GtE -> String
">="
  CmpOp
Is -> String
"is"
  CmpOp
IsNot -> String
"is not"
  CmpOp
In -> String
"in"
  CmpOp
NotIn -> String
"not in"

formatComprehension :: Comprehension -> String
formatComprehension :: Comprehension -> String
formatComprehension (Comprehension Target'
x Expr'
iter Maybe Expr'
ifs) =
  let body :: String
body = String
"for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
iter
      ifs' :: String
ifs' = case Maybe Expr'
ifs of
        Maybe Expr'
Nothing -> String
""
        Just Expr'
ifs -> String
" if " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
ifs
   in String
body String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ifs'

formatTarget :: Target' -> String
formatTarget :: Target' -> String
formatTarget (WithLoc' Maybe Loc
_ Target
x) = case Target
x of
  SubscriptTrg Target'
x Expr'
e -> Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  NameTrg VarName'
x -> VarName -> String
unVarName (VarName' -> VarName
forall a. WithLoc' a -> a
value' VarName'
x)
  TupleTrg [Target']
xs -> case [Target']
xs of
    [] -> String
"()"
    [Target'
x] -> String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
",)"
    [Target']
_ -> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Target' -> String) -> [Target'] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Target' -> String
formatTarget [Target']
xs)

formatExpr :: Expr' -> String
formatExpr :: Expr' -> String
formatExpr (WithLoc' Maybe Loc
_ Expr
e0) = case Expr
e0 of
  BoolOp Expr'
e1 BoolOp
op Expr'
e2 -> Expr' -> String
formatExpr Expr'
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ BoolOp -> String
formatBoolOp BoolOp
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e2
  BinOp Expr'
e1 Operator
op Expr'
e2 -> Expr' -> String
formatExpr Expr'
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Operator -> String
formatOperator Operator
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e2
  UnaryOp UnaryOp
op Expr'
e -> UnaryOp -> String
formatUnaryOp UnaryOp
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e
  Lambda [(VarName', Type)]
args Expr'
body -> case [(VarName', Type)]
args of
    [] -> String
"lambda: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
body
    [(VarName', Type)]
_ -> String
"lambda " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " (((VarName', Type) -> String) -> [(VarName', Type)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (VarName -> String
unVarName (VarName -> String)
-> ((VarName', Type) -> VarName) -> (VarName', Type) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VarName' -> VarName
forall a. WithLoc' a -> a
value' (VarName' -> VarName)
-> ((VarName', Type) -> VarName') -> (VarName', Type) -> VarName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VarName', Type) -> VarName'
forall a b. (a, b) -> a
fst) [(VarName', Type)]
args) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
body
  IfExp Expr'
e1 Expr'
e2 Expr'
e3 -> Expr' -> String
formatExpr Expr'
e2 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" if " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" else " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e3
  ListComp Expr'
e Comprehension
comp -> String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Comprehension -> String
formatComprehension Comprehension
comp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  Compare Expr'
e1 CmpOp'
op Expr'
e2 -> Expr' -> String
formatExpr Expr'
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ CmpOp' -> String
formatCmpOp CmpOp'
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e2
  Call Expr'
f [Expr']
args -> case [Expr']
args of
    [WithLoc' Maybe Loc
_ (ListComp Expr'
e Comprehension
comp)] -> Expr' -> String
formatExpr Expr'
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Comprehension -> String
formatComprehension Comprehension
comp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
    [Expr']
_ -> Expr' -> String
formatExpr Expr'
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Expr' -> String) -> [Expr'] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr' -> String
formatExpr [Expr']
args) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  Constant Constant
const -> Constant -> String
formatConstant Constant
const
  Attribute Expr'
e (WithLoc' Maybe Loc
_ Attribute
x) -> Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ Attribute -> String
formatAttribute Attribute
x
  Subscript Expr'
e1 Expr'
e2 -> Expr' -> String
formatExpr Expr'
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e2 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  Starred Expr'
e -> String
"*" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e
  Name VarName'
x -> VarName -> String
unVarName (VarName' -> VarName
forall a. WithLoc' a -> a
value' VarName'
x)
  List Type
_ [Expr']
es -> String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Expr' -> String) -> [Expr'] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr' -> String
formatExpr [Expr']
es) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"
  Tuple [Expr']
es -> case [Expr']
es of
    [] -> String
"()"
    [Expr'
e] -> String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
",)"
    [Expr']
_ -> String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Expr' -> String) -> [Expr'] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr' -> String
formatExpr [Expr']
es) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  SubscriptSlice Expr'
e Maybe Expr'
from Maybe Expr'
to Maybe Expr'
step ->
    let from' :: String
from' = String -> (Expr' -> String) -> Maybe Expr' -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" Expr' -> String
formatExpr Maybe Expr'
from
        to' :: String
to' = String -> (Expr' -> String) -> Maybe Expr' -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" Expr' -> String
formatExpr Maybe Expr'
to
        step' :: String
step' = String -> (Expr' -> String) -> Maybe Expr' -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" ((Char
':' Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (Expr' -> String) -> Expr' -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr' -> String
formatExpr) Maybe Expr'
step
     in Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
from' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
to' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
step' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]"

formatStatement :: Statement -> [String]
formatStatement :: Statement -> [String]
formatStatement = \case
  Return Expr'
e -> [String
"return " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]
  AugAssign Target'
x Operator
op Expr'
e -> [Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Operator -> String
formatOperator Operator
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"= " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]
  AnnAssign Target'
x Type
t Expr'
e -> [Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]
  For Target'
x Expr'
iter [Statement]
body -> [String
"for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Target' -> String
formatTarget Target'
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
iter String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent]
  If Expr'
e [Statement]
body1 [Statement]
body2 -> case [Statement]
body2 of
    [] -> [String
"if " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body1 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent]
    [body2 :: Statement
body2@(If Expr'
_ [Statement]
_ [Statement]
_)] ->
      let String
elif : [String]
cont = Statement -> [String]
formatStatement Statement
body2
       in [String
"if " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body1 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent, String
"el" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
elif] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
cont
    [Statement]
_ -> [String
"if " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body1 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent, String
"else:", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body2 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent]
  Assert Expr'
e -> [String
"assert " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]
  Expr' Expr'
e -> [Expr' -> String
formatExpr Expr'
e]

formatToplevelStatement :: ToplevelStatement -> [String]
formatToplevelStatement :: ToplevelStatement -> [String]
formatToplevelStatement = \case
  ToplevelAnnAssign VarName'
x Type
t Expr'
e -> [VarName -> String
unVarName (VarName' -> VarName
forall a. WithLoc' a -> a
value' VarName'
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]
  ToplevelFunctionDef VarName'
f [(VarName', Type)]
args Type
ret [Statement]
body -> [String
"def " String -> String -> String
forall a. [a] -> [a] -> [a]
++ VarName -> String
unVarName (VarName' -> VarName
forall a. WithLoc' a -> a
value' VarName'
f) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " (((VarName', Type) -> String) -> [(VarName', Type)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\(VarName'
x, Type
t) -> VarName -> String
unVarName (VarName' -> VarName
forall a. WithLoc' a -> a
value' VarName'
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
t) [(VarName', Type)]
args) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") -> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
formatType Type
ret String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":", String
indent] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (Statement -> [String]) -> [Statement] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Statement -> [String]
formatStatement [Statement]
body [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
dedent]
  ToplevelAssert Expr'
e -> [String
"assert " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr' -> String
formatExpr Expr'
e]

formatProgram :: Program -> [String]
formatProgram :: Program -> [String]
formatProgram Program
prog = (ToplevelStatement -> [String]) -> Program -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ToplevelStatement -> [String]
formatToplevelStatement Program
prog

run' :: Program -> String
run' :: Program -> String
run' = [String] -> String
unlines ([String] -> String) -> (Program -> [String]) -> Program -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
makeIndentFromMarkers Int
4 ([String] -> [String])
-> (Program -> [String]) -> Program -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Program -> [String]
formatProgram

run :: Applicative m => Program -> m Text
run :: Program -> m Text
run = Text -> m Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> m Text) -> (Program -> Text) -> Program -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> (Program -> String) -> Program -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Program -> String
run'