{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} {- | Module : Language.Egison.PrettyPrint Licence : MIT This module contains pretty printing for Egison syntax -} module Language.Egison.Pretty ( prettyTopExprs , PrettyS(..) , prettyStr , prettyStr' , showTSV ) where import Data.Foldable (toList) import qualified Data.HashMap.Strict as HashMap import Data.List (intercalate) import Data.Text.Prettyprint.Doc import Data.Text.Prettyprint.Doc.Render.String (renderString) import qualified Data.Vector as V import Language.Egison.AST import Language.Egison.MathExpr hiding (Printable(..)) import Language.Egison.Data -- -- Pretty printing for Non-S syntax -- prettyTopExprs :: [EgisonTopExpr] -> Doc [EgisonTopExpr] prettyTopExprs exprs = vsep $ punctuate line (map pretty exprs) instance Pretty EgisonTopExpr where pretty (Define x (LambdaExpr args body)) = hsep (pretty x : map pretty args) <+> indentBlock (pretty ":=") [pretty body] pretty (Define x expr) = pretty x <+> indentBlock (pretty ":=") [pretty expr] pretty (Test expr) = pretty expr pretty (LoadFile file) = pretty "loadFile" <+> pretty (show file) pretty (Load lib) = pretty "load" <+> pretty (show lib) pretty _ = error "Unsupported topexpr" instance Pretty EgisonExpr where -- Use |viaShow| to correctly handle escaped characters pretty (CharExpr x) = viaShow x pretty (StringExpr x) = viaShow x pretty (BoolExpr x) = pretty x pretty (IntegerExpr x) = pretty x pretty (FloatExpr x) = pretty x pretty (VarExpr x) = pretty x pretty FreshVarExpr = pretty "#" pretty (IndexedExpr True e indices) = pretty' e <> cat (map pretty indices) pretty (IndexedExpr False e indices) = pretty' e <> pretty "..." <> cat (map pretty indices) pretty (SubrefsExpr b e1 e2) = applyLike [pretty "subrefs" <> (if b then pretty "!" else emptyDoc), pretty' e1, pretty' e2] pretty (SuprefsExpr b e1 e2) = applyLike [pretty "suprefs" <> (if b then pretty "!" else emptyDoc), pretty' e1, pretty' e2] pretty (UserrefsExpr b e1 e2) = applyLike [pretty "userRefs" <> (if b then pretty "!" else emptyDoc), pretty' e1, pretty' e2] pretty (InductiveDataExpr c xs) = nest 2 (sep (pretty c : map pretty' xs)) pretty (TupleExpr xs) = tupled (map pretty xs) pretty (CollectionExpr xs) | length xs < 20 = list (map pretty xs) | otherwise = pretty "[" <> align (fillSepAtom (punctuate comma (map pretty xs))) <> pretty "]" pretty (HashExpr xs) = listoid "{|" "|}" (map (\(x, y) -> tupled [pretty x, pretty y]) xs) pretty (VectorExpr xs) = listoid "[|" "|]" (map pretty xs) pretty (LambdaExpr xs e) = lambdaLike (pretty "\\") (map pretty xs) (pretty "->") (pretty e) pretty (MemoizedLambdaExpr xs e) = lambdaLike (pretty "memoizedLambda ") (map pretty xs) (pretty "->") (pretty e) pretty (CambdaExpr x e) = indentBlock (pretty "cambda" <+> pretty x <+> pretty "->") [pretty e] pretty (PatternFunctionExpr xs p) = lambdaLike (pretty "\\") (map pretty xs) (pretty "=>") (pretty p) pretty (IfExpr x y z) = indentBlock (pretty "if" <+> pretty x) [pretty "then" <+> pretty y, pretty "else" <+> pretty z] pretty (LetRecExpr bindings body) = hang 1 (pretty "let" <+> align (vsep (map pretty bindings)) <> hardline <> pretty "in" <+> align (pretty body)) pretty (LetExpr _ _) = error "unreachable" pretty (LetStarExpr _ _) = error "unreachable" pretty (WithSymbolsExpr xs e) = indentBlock (pretty "withSymbols" <+> list (map pretty xs)) [pretty e] pretty (MatchExpr BFSMode tgt matcher clauses) = nest 2 (pretty "match" <+> pretty tgt <+> prettyMatch matcher clauses) pretty (MatchExpr DFSMode tgt matcher clauses) = nest 2 (pretty "matchDFS" <+> pretty tgt <+> prettyMatch matcher clauses) pretty (MatchAllExpr BFSMode tgt matcher clauses) = nest 2 (pretty "matchAll" <+> pretty tgt <+> prettyMatch matcher clauses) pretty (MatchAllExpr DFSMode tgt matcher clauses) = nest 2 (pretty "matchAllDFS" <+> pretty tgt <+> prettyMatch matcher clauses) pretty (MatchLambdaExpr matcher clauses) = nest 2 (pretty "\\match" <+> prettyMatch matcher clauses) pretty (MatchAllLambdaExpr matcher clauses) = nest 2 (pretty "\\matchAll" <+> prettyMatch matcher clauses) pretty (MatcherExpr patDefs) = nest 2 (pretty "matcher" <> hardline <> align (vsep (map prettyPatDef patDefs))) where prettyPatDef (pppat, expr, body) = nest 2 (pipe <+> pretty pppat <+> pretty "as" <+> group (pretty expr) <+> pretty "with" <> hardline <> align (vsep (map prettyPatBody body))) prettyPatBody (pdpat, expr) = indentBlock (pipe <+> align (pretty pdpat) <+> pretty "->") [pretty expr] pretty (AlgebraicDataMatcherExpr patDefs) = nest 2 (pretty "algebraicDataMatcher" <> hardline <> align (vsep (map prettyPatDef patDefs))) where prettyPatDef (name, exprs) = pipe <+> hsep (pretty name : map pretty exprs) pretty (QuoteExpr e) = squote <> pretty' e pretty (QuoteSymbolExpr e) = pretty '`' <> pretty' e pretty (PrefixExpr op x@(IntegerExpr _)) = pretty op <> pretty x pretty (PrefixExpr op x) | isAtomOrApp x = pretty op <+> pretty x | otherwise = pretty op <+> parens (pretty x) -- (x1 op' x2) op y pretty (InfixExpr op x@(InfixExpr op' _ _) y) = if priority op > priority op' || priority op == priority op' && assoc op == RightAssoc then parens (pretty x) <+> pretty op <> infixRight (pretty'' y) else pretty x <+> pretty op <> infixRight (pretty'' y) -- x op (y1 op' y2) pretty (InfixExpr op x y@(InfixExpr op' _ _)) = if priority op > priority op' || priority op == priority op' && assoc op == LeftAssoc then pretty'' x <+> pretty op <> infixRight (parens (pretty y)) else pretty'' x <+> pretty op <> infixRight (pretty y) pretty (InfixExpr op x y) = pretty'' x <+> pretty op <> infixRight (pretty'' y) pretty (SectionExpr op Nothing Nothing) = parens (pretty op) pretty (SectionExpr op (Just x) Nothing) = parens (pretty x <+> pretty op) pretty (SectionExpr op Nothing (Just x)) = parens (pretty op <+> pretty x) pretty (DoExpr [] y) = pretty "do" <+> pretty y pretty (DoExpr xs (ApplyExpr (VarExpr (Var ["return"] [])) (TupleExpr []))) = pretty "do" <+> align (hsepHard (map prettyDoBinds xs)) pretty (DoExpr xs y) = pretty "do" <+> align (hsepHard (map prettyDoBinds xs ++ [pretty y])) pretty (IoExpr x) = pretty "io" <+> pretty x pretty (SeqExpr e1 e2) = applyLike [pretty "seq", pretty' e1, pretty' e2] pretty (ApplyExpr x y@(TupleExpr [])) = applyLike (map pretty' [x, y]) pretty (ApplyExpr x (TupleExpr ys)) = applyLike (map pretty' (x : ys)) pretty (ApplyExpr x y) = applyLike [pretty' x, pretty' y] pretty (CApplyExpr e1 e2) = applyLike [pretty "capply", pretty' e1, pretty' e2] pretty (AnonParamFuncExpr n e) = pretty n <> pretty '#' <> pretty' e pretty (AnonParamExpr n) = pretty '%' <> pretty n pretty (GenerateTensorExpr gen shape) = applyLike [pretty "generateTensor", pretty' gen, pretty' shape] pretty (TensorExpr e1 e2) = applyLike [pretty "tensor", pretty' e1, pretty' e2] pretty (TensorContractExpr e1) = applyLike [pretty "contract", pretty' e1] pretty (TensorMapExpr e1 e2) = applyLike [pretty "tensorMap", pretty' e1, pretty' e2] pretty (TensorMap2Expr e1 e2 e3) = applyLike [pretty "tensorMap2", pretty' e1, pretty' e2, pretty' e3] pretty (TransposeExpr e1 e2) = applyLike [pretty "transpose", pretty' e1, pretty' e2] pretty (FlipIndicesExpr _) = error "unreachable" pretty (FunctionExpr xs) = pretty "function" <+> tupled (map pretty xs) pretty SomethingExpr = pretty "something" pretty UndefinedExpr = pretty "undefined" pretty _ = pretty "REPLACEME" instance Pretty Arg where pretty (ScalarArg x) = pretty x pretty (InvertedScalarArg x) = pretty "*" <> pretty x pretty (TensorArg x) = pretty '%' <> pretty x instance Pretty Var where pretty (Var xs is) = concatWith (surround dot) (map pretty xs) <> hcat (map pretty is) instance Pretty VarWithIndices where pretty (VarWithIndices xs is) = concatWith (surround dot) (map pretty xs) <> hcat (map pretty is) instance Pretty InnerExpr where pretty (ElementExpr x) = pretty x pretty (SubCollectionExpr _) = error "Not supported" instance {-# OVERLAPPING #-} Pretty BindingExpr where pretty ([var], LambdaExpr args body) = hsep (pretty var : map pretty args) <+> indentBlock (pretty ":=") [pretty body] pretty ([var], expr) = pretty var <+> pretty ":=" <+> align (pretty expr) pretty (vars, expr) = tupled (map pretty vars) <+> pretty ":=" <+> align (pretty expr) instance {-# OVERLAPPING #-} Pretty MatchClause where pretty (pat, expr) = pipe <+> align (pretty pat) <+> indentBlock (pretty "->") [pretty expr] instance {-# OVERLAPPING #-} Pretty (Index ()) where -- Used for 'Var' pretty Subscript{} = pretty '_' pretty Superscript{} = pretty '~' pretty SupSubscript{} = pretty "~_" pretty DFscript{} = pretty "" pretty Userscript{} = pretty '|' pretty _ = undefined instance {-# OVERLAPPING #-} Pretty (Index String) where -- for 'VarWithIndices' pretty (Superscript s) = pretty ("~" ++ s) pretty (Subscript s) = pretty ("_" ++ s) pretty (SupSubscript s) = pretty ("~_" ++ s) pretty (DFscript _ _) = pretty "" pretty (Userscript i) = pretty ("|" ++ show i) pretty _ = undefined instance (Pretty a, Complex a) => Pretty (Index a) where pretty (Subscript i) = pretty '_' <> pretty' i pretty (Superscript i) = pretty '~' <> pretty' i pretty (SupSubscript i) = pretty "~_" <> pretty' i pretty (MultiSubscript i j) = pretty '_' <> pretty' i <> pretty "..._" <> pretty' j pretty (MultiSuperscript i j) = pretty '~' <> pretty' i <> pretty "...~" <> pretty' j pretty (DFscript _ _) = undefined pretty (Userscript i) = pretty '|' <> pretty' i instance Pretty EgisonPattern where pretty WildCard = pretty "_" pretty (PatVar x) = pretty "$" <> pretty x pretty (ValuePat v) = pretty "#" <> pretty' v pretty (PredPat v) = pretty "?" <> pretty' v pretty (IndexedPat p indices) = pretty p <> hcat (map (\i -> pretty '_' <> pretty' i) indices) pretty (LetPat binds pat) = pretty "let" <+> align (vsep (map pretty binds)) <+> pretty "in" <+> pretty pat -- (p11 op' p12) op p2 pretty (InfixPat op p1@(InfixPat op' _ _) p2) = if priority op > priority op' || priority op == priority op' && assoc op == RightAssoc then parens (pretty p1) <+> pretty (repr op) <+> pretty'' p2 else pretty p1 <+> pretty (repr op) <+> pretty'' p2 -- p1 op (p21 op' p22) pretty (InfixPat op p1 p2@(InfixPat op' _ _)) = if priority op > priority op' || priority op == priority op' && assoc op == LeftAssoc then pretty'' p1 <+> pretty (repr op) <+> parens (pretty p2) else pretty'' p1 <+> pretty (repr op) <+> pretty p2 pretty (InfixPat op p1 p2) = pretty'' p1 <+> pretty (repr op) <+> pretty'' p2 pretty (NotPat pat) = pretty "!" <> pretty' pat pretty (TuplePat pats) = tupled $ map pretty pats pretty (InductivePat "nil" []) = pretty "[]" pretty (InductivePat "cons" [p, InductivePat "nil" []]) = pretty "[" <> pretty p <> pretty "]" pretty (InductivePat ctor xs) = hsep (pretty ctor : map pretty' xs) pretty (LoopPat i range p1 p2) = hang 2 (pretty "loop" <+> pretty '$' <> pretty i <+> pretty range <> flatAlt (hardline <> group (pretty' p1) <> hardline <> group (pretty' p2)) (space <> pretty' p1 <+> pretty' p2)) pretty ContPat = pretty "..." pretty (PApplyPat fn ps) = applyLike (pretty' fn : map pretty' ps) pretty (VarPat x) = pretty ('~' : x) pretty SeqNilPat = pretty "{}" pretty (SeqConsPat p1 p2) = listoid "{" "}" (f p1 p2) where f p1 SeqNilPat = [pretty p1] f p1 (SeqConsPat p2 p3) = pretty p1 : f p2 p3 f p1 p2 = [pretty p1, pretty p2] pretty LaterPatVar = pretty "@" pretty (DApplyPat p ps) = applyLike (map pretty' (p : ps)) pretty _ = pretty "REPLACEME" instance Pretty LoopRange where pretty (LoopRange from (ApplyExpr (VarExpr (Var ["from"] [])) (InfixExpr (Infix { repr = "-'" }) _ (IntegerExpr 1))) pat) = tupled [pretty from, pretty pat] pretty (LoopRange from to pat) = tupled [pretty from, pretty to, pretty pat] instance Pretty PrimitivePatPattern where pretty PPWildCard = pretty "_" pretty PPPatVar = pretty "$" pretty (PPValuePat x) = pretty ('#' : '$' : x) pretty (PPInductivePat x pppats) = hsep (pretty x : map pretty pppats) pretty (PPTuplePat pppats) = tupled (map pretty pppats) instance Pretty PrimitiveDataPattern where pretty PDWildCard = pretty "_" pretty (PDPatVar x) = pretty ('$' : x) pretty (PDInductivePat x pdpats) = applyLike (pretty x : map pretty' pdpats) pretty (PDTuplePat pdpats) = tupled (map pretty pdpats) pretty PDEmptyPat = pretty "[]" pretty (PDConsPat pdp1 pdp2) = pretty'' pdp1 <+> pretty "::" <+> pretty'' pdp2 pretty (PDSnocPat pdp1 pdp2) = applyLike [pretty "snoc", pretty' pdp1, pretty' pdp2] pretty (PDConstantPat expr) = pretty expr instance Pretty Infix where pretty op | isWedge op = pretty ("!" ++ repr op) | otherwise = pretty (repr op) class Complex a where isAtom :: a -> Bool isAtomOrApp :: a -> Bool isInfix :: a -> Bool instance Complex EgisonExpr where isAtom (IntegerExpr i) | i < 0 = False isAtom (InductiveDataExpr _ []) = True isAtom (InductiveDataExpr _ _) = False isAtom PrefixExpr{} = False isAtom InfixExpr{} = False isAtom ApplyExpr{} = False isAtom CApplyExpr{} = False isAtom LambdaExpr{} = False isAtom MemoizedLambdaExpr{} = False isAtom CambdaExpr{} = False isAtom PatternFunctionExpr{} = False isAtom IfExpr{} = False isAtom LetRecExpr{} = False isAtom SubrefsExpr{} = False isAtom SuprefsExpr{} = False isAtom UserrefsExpr{} = False isAtom WithSymbolsExpr{} = False isAtom MatchExpr{} = False isAtom MatchAllExpr{} = False isAtom MatchLambdaExpr{} = False isAtom MatchAllLambdaExpr{} = False isAtom MatcherExpr{} = False isAtom AlgebraicDataMatcherExpr{} = False isAtom GenerateTensorExpr{} = False isAtom TensorExpr{} = False isAtom FunctionExpr{} = False isAtom TensorContractExpr{} = False isAtom TensorMapExpr{} = False isAtom TensorMap2Expr{} = False isAtom TransposeExpr{} = False isAtom _ = True isAtomOrApp ApplyExpr{} = True isAtomOrApp InductiveDataExpr{} = True isAtomOrApp e = isAtom e isInfix InfixExpr{} = True isInfix _ = False instance Complex EgisonPattern where isAtom (LetPat _ _) = False isAtom (InductivePat _ []) = True isAtom (InductivePat _ _) = False isAtom (InfixPat _ _ _) = False isAtom (LoopPat _ _ _ _) = False isAtom (PApplyPat _ []) = True isAtom (PApplyPat _ _) = False isAtom _ = True isAtomOrApp PApplyPat{} = True isAtomOrApp InductivePat{} = True isAtomOrApp e = isAtom e isInfix (InfixPat _ _ _) = True isInfix _ = False instance Complex PrimitiveDataPattern where isAtom (PDInductivePat _ []) = True isAtom (PDInductivePat _ _) = False isAtom (PDConsPat _ _) = False isAtom (PDSnocPat _ _) = False isAtom _ = True isAtomOrApp PDInductivePat{} = True isAtomOrApp PDSnocPat{} = True isAtomOrApp e = isAtom e isInfix (PDConsPat _ _) = True isInfix _ = False pretty' :: (Pretty a, Complex a) => a -> Doc ann pretty' x | isAtom x = pretty x | otherwise = parens $ pretty x pretty'' :: (Pretty a, Complex a) => a -> Doc ann pretty'' x | isAtomOrApp x || isInfix x = pretty x | otherwise = parens $ pretty x -- Display "hoge" instead of "() := hoge" prettyDoBinds :: BindingExpr -> Doc ann prettyDoBinds ([], expr) = pretty expr prettyDoBinds (vs, expr) = pretty "let" <+> pretty (vs, expr) prettyMatch :: EgisonExpr -> [MatchClause] -> Doc ann prettyMatch matcher clauses = pretty "as" <> group (flatAlt (hardline <> pretty matcher) (space <> pretty matcher) <+> pretty "with") <> hardline <> align (vsep (map pretty clauses)) listoid :: String -> String -> [Doc ann] -> Doc ann listoid lp rp elems = encloseSep (pretty lp) (pretty rp) (comma <> space) elems -- Just like |fillSep|, but does not break the atomicity of grouped Docs fillSepAtom :: [Doc ann] -> Doc ann fillSepAtom [] = emptyDoc fillSepAtom [x] = x fillSepAtom (x:xs) = x <> fillSepAtom' xs where fillSepAtom' [] = emptyDoc fillSepAtom' (x:xs) = group (flatAlt (hardline <> x) (space <> x)) <> fillSepAtom' xs indentBlock :: Doc ann -> [Doc ann] -> Doc ann indentBlock header bodies = group (nest 2 (header <> flatAlt (hardline <> hsepHard bodies) (space <> hsep bodies))) hsepHard :: [Doc ann] -> Doc ann hsepHard = concatWith (\x y -> x <> hardline <> y) lambdaLike :: Doc ann -> [Doc ann] -> Doc ann -> Doc ann -> Doc ann lambdaLike start [] arrow body = indentBlock (start <> pretty "()" <+> arrow) [body] lambdaLike start args arrow body = indentBlock (start <> hsep args <+> arrow) [body] applyLike :: [Doc ann] -> Doc ann applyLike = hang 2 . sep . map group -- Tests if the argument can be printed in a single line, and if not, -- inserts a line break before printing it. -- This is useful for nicely printing infix expressions. infixRight :: Doc ann -> Doc ann infixRight p = group (flatAlt (hardline <> p) (space <> p)) -- -- Pretty printer for error messages -- prettyStr :: Pretty a => a -> String prettyStr = renderString . layoutPretty (LayoutOptions Unbounded) . pretty prettyStr' :: (Pretty a, Complex a) => a -> String prettyStr' = renderString . layoutPretty (LayoutOptions Unbounded) . pretty' -- -- Pretty printer for S-expression -- class PrettyS a where prettyS :: a -> String instance PrettyS EgisonValue where prettyS (Char c) = "c#" ++ [c] prettyS (String str) = show str prettyS (Bool True) = "#t" prettyS (Bool False) = "#f" prettyS (ScalarData mExpr) = prettyS mExpr prettyS (TensorData (Tensor [_] xs js)) = "[| " ++ unwords (map prettyS (V.toList xs)) ++ " |]" ++ concatMap prettyS js prettyS (TensorData (Tensor [0, 0] _ js)) = "[| [| |] |]" ++ concatMap prettyS js prettyS (TensorData (Tensor [_, j] xs js)) = "[| " ++ f (fromIntegral j) (V.toList xs) ++ "|]" ++ concatMap prettyS js where f _ [] = "" f j xs = "[| " ++ unwords (map prettyS (take j xs)) ++ " |] " ++ f j (drop j xs) prettyS (TensorData (Tensor ns xs js)) = "(tensor {" ++ unwords (map show ns) ++ "} {" ++ unwords (map prettyS (V.toList xs)) ++ "} )" ++ concatMap prettyS js prettyS (Float x) = show x prettyS (InductiveData name vals) = "<" ++ name ++ concatMap ((' ':) . prettyS) vals ++ ">" prettyS (Tuple vals) = "[" ++ unwords (map prettyS vals) ++ "]" prettyS (Collection vals) = "{" ++ unwords (map prettyS (toList vals)) ++ "}" prettyS (IntHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}" prettyS (CharHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}" prettyS (StrHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}" prettyS UserMatcher{} = "#" prettyS (Func Nothing _ args _) = "(lambda [" ++ unwords (map ('$':) args) ++ "] ...)" prettyS (Func (Just name) _ _ _) = prettyS name prettyS (AnonParamFunc _ n _) = show n ++ "#(...)" prettyS (CFunc Nothing _ name _) = "(cambda " ++ name ++ " ...)" prettyS (CFunc (Just name) _ _ _) = prettyS name prettyS (MemoizedFunc Nothing _ _ _ names _) = "(memoized-lambda [" ++ unwords names ++ "] ...)" prettyS (MemoizedFunc (Just name) _ _ _ _ _) = prettyS name prettyS PatternFunc{} = "#" prettyS (PrimitiveFunc name _) = "#" prettyS (IOFunc _) = "#" prettyS (Port _) = "#" prettyS Something = "something" prettyS Undefined = "undefined" prettyS World = "#" prettyS _ = "(not supported)" instance PrettyS Var where prettyS = show instance PrettyS ScalarData where prettyS (Div p1 (Plus [Term 1 []])) = prettyS p1 prettyS (Div p1 p2) = "(/ " ++ prettyS p1 ++ " " ++ prettyS p2 ++ ")" instance PrettyS PolyExpr where prettyS (Plus []) = "0" prettyS (Plus [t]) = prettyS t prettyS (Plus ts) = "(+ " ++ unwords (map prettyS ts) ++ ")" instance PrettyS TermExpr where prettyS (Term a []) = show a prettyS (Term 1 [x]) = showPoweredSymbol x prettyS (Term 1 xs) = "(* " ++ unwords (map showPoweredSymbol xs) ++ ")" prettyS (Term a xs) = "(* " ++ show a ++ " " ++ unwords (map showPoweredSymbol xs) ++ ")" showPoweredSymbol :: (SymbolExpr, Integer) -> String showPoweredSymbol (x, 1) = prettyS x showPoweredSymbol (x, n) = prettyS x ++ "^" ++ show n instance PrettyS SymbolExpr where prettyS (Symbol _ (':':':':':':_) []) = "#" prettyS (Symbol _ s []) = s prettyS (Symbol _ s js) = s ++ concatMap prettyS js prettyS (Apply fn mExprs) = "(" ++ prettyS fn ++ " " ++ unwords (map prettyS mExprs) ++ ")" prettyS (Quote mExprs) = "'" ++ prettyS mExprs prettyS (FunctionData name _ _ js) = show name ++ concatMap prettyS js showTSV :: EgisonValue -> String showTSV (Tuple (val:vals)) = foldl (\r x -> r ++ "\t" ++ x) (prettyS val) (map prettyS vals) showTSV (Collection vals) = intercalate "\t" (map prettyS (toList vals)) showTSV val = prettyS val instance PrettyS a => PrettyS (Index a) where prettyS (Subscript i) = "_" ++ prettyS i prettyS (Superscript i) = "~" ++ prettyS i prettyS (SupSubscript i) = "~_" ++ prettyS i prettyS (MultiSubscript x y) = "_[" ++ prettyS x ++ "]..._[" ++ prettyS y ++ "]" prettyS (MultiSuperscript x y) = "~[" ++ prettyS x ++ "]...~[" ++ prettyS y ++ "]" prettyS (DFscript _ _) = "" prettyS (Userscript i) = "|" ++ prettyS i instance {-# OVERLAPPING #-} PrettyS (Index EgisonValue) where prettyS (Superscript i) = case i of ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "~[" ++ prettyS i ++ "]" _ -> "~" ++ prettyS i prettyS (Subscript i) = case i of ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "_[" ++ prettyS i ++ "]" _ -> "_" ++ prettyS i prettyS (SupSubscript i) = "~_" ++ prettyS i prettyS (DFscript i j) = "_d" ++ show i ++ show j prettyS (Userscript i) = case i of ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "_[" ++ prettyS i ++ "]" _ -> "|" ++ prettyS i