----------------------------------------------------------------------------
-- |
-- Module      :  FastTags.LexerTypes
-- Copyright   :  (c) Sergey Vinokurov 2019
--
-- Auxiliary types for lexer.
----------------------------------------------------------------------------

{-# LANGUAGE BangPatterns               #-}
{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase                 #-}

module FastTags.LexerTypes
    ( Context(..)
    , AlexCode(..)
    , LitStyle(..)
    , LitMode(..)
    , isLiterateEnabled
    , isLiterateBirdInside
    , isLiterateLatexInside
    ) where

import Control.DeepSeq

-- | Whether we're currently in Haskell context or within Template Haskell
-- quasiquoter and should discard as much as possible.
data Context = CtxHaskell | CtxQuasiquoter
    deriving (Int -> Context -> ShowS
[Context] -> ShowS
Context -> String
(Int -> Context -> ShowS)
-> (Context -> String) -> ([Context] -> ShowS) -> Show Context
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Context] -> ShowS
$cshowList :: [Context] -> ShowS
show :: Context -> String
$cshow :: Context -> String
showsPrec :: Int -> Context -> ShowS
$cshowsPrec :: Int -> Context -> ShowS
Show, Context -> Context -> Bool
(Context -> Context -> Bool)
-> (Context -> Context -> Bool) -> Eq Context
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Context -> Context -> Bool
$c/= :: Context -> Context -> Bool
== :: Context -> Context -> Bool
$c== :: Context -> Context -> Bool
Eq, Eq Context
Eq Context
-> (Context -> Context -> Ordering)
-> (Context -> Context -> Bool)
-> (Context -> Context -> Bool)
-> (Context -> Context -> Bool)
-> (Context -> Context -> Bool)
-> (Context -> Context -> Context)
-> (Context -> Context -> Context)
-> Ord Context
Context -> Context -> Bool
Context -> Context -> Ordering
Context -> Context -> Context
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Context -> Context -> Context
$cmin :: Context -> Context -> Context
max :: Context -> Context -> Context
$cmax :: Context -> Context -> Context
>= :: Context -> Context -> Bool
$c>= :: Context -> Context -> Bool
> :: Context -> Context -> Bool
$c> :: Context -> Context -> Bool
<= :: Context -> Context -> Bool
$c<= :: Context -> Context -> Bool
< :: Context -> Context -> Bool
$c< :: Context -> Context -> Bool
compare :: Context -> Context -> Ordering
$ccompare :: Context -> Context -> Ordering
$cp1Ord :: Eq Context
Ord)

-- | Abstract wrapper around alex automata states.
newtype AlexCode = AlexCode { AlexCode -> Int
unAlexCode :: Int }
    deriving (AlexCode -> AlexCode -> Bool
(AlexCode -> AlexCode -> Bool)
-> (AlexCode -> AlexCode -> Bool) -> Eq AlexCode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AlexCode -> AlexCode -> Bool
$c/= :: AlexCode -> AlexCode -> Bool
== :: AlexCode -> AlexCode -> Bool
$c== :: AlexCode -> AlexCode -> Bool
Eq, Eq AlexCode
Eq AlexCode
-> (AlexCode -> AlexCode -> Ordering)
-> (AlexCode -> AlexCode -> Bool)
-> (AlexCode -> AlexCode -> Bool)
-> (AlexCode -> AlexCode -> Bool)
-> (AlexCode -> AlexCode -> Bool)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> Ord AlexCode
AlexCode -> AlexCode -> Bool
AlexCode -> AlexCode -> Ordering
AlexCode -> AlexCode -> AlexCode
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AlexCode -> AlexCode -> AlexCode
$cmin :: AlexCode -> AlexCode -> AlexCode
max :: AlexCode -> AlexCode -> AlexCode
$cmax :: AlexCode -> AlexCode -> AlexCode
>= :: AlexCode -> AlexCode -> Bool
$c>= :: AlexCode -> AlexCode -> Bool
> :: AlexCode -> AlexCode -> Bool
$c> :: AlexCode -> AlexCode -> Bool
<= :: AlexCode -> AlexCode -> Bool
$c<= :: AlexCode -> AlexCode -> Bool
< :: AlexCode -> AlexCode -> Bool
$c< :: AlexCode -> AlexCode -> Bool
compare :: AlexCode -> AlexCode -> Ordering
$ccompare :: AlexCode -> AlexCode -> Ordering
$cp1Ord :: Eq AlexCode
Ord, Int -> AlexCode -> ShowS
[AlexCode] -> ShowS
AlexCode -> String
(Int -> AlexCode -> ShowS)
-> (AlexCode -> String) -> ([AlexCode] -> ShowS) -> Show AlexCode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AlexCode] -> ShowS
$cshowList :: [AlexCode] -> ShowS
show :: AlexCode -> String
$cshow :: AlexCode -> String
showsPrec :: Int -> AlexCode -> ShowS
$cshowsPrec :: Int -> AlexCode -> ShowS
Show, Int -> AlexCode
AlexCode -> Int
AlexCode -> [AlexCode]
AlexCode -> AlexCode
AlexCode -> AlexCode -> [AlexCode]
AlexCode -> AlexCode -> AlexCode -> [AlexCode]
(AlexCode -> AlexCode)
-> (AlexCode -> AlexCode)
-> (Int -> AlexCode)
-> (AlexCode -> Int)
-> (AlexCode -> [AlexCode])
-> (AlexCode -> AlexCode -> [AlexCode])
-> (AlexCode -> AlexCode -> [AlexCode])
-> (AlexCode -> AlexCode -> AlexCode -> [AlexCode])
-> Enum AlexCode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: AlexCode -> AlexCode -> AlexCode -> [AlexCode]
$cenumFromThenTo :: AlexCode -> AlexCode -> AlexCode -> [AlexCode]
enumFromTo :: AlexCode -> AlexCode -> [AlexCode]
$cenumFromTo :: AlexCode -> AlexCode -> [AlexCode]
enumFromThen :: AlexCode -> AlexCode -> [AlexCode]
$cenumFromThen :: AlexCode -> AlexCode -> [AlexCode]
enumFrom :: AlexCode -> [AlexCode]
$cenumFrom :: AlexCode -> [AlexCode]
fromEnum :: AlexCode -> Int
$cfromEnum :: AlexCode -> Int
toEnum :: Int -> AlexCode
$ctoEnum :: Int -> AlexCode
pred :: AlexCode -> AlexCode
$cpred :: AlexCode -> AlexCode
succ :: AlexCode -> AlexCode
$csucc :: AlexCode -> AlexCode
Enum, Integer -> AlexCode
AlexCode -> AlexCode
AlexCode -> AlexCode -> AlexCode
(AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode)
-> (AlexCode -> AlexCode)
-> (AlexCode -> AlexCode)
-> (Integer -> AlexCode)
-> Num AlexCode
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> AlexCode
$cfromInteger :: Integer -> AlexCode
signum :: AlexCode -> AlexCode
$csignum :: AlexCode -> AlexCode
abs :: AlexCode -> AlexCode
$cabs :: AlexCode -> AlexCode
negate :: AlexCode -> AlexCode
$cnegate :: AlexCode -> AlexCode
* :: AlexCode -> AlexCode -> AlexCode
$c* :: AlexCode -> AlexCode -> AlexCode
- :: AlexCode -> AlexCode -> AlexCode
$c- :: AlexCode -> AlexCode -> AlexCode
+ :: AlexCode -> AlexCode -> AlexCode
$c+ :: AlexCode -> AlexCode -> AlexCode
Num, Num AlexCode
Ord AlexCode
Num AlexCode
-> Ord AlexCode -> (AlexCode -> Rational) -> Real AlexCode
AlexCode -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: AlexCode -> Rational
$ctoRational :: AlexCode -> Rational
$cp2Real :: Ord AlexCode
$cp1Real :: Num AlexCode
Real, Enum AlexCode
Real AlexCode
Real AlexCode
-> Enum AlexCode
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> AlexCode)
-> (AlexCode -> AlexCode -> (AlexCode, AlexCode))
-> (AlexCode -> AlexCode -> (AlexCode, AlexCode))
-> (AlexCode -> Integer)
-> Integral AlexCode
AlexCode -> Integer
AlexCode -> AlexCode -> (AlexCode, AlexCode)
AlexCode -> AlexCode -> AlexCode
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: AlexCode -> Integer
$ctoInteger :: AlexCode -> Integer
divMod :: AlexCode -> AlexCode -> (AlexCode, AlexCode)
$cdivMod :: AlexCode -> AlexCode -> (AlexCode, AlexCode)
quotRem :: AlexCode -> AlexCode -> (AlexCode, AlexCode)
$cquotRem :: AlexCode -> AlexCode -> (AlexCode, AlexCode)
mod :: AlexCode -> AlexCode -> AlexCode
$cmod :: AlexCode -> AlexCode -> AlexCode
div :: AlexCode -> AlexCode -> AlexCode
$cdiv :: AlexCode -> AlexCode -> AlexCode
rem :: AlexCode -> AlexCode -> AlexCode
$crem :: AlexCode -> AlexCode -> AlexCode
quot :: AlexCode -> AlexCode -> AlexCode
$cquot :: AlexCode -> AlexCode -> AlexCode
$cp2Integral :: Enum AlexCode
$cp1Integral :: Real AlexCode
Integral, AlexCode -> ()
(AlexCode -> ()) -> NFData AlexCode
forall a. (a -> ()) -> NFData a
rnf :: AlexCode -> ()
$crnf :: AlexCode -> ()
NFData)

