{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Ormolu.Fixity.Printer
( printFixityMap,
)
where
import qualified Data.Char as Char
import qualified Data.Map.Strict as Map
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Text.Lazy.Builder (Builder)
import qualified Data.Text.Lazy.Builder as B
import qualified Data.Text.Lazy.Builder.Int as B
import Ormolu.Fixity
printFixityMap :: FixityMap -> Text
printFixityMap :: FixityMap -> Text
printFixityMap =
Text -> Text
TL.toStrict
(Text -> Text) -> (FixityMap -> Text) -> FixityMap -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
B.toLazyText
(Builder -> Text) -> (FixityMap -> Builder) -> FixityMap -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
([Builder] -> Builder)
-> (FixityMap -> [Builder]) -> FixityMap -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((FixityDirection, Int, OpName) -> Builder)
-> [(FixityDirection, Int, OpName)] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FixityDirection, Int, OpName) -> Builder
renderOne
([(FixityDirection, Int, OpName)] -> [Builder])
-> (FixityMap -> [(FixityDirection, Int, OpName)])
-> FixityMap
-> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((OpName, FixityInfo) -> [(FixityDirection, Int, OpName)])
-> [(OpName, FixityInfo)] -> [(FixityDirection, Int, OpName)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (OpName, FixityInfo) -> [(FixityDirection, Int, OpName)]
decompose
([(OpName, FixityInfo)] -> [(FixityDirection, Int, OpName)])
-> (FixityMap -> [(OpName, FixityInfo)])
-> FixityMap
-> [(FixityDirection, Int, OpName)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FixityMap -> [(OpName, FixityInfo)]
forall k a. Map k a -> [(k, a)]
Map.toList
where
decompose :: (OpName, FixityInfo) -> [(FixityDirection, Int, OpName)]
decompose :: (OpName, FixityInfo) -> [(FixityDirection, Int, OpName)]
decompose (OpName
operator, FixityInfo {Int
Maybe FixityDirection
fiDirection :: Maybe FixityDirection
fiMinPrecedence :: Int
fiMaxPrecedence :: Int
fiDirection :: FixityInfo -> Maybe FixityDirection
fiMinPrecedence :: FixityInfo -> Int
fiMaxPrecedence :: FixityInfo -> Int
..}) =
let forDirection :: a -> [(a, Int, OpName)]
forDirection a
dir =
(a
dir, Int
fiMinPrecedence, OpName
operator)
(a, Int, OpName) -> [(a, Int, OpName)] -> [(a, Int, OpName)]
forall a. a -> [a] -> [a]
: [ (a
dir, Int
fiMaxPrecedence, OpName
operator)
| Int
fiMinPrecedence Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
fiMaxPrecedence
]
in case Maybe FixityDirection
fiDirection of
Maybe FixityDirection
Nothing -> (FixityDirection -> [(FixityDirection, Int, OpName)])
-> [FixityDirection] -> [(FixityDirection, Int, OpName)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap FixityDirection -> [(FixityDirection, Int, OpName)]
forall {a}. a -> [(a, Int, OpName)]
forDirection [FixityDirection
InfixL, FixityDirection
InfixR]
Just FixityDirection
dir -> FixityDirection -> [(FixityDirection, Int, OpName)]
forall {a}. a -> [(a, Int, OpName)]
forDirection FixityDirection
dir
renderOne :: (FixityDirection, Int, OpName) -> Builder
renderOne :: (FixityDirection, Int, OpName) -> Builder
renderOne (FixityDirection
fixityDirection, Int
n, OpName Text
operator) =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ case FixityDirection
fixityDirection of
FixityDirection
InfixL -> Builder
"infixl"
FixityDirection
InfixR -> Builder
"infixr"
FixityDirection
InfixN -> Builder
"infix",
Builder
" ",
Int -> Builder
forall a. Integral a => a -> Builder
B.decimal Int
n,
Builder
" ",
if Text -> Bool
isTickedOperator Text
operator
then Builder
"`" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
B.fromText Text
operator Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"`"
else Text -> Builder
B.fromText Text
operator,
Builder
"\n"
]
isTickedOperator :: Text -> Bool
isTickedOperator = Bool -> ((Char, Text) -> Bool) -> Maybe (Char, Text) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (Char -> Bool
Char.isLetter (Char -> Bool) -> ((Char, Text) -> Char) -> (Char, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char, Text) -> Char
forall a b. (a, b) -> a
fst) (Maybe (Char, Text) -> Bool)
-> (Text -> Maybe (Char, Text)) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe (Char, Text)
T.uncons