{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TupleSections #-}

-- | This is an internal module that provides the core parsing engine
-- functionality for the Demangler.

module Demangler.Engine
where

import           Control.Applicative
import           Control.Lens ( Lens, Lens', (&), (^.), (.~), _1, _2, _3 )
import           Data.Char
import           Data.List.NonEmpty ( NonEmpty((:|)) )
import           Data.Maybe ( fromMaybe )
import qualified Data.Sequence as Seq
import           Data.Text ( Text )
import qualified Data.Text as T

import           Demangler.Context
import           Demangler.Structure

#ifdef MIN_VERSION_panic
-- The debug flag is enabled in the cabal file
import           Debug.Trace
import           Panic

instance PanicComponent Demangler where
  panicComponentName _ = "Demangler"
  panicComponentIssues = const "https://github.com/galoisinc/demangler/issues"
  panicComponentRevision _ = ("main", "-")

cannot :: PanicComponent a => a -> String -> [String] -> b
cannot = panic
#else
cannot :: a -> String -> [String] -> Maybe b
cannot :: forall a b. a -> String -> [String] -> Maybe b
cannot a
_ String
_ [String]
_ = forall a. Maybe a
Nothing  -- signals a parsing failure, ultimately resulting in Original
#endif

data Demangler = Demangler


type Result = (Demangled, Context)

--------------------
-- Mangled name parsing basis types

-- | Next encodes a parsing step: provided with the current string and the
-- context, it may succeed with the remainder of the string after the portion
-- consumed by this parser and the updated context.

type Next a b = NextArg a -> Maybe (NextArg b)

type NextArg a = (Text, (a, (Context, ( Seq.Seq SubsCandidate
                                      , (Seq.Seq TemplateArg, Bool, Bool)))))

type AnyNext b = forall a . Next a b


nInp :: Lens' (NextArg a) Text
nInp :: forall a. Lens' (NextArg a) Text
nInp = forall s t a b. Field1 s t a b => Lens s t a b
_1

nVal :: Lens (NextArg a) (NextArg b) a b
nVal :: forall a b. Lens (NextArg a) (NextArg b) a b
nVal = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field1 s t a b => Lens s t a b
_1

nContext :: Lens' (NextArg a) Context
nContext :: forall a. Lens' (NextArg a) Context
nContext = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field1 s t a b => Lens s t a b
_1

nSubs :: Lens' (NextArg a) (Seq.Seq SubsCandidate)
nSubs :: forall a. Lens' (NextArg a) (Seq SubsCandidate)
nSubs = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field1 s t a b => Lens s t a b
_1

nTmplSubs :: Lens' (NextArg a) (Seq.Seq TemplateArg)
nTmplSubs :: forall a. Lens' (NextArg a) (Seq TemplateArg)
nTmplSubs = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field1 s t a b => Lens s t a b
_1

nTmplSubsLatch :: Lens' (NextArg a) Bool
nTmplSubsLatch :: forall a. Lens' (NextArg a) Bool
nTmplSubsLatch = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2

nTmplSubsLock :: Lens' (NextArg a) Bool
nTmplSubsLock :: forall a. Lens' (NextArg a) Bool
nTmplSubsLock = forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field3 s t a b => Lens s t a b
_3

ret :: Applicative f => NextArg a -> b -> f (NextArg b)
ret :: forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg a
i b
v = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall s t a b. Field2 s t a b => Lens s t a b
_2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. Field1 s t a b => Lens s t a b
_1 forall s t a b. ASetter s t a b -> b -> s -> t
.~ b
v forall a b. (a -> b) -> a -> b
$ NextArg a
i)

ret' :: Applicative f => b -> NextArg a -> f (NextArg b)
ret' :: forall (f :: * -> *) b a.
Applicative f =>
b -> NextArg a -> f (NextArg b)
ret' b
a NextArg a
b = forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg a
b b
a

rmap :: Applicative f => (a -> b) -> NextArg a -> f (NextArg b)
rmap :: forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap a -> b
f NextArg a
i = forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg a
i forall a b. (a -> b) -> a -> b
$ a -> b
f (NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal)


--------------------
-- Helpers

match :: Text -> Next a a
match :: forall a. Text -> Next a a
match Text
n NextArg a
i =
  let (Text
mp, Text
rp) = Int -> Text -> (Text, Text)
T.splitAt (Text -> Int
T.length Text
n) (NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Text
nInp)
  in do Bool -> Maybe ()
require (Text
mp forall a. Eq a => a -> a -> Bool
== Text
n)
        forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ NextArg a
i forall a b. a -> (a -> b) -> b
& forall a. Lens' (NextArg a) Text
nInp forall s t a b. ASetter s t a b -> b -> s -> t
.~ Text
rp

single_digit_num :: AnyNext Int
single_digit_num :: AnyNext Int
single_digit_num NextArg a
i =
  let txt :: Text
txt = NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Text
nInp
      d :: Char
d = Text -> Char
T.head Text
txt
  in if Bool -> Bool
not (Text -> Bool
T.null Text
txt) Bool -> Bool -> Bool
&& Char -> Bool
isDigit Char
d
     then forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NextArg a
i forall a b. a -> (a -> b) -> b
& forall a. Lens' (NextArg a) Text
nInp forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int -> Text -> Text
T.drop Int
1 Text
txt forall a b. a -> (a -> b) -> b
& forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall s t a b. ASetter s t a b -> b -> s -> t
.~ Char -> Int
ord Char
d forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'0'
     else forall a. Maybe a
Nothing

digits_num :: AnyNext Int
digits_num :: AnyNext Int
digits_num NextArg a
i =
  let (Text
d,Text
r) = (Char -> Bool) -> Text -> (Text, Text)
T.span Char -> Bool
isDigit forall a b. (a -> b) -> a -> b
$ NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Text
nInp
  in if Text -> Bool
T.null Text
d
     then forall a. Maybe a
Nothing
     else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NextArg a
i forall a b. a -> (a -> b) -> b
& forall a. Lens' (NextArg a) Text
nInp forall s t a b. ASetter s t a b -> b -> s -> t
.~ Text
r forall a b. a -> (a -> b) -> b
& forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall s t a b. ASetter s t a b -> b -> s -> t
.~ forall a. Read a => String -> a
read (Text -> String
T.unpack Text
d)

base36_num :: AnyNext Int
base36_num :: AnyNext Int
base36_num NextArg a
i =
  let isB36char :: Char -> Bool
isB36char Char
c = forall (t :: * -> *). Foldable t => t Bool -> Bool
or [ Char -> Bool
isDigit Char
c, Char -> Bool
isAsciiUpper Char
c ]
      nextB36Digit :: Int -> Char -> Int
nextB36Digit Int
a Char
x = (Int
a forall a. Num a => a -> a -> a
* Int
36)
                         forall a. Num a => a -> a -> a
+ (Char -> Int
ord Char
x forall a. Num a => a -> a -> a
- if Char -> Bool
isDigit Char
x then Char -> Int
ord Char
'0' else Char -> Int
ord Char
'A' forall a. Num a => a -> a -> a
- Int
10)
      (Text
d,Text
r) = (Char -> Bool) -> Text -> (Text, Text)
T.span Char -> Bool
isB36char forall a b. (a -> b) -> a -> b
$ NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Text
nInp
  in if Text -> Bool
T.null Text
d
     then forall a. Maybe a
Nothing
     else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NextArg a
i forall a b. a -> (a -> b) -> b
& forall a. Lens' (NextArg a) Text
nInp forall s t a b. ASetter s t a b -> b -> s -> t
.~ Text
r forall a b. a -> (a -> b) -> b
& forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall s t a b. ASetter s t a b -> b -> s -> t
.~ forall a. (a -> Char -> a) -> a -> Text -> a
T.foldl Int -> Char -> Int
nextB36Digit Int
0 Text
d

require :: Bool -> Maybe ()
require :: Bool -> Maybe ()
require Bool
t = if Bool
t then forall a. a -> Maybe a
Just () else forall a. Maybe a
Nothing

rdiscard :: NextArg a -> NextArg ()
rdiscard :: forall a. NextArg a -> NextArg ()
rdiscard = forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall s t a b. ASetter s t a b -> b -> s -> t
.~ ()

#if MIN_VERSION_base(4,16,0)
#else
asum :: (Foldable t, Alternative f) => t (f a) -> f a
asum = foldr (<|>) empty
#endif

asum' :: (Foldable t, Functor t, Alternative f) => t (a -> f b) -> a -> f b
asum' :: forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Functor t, Alternative f) =>
t (a -> f b) -> a -> f b
asum' t (a -> f b)
opts a
i = forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum forall a b. (a -> b) -> a -> b
$ (forall a b. (a -> b) -> a -> b
$ a
i) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t (a -> f b)
opts

tbd :: String -> Next a b
#ifdef MIN_VERSION_panic
tbd why i = trace ("TBD: " <> why <> " @ " <> (T.unpack $ i ^. nInp)) Nothing
#else
tbd :: forall a b. String -> Next a b
tbd String
_why = forall a b. a -> b -> a
const forall a. Maybe a
Nothing
#endif

some' :: AnyNext a -> Next b (NonEmpty a)
some' :: forall a b. AnyNext a -> Next b (NonEmpty a)
some' AnyNext a
p NextArg b
i = do NextArg a
e1 <- AnyNext a
p NextArg b
i
               forall {f :: * -> *} {a}.
Monad f =>
((Text,
  (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
 -> Maybe
      (Text,
       (a,
        (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool))))))
-> (Text,
    (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> f (NextArg [a])
go AnyNext a
p NextArg a
e1 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (NextArg a
e1 forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall a. a -> [a] -> NonEmpty a
:|)
  where go :: ((Text,
  (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
 -> Maybe
      (Text,
       (a,
        (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool))))))
-> (Text,
    (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> f (NextArg [a])
go (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> Maybe
     (Text,
      (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
p' (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
i' = case (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> Maybe
     (Text,
      (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
p' (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
i' of
                     Maybe
  (Text,
   (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
Nothing -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
i' []
                     Just (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
e -> ((Text,
  (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
 -> Maybe
      (Text,
       (a,
        (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool))))))
-> (Text,
    (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> f (NextArg [a])
go (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
-> Maybe
     (Text,
      (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
p' (Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
e forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap ((Text,
 (a, (Context, (Seq SubsCandidate, (Seq TemplateArg, Bool, Bool)))))
e forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall a. a -> [a] -> [a]
:)

many' :: Next () a -> Next () [a]
many' :: forall a. Next () a -> Next () [a]
many' Next () a
p NextArg ()
i = case Next () a
p NextArg ()
i of
              Maybe (NextArg a)
Nothing -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg ()
i []
              Just NextArg a
e -> forall a. Next () a -> Next () [a]
many' Next () a
p (forall a. NextArg a -> NextArg ()
rdiscard NextArg a
e) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (NextArg a
e forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall a. a -> [a] -> [a]
:)

optional' :: Next a b -> Next a (a, Maybe b)
optional' :: forall a b. Next a b -> Next a (a, Maybe b)
optional' Next a b
o NextArg a
i = (Next a b
o NextArg a
i forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap ((NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal,) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (,forall a. Maybe a
Nothing) NextArg a
i

(>&=>) :: Next a b -> Next b c -> Next a (b,c)
Next a b
a >&=> :: forall a b c. Next a b -> Next b c -> Next a (b, c)
>&=> Next b c
b = \NextArg a
i -> do NextArg b
x <- Next a b
a NextArg a
i
                    NextArg c
y <- Next b c
b NextArg b
x
                    forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap ((NextArg b
x forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal,)) NextArg c
y
infix 2 >&=>

insert :: b -> Next a b
insert :: forall b a. b -> Next a b
insert b
v = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. Lens (NextArg a) (NextArg b) a b
nVal forall s t a b. ASetter s t a b -> b -> s -> t
.~ b
v)

noop :: Next a a
noop :: forall a. Next a a
noop = forall a. a -> Maybe a
Just

end_of_input :: Next a a
end_of_input :: forall a. Next a a
end_of_input NextArg a
i = if Text -> Bool
T.null (NextArg a
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Text
nInp) then forall a. a -> Maybe a
Just NextArg a
i else forall a. Maybe a
Nothing

#ifdef MIN_VERSION_panic
traceP :: String -> Next a a
traceP at i = trace (at <> " @ " <> (T.unpack $ i ^. nInp) <> " #subs=" <> show (Seq.length (i ^. nSubs)) <> " #tmplSubs=" <> show (Seq.length (i ^. nTmplSubs))) $ Just i
#endif

----------------------------------------------------------------------

-- | Add an additional PrefixR entry to the end of a Prefix.

extendPrefix :: Prefix -> PrefixR -> Prefix
extendPrefix :: Prefix -> PrefixR -> Prefix
extendPrefix = \case
      PrefixTemplateParam TemplateArg
tp PrefixR
PrefixEnd -> TemplateArg -> PrefixR -> Prefix
PrefixTemplateParam TemplateArg
tp
      PrefixDeclType ()
dt PrefixR
PrefixEnd -> () -> PrefixR -> Prefix
PrefixDeclType ()
dt
      Prefix PrefixR
PrefixEnd -> PrefixR -> Prefix
Prefix
      PrefixTemplateParam TemplateArg
tp PrefixR
sp -> TemplateArg -> PrefixR -> Prefix
PrefixTemplateParam TemplateArg
tp forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixR -> PrefixR -> PrefixR
extPfx2 PrefixR
sp
      PrefixDeclType ()
dt PrefixR
sp -> () -> PrefixR -> Prefix
PrefixDeclType ()
dt forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixR -> PrefixR -> PrefixR
extPfx2 PrefixR
sp
      Prefix PrefixR
sp -> PrefixR -> Prefix
Prefix forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixR -> PrefixR -> PrefixR
extPfx2 PrefixR
sp
      Prefix
o -> forall a. a -> Maybe a -> a
fromMaybe (forall a b. a -> b -> a
const Prefix
o) forall a b. (a -> b) -> a -> b
$ forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"extendPrefix"
           [ String
"What prefix to extend? " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Prefix
o ]
extPfx2 :: PrefixR -> (PrefixR -> PrefixR)
extPfx2 :: PrefixR -> PrefixR -> PrefixR
extPfx2 = \case
      PrefixR
PrefixEnd -> forall a. a -> a
id
      PrefixUQName UnqualifiedName
uqn PrefixR
sp -> UnqualifiedName -> PrefixR -> PrefixR
PrefixUQName UnqualifiedName
uqn forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixR -> PrefixR -> PrefixR
extPfx2 PrefixR
sp
      PrefixTemplateArgs TemplateArgs
ta PrefixR
sp -> TemplateArgs -> PrefixR -> PrefixR
PrefixTemplateArgs TemplateArgs
ta forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixR -> PrefixR -> PrefixR
extPfx2 PrefixR
sp

-- | Split a prefix into the last element and the initial portion without that
-- last element (if possible).

prefixInitLast :: Prefix -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
prefixInitLast :: Prefix -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
prefixInitLast = \case
  PrefixTemplateParam TemplateArg
tp PrefixR
p2 -> (PrefixR -> Prefix)
-> PrefixR -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
descend (TemplateArg -> PrefixR -> Prefix
PrefixTemplateParam TemplateArg
tp) PrefixR
p2
  PrefixDeclType ()
dt PrefixR
sp -> (PrefixR -> Prefix)
-> PrefixR -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
descend (() -> PrefixR -> Prefix
PrefixDeclType ()
dt) PrefixR
sp
  Prefix PrefixR
p2 -> (PrefixR -> Prefix)
-> PrefixR -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
descend PrefixR -> Prefix
Prefix PrefixR
p2
  Prefix
o -> forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"prefixInitLast"
       [ String
"Not a valid prefix for this need"
       , forall a. Show a => a -> String
show Prefix
o
       ]
  where
    descend :: (PrefixR -> Prefix) -> PrefixR
            -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
    descend :: (PrefixR -> Prefix)
-> PrefixR -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
descend PrefixR -> Prefix
mkPfx PrefixR
pfxR = let (PrefixR -> PrefixR
rf, Maybe (Either UnqualifiedName TemplateArgs)
mb'le) = forall {c}.
(PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
-> PrefixR
-> (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
go (forall a. a -> a
id, forall a. Maybe a
Nothing) PrefixR
pfxR
                         in case Maybe (Either UnqualifiedName TemplateArgs)
mb'le of
                              Maybe (Either UnqualifiedName TemplateArgs)
Nothing -> forall a. Maybe a
Nothing
                              Just Either UnqualifiedName TemplateArgs
le -> forall a. a -> Maybe a
Just (PrefixR -> Prefix
mkPfx forall a b. (a -> b) -> a -> b
$ PrefixR -> PrefixR
rf PrefixR
PrefixEnd, Either UnqualifiedName TemplateArgs
le)
    go :: (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
-> PrefixR
-> (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
go (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen = \case
      PrefixUQName UnqualifiedName
uqn PrefixR
PrefixEnd -> (forall a b. (a, b) -> a
fst (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left UnqualifiedName
uqn)
      PrefixUQName UnqualifiedName
uqn PrefixR
subpfx ->
        (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
-> PrefixR
-> (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
go (forall a b. (a, b) -> a
fst (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnqualifiedName -> PrefixR -> PrefixR
PrefixUQName UnqualifiedName
uqn, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left UnqualifiedName
uqn) PrefixR
subpfx
      PrefixTemplateArgs TemplateArgs
ta PrefixR
PrefixEnd -> (forall a b. (a, b) -> a
fst (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right TemplateArgs
ta)
      PrefixTemplateArgs TemplateArgs
ta PrefixR
subpfx ->
        (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
-> PrefixR
-> (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
go (forall a b. (a, b) -> a
fst (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen forall b c a. (b -> c) -> (a -> b) -> a -> c
. TemplateArgs -> PrefixR -> PrefixR
PrefixTemplateArgs TemplateArgs
ta, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right TemplateArgs
ta) PrefixR
subpfx
      PrefixR
PrefixEnd -> (PrefixR -> c, Maybe (Either UnqualifiedName TemplateArgs))
seen