-- | Literate style we're currently in.
data LitStyle = Bird | Latex
    deriving (LitStyle -> LitStyle -> Bool
(LitStyle -> LitStyle -> Bool)
-> (LitStyle -> LitStyle -> Bool) -> Eq LitStyle
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LitStyle -> LitStyle -> Bool
$c/= :: LitStyle -> LitStyle -> Bool
== :: LitStyle -> LitStyle -> Bool
$c== :: LitStyle -> LitStyle -> Bool
Eq, Eq LitStyle
Eq LitStyle
-> (LitStyle -> LitStyle -> Ordering)
-> (LitStyle -> LitStyle -> Bool)
-> (LitStyle -> LitStyle -> Bool)
-> (LitStyle -> LitStyle -> Bool)
-> (LitStyle -> LitStyle -> Bool)
-> (LitStyle -> LitStyle -> LitStyle)
-> (LitStyle -> LitStyle -> LitStyle)
-> Ord LitStyle
LitStyle -> LitStyle -> Bool
LitStyle -> LitStyle -> Ordering
LitStyle -> LitStyle -> LitStyle
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LitStyle -> LitStyle -> LitStyle
$cmin :: LitStyle -> LitStyle -> LitStyle
max :: LitStyle -> LitStyle -> LitStyle
$cmax :: LitStyle -> LitStyle -> LitStyle
>= :: LitStyle -> LitStyle -> Bool
$c>= :: LitStyle -> LitStyle -> Bool
> :: LitStyle -> LitStyle -> Bool
$c> :: LitStyle -> LitStyle -> Bool
<= :: LitStyle -> LitStyle -> Bool
$c<= :: LitStyle -> LitStyle -> Bool
< :: LitStyle -> LitStyle -> Bool
$c< :: LitStyle -> LitStyle -> Bool
compare :: LitStyle -> LitStyle -> Ordering
$ccompare :: LitStyle -> LitStyle -> Ordering
$cp1Ord :: Eq LitStyle
Ord, Int -> LitStyle -> ShowS
[LitStyle] -> ShowS
LitStyle -> String
(Int -> LitStyle -> ShowS)
-> (LitStyle -> String) -> ([LitStyle] -> ShowS) -> Show LitStyle
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LitStyle] -> ShowS
$cshowList :: [LitStyle] -> ShowS
show :: LitStyle -> String
$cshow :: LitStyle -> String
showsPrec :: Int -> LitStyle -> ShowS
$cshowsPrec :: Int -> LitStyle -> ShowS
Show, Int -> LitStyle
LitStyle -> Int
LitStyle -> [LitStyle]
LitStyle -> LitStyle
LitStyle -> LitStyle -> [LitStyle]
LitStyle -> LitStyle -> LitStyle -> [LitStyle]
(LitStyle -> LitStyle)
-> (LitStyle -> LitStyle)
-> (Int -> LitStyle)
-> (LitStyle -> Int)
-> (LitStyle -> [LitStyle])
-> (LitStyle -> LitStyle -> [LitStyle])
-> (LitStyle -> LitStyle -> [LitStyle])
-> (LitStyle -> LitStyle -> LitStyle -> [LitStyle])
-> Enum LitStyle
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: LitStyle -> LitStyle -> LitStyle -> [LitStyle]
$cenumFromThenTo :: LitStyle -> LitStyle -> LitStyle -> [LitStyle]
enumFromTo :: LitStyle -> LitStyle -> [LitStyle]
$cenumFromTo :: LitStyle -> LitStyle -> [LitStyle]
enumFromThen :: LitStyle -> LitStyle -> [LitStyle]
$cenumFromThen :: LitStyle -> LitStyle -> [LitStyle]
enumFrom :: LitStyle -> [LitStyle]
$cenumFrom :: LitStyle -> [LitStyle]
fromEnum :: LitStyle -> Int
$cfromEnum :: LitStyle -> Int
toEnum :: Int -> LitStyle
$ctoEnum :: Int -> LitStyle
pred :: LitStyle -> LitStyle
$cpred :: LitStyle -> LitStyle
succ :: LitStyle -> LitStyle
$csucc :: LitStyle -> LitStyle
Enum, LitStyle
LitStyle -> LitStyle -> Bounded LitStyle
forall a. a -> a -> Bounded a
maxBound :: LitStyle
$cmaxBound :: LitStyle
minBound :: LitStyle
$cminBound :: LitStyle
Bounded)

