{-# LANGUAGE Rank2Types #-}

-- Haskell expression parser.  Big hack, but only uses documented APIs so it
-- should be more robust than the previous hack.
module Lambdabot.Util.Parser
    ( withParsed
    , prettyPrintInLine
    ) where

import Data.Generics
import Language.Haskell.Exts.Simple

-- |Parse a string as an 'Exp' or a 'Decl', apply the given generic transformation to it,
-- and re-render it back to text.
withParsed :: (forall a. (Data a, Eq a) => a -> a) -> String -> String
withParsed :: (forall a. (Data a, Eq a) => a -> a) -> String -> String
withParsed forall a. (Data a, Eq a) => a -> a
_ String
"" = String
"Error: expected a Haskell expression or declaration"
withParsed forall a. (Data a, Eq a) => a -> a
f String
s  = case (String -> ParseResult Exp
parseExp String
s, String -> ParseResult Decl
parseDecl String
s) of
    (ParseOk Exp
a, ParseResult Decl
_)          -> Exp -> String
forall a. Pretty a => a -> String
prettyPrintInLine (Exp -> String) -> Exp -> String
forall a b. (a -> b) -> a -> b
$ Exp -> Exp
forall a. (Data a, Eq a) => a -> a
f Exp
a
    (ParseResult Exp
_, ParseOk Decl
a)          -> Decl -> String
forall a. Pretty a => a -> String
prettyPrintInLine (Decl -> String) -> Decl -> String
forall a b. (a -> b) -> a -> b
$ Decl -> Decl
forall a. (Data a, Eq a) => a -> a
f Decl
a
    (ParseFailed SrcLoc
l String
e,  ParseResult Decl
_)   -> SrcLoc -> String
forall a. Pretty a => a -> String
prettyPrint SrcLoc
l String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char
':' Char -> String -> String
forall a. a -> [a] -> [a]
: String
e

-- |Render haskell code in a compact format
prettyPrintInLine :: Pretty a => a -> String
prettyPrintInLine :: a -> String
prettyPrintInLine = PPHsMode -> a -> String
forall a. Pretty a => PPHsMode -> a -> String
prettyPrintWithMode (PPHsMode
defaultMode { layout :: PPLayout
layout = PPLayout
PPInLine })