{-# LANGUAGE LambdaCase #-}
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'