-- | Literate mode of whole file. Either @LitVanilla@ all the time, which means
-- it's non-literate file or @LitOutside@ when looking at literate comments and
-- @LitInside mode@ when lexing Haskell source with specific literate @mode@.
data LitMode a = LitInside !a | LitOutside | LitVanilla
    deriving (LitMode a -> LitMode a -> Bool
(LitMode a -> LitMode a -> Bool)
-> (LitMode a -> LitMode a -> Bool) -> Eq (LitMode a)
forall a. Eq a => LitMode a -> LitMode a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LitMode a -> LitMode a -> Bool
$c/= :: forall a. Eq a => LitMode a -> LitMode a -> Bool
== :: LitMode a -> LitMode a -> Bool
$c== :: forall a. Eq a => LitMode a -> LitMode a -> Bool
Eq, Eq (LitMode a)
Eq (LitMode a)
-> (LitMode a -> LitMode a -> Ordering)
-> (LitMode a -> LitMode a -> Bool)
-> (LitMode a -> LitMode a -> Bool)
-> (LitMode a -> LitMode a -> Bool)
-> (LitMode a -> LitMode a -> Bool)
-> (LitMode a -> LitMode a -> LitMode a)
-> (LitMode a -> LitMode a -> LitMode a)
-> Ord (LitMode a)
LitMode a -> LitMode a -> Bool
LitMode a -> LitMode a -> Ordering
LitMode a -> LitMode a -> LitMode a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (LitMode a)
forall a. Ord a => LitMode a -> LitMode a -> Bool
forall a. Ord a => LitMode a -> LitMode a -> Ordering
forall a. Ord a => LitMode a -> LitMode a -> LitMode a
min :: LitMode a -> LitMode a -> LitMode a
$cmin :: forall a. Ord a => LitMode a -> LitMode a -> LitMode a
max :: LitMode a -> LitMode a -> LitMode a
$cmax :: forall a. Ord a => LitMode a -> LitMode a -> LitMode a
>= :: LitMode a -> LitMode a -> Bool
$c>= :: forall a. Ord a => LitMode a -> LitMode a -> Bool
> :: LitMode a -> LitMode a -> Bool
$c> :: forall a. Ord a => LitMode a -> LitMode a -> Bool
<= :: LitMode a -> LitMode a -> Bool
$c<= :: forall a. Ord a => LitMode a -> LitMode a -> Bool
< :: LitMode a -> LitMode a -> Bool
$c< :: forall a. Ord a => LitMode a -> LitMode a -> Bool
compare :: LitMode a -> LitMode a -> Ordering
$ccompare :: forall a. Ord a => LitMode a -> LitMode a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (LitMode a)
Ord, Int -> LitMode a -> ShowS
[LitMode a] -> ShowS
LitMode a -> String
(Int -> LitMode a -> ShowS)
-> (LitMode a -> String)
-> ([LitMode a] -> ShowS)
-> Show (LitMode a)
forall a. Show a => Int -> LitMode a -> ShowS
forall a. Show a => [LitMode a] -> ShowS
forall a. Show a => LitMode a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LitMode a] -> ShowS
$cshowList :: forall a. Show a => [LitMode a] -> ShowS
show :: LitMode a -> String
$cshow :: forall a. Show a => LitMode a -> String
showsPrec :: Int -> LitMode a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> LitMode a -> ShowS
Show, a -> LitMode b -> LitMode a
(a -> b) -> LitMode a -> LitMode b
(forall a b. (a -> b) -> LitMode a -> LitMode b)
-> (forall a b. a -> LitMode b -> LitMode a) -> Functor LitMode
forall a b. a -> LitMode b -> LitMode a
forall a b. (a -> b) -> LitMode a -> LitMode b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> LitMode b -> LitMode a
$c<$ :: forall a b. a -> LitMode b -> LitMode a
fmap :: (a -> b) -> LitMode a -> LitMode b
$cfmap :: forall a b. (a -> b) -> LitMode a -> LitMode b
Functor)

{-# INLINE isLiterateEnabled #-}
isLiterateEnabled :: LitMode a -> Bool
isLiterateEnabled :: LitMode a -> Bool
isLiterateEnabled = \case
    LitInside a
_ -> Bool
True
    LitMode a
LitOutside  -> Bool
True
    LitMode a
LitVanilla  -> Bool
False

{-# INLINE isLiterateBirdInside #-}
isLiterateBirdInside :: LitMode LitStyle -> Bool
isLiterateBirdInside :: LitMode LitStyle -> Bool
isLiterateBirdInside = \case
    LitInside LitStyle
Bird  -> Bool
True
    LitInside LitStyle
Latex -> Bool
False
    LitMode LitStyle
LitOutside      -> Bool
True
    LitMode LitStyle
LitVanilla      -> Bool
False

{-# INLINE isLiterateLatexInside #-}
isLiterateLatexInside :: LitMode LitStyle -> Bool
isLiterateLatexInside :: LitMode LitStyle -> Bool
isLiterateLatexInside = \case
    LitInside LitStyle
Bird  -> Bool
False
    LitInside LitStyle
Latex -> Bool
True
    LitMode LitStyle
LitOutside      -> Bool
False
    LitMode LitStyle
LitVanilla      -> Bool
False