{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Demangler.Substitution
  (
    -- * Parse a substitution reference
    substitution
    -- * Substitute the found substitution into the result
  , substituteUnqualifiedName
  , substitutePrefix
  , substitutePrefixR
  , substituteTemplateParam
  , substituteTemplatePrefix
  , substituteType
  , stdSubstToType
  -- * When a subtitution candidate has been parsed, it is recorded here
  , canSubstUnscopedTemplateName
  , canSubstPrefix
  , canSubstTemplateArg
  , canSubstTemplateParam
  , canSubstTemplatePrefix
  , canSubstType
  , canSubstTypes
  , dropLastSubst
  )
where

import           Control.Applicative
import           Control.Lens ( (&), (^.), (%~) )
import           Control.Monad
import           Data.List.NonEmpty ( NonEmpty((:|)) )
import qualified Data.List.NonEmpty as NEL
import           Data.Maybe
import           Data.Sequence ( (|>), ViewR((:>)) )
import qualified Data.Sequence as Seq

import           Demangler.Context
import           Demangler.Engine
import           Demangler.Structure
import           Demangler.PPrint ()

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

import           Prelude hiding ( last )


--------------------
-- * Handling Substitutions
--
-- Substition could be handled at parsing time or at pretty-printing time.  This
-- implementation handles substitution at parsing time for the following reasons:
--
--  1. Parser "type" information to confirm that the substitution value is
--     appropriate to be substituted in the current parsing element.
--
--  2. The resulting Demangled structure is fully expressed and does not need to
--     hold additional "sequencing" information that would allow Substitution
--     target identification.  Also simplifies use of the Demangled structure.
--
--  3. The sequencing information can also be more difficult to re-determine at
--     pretty-printing time (viz. the efforts in the itanium-abi package which
--     performs substitution at pretty-printing time).
--
-- Substitution is very tricky: the BNF (at the URL in the Dismantle module, and
-- which isn't fully correct) specifies that wherever "<substitution>" appears, a
-- substitution may be made OR a substitution capture can occur.  It also states
-- that substitutions are not duplicated.  It implies (but is not clear) that
-- there are actually two substitution namespaces: regular substitutions and
-- template subsitutions, where the former are accessed as "S[n]_" and the latter
-- are accessed as "T[m]_", where the n and m ordering are within the associated
-- namespace.  Here are the additional rules and exceptions not discussed:
--
--   * Constructor/Destructor names are not captured or substituted (but operator
--     names are)
--
--   * Known substitutions ("St" for "std::", "Sa" for "std::allocator", etc.)
--     are *not* added as a possible substitution if they appear alone, but if
--     they are part of a prefix (i.e. they are followed by other information)
--     then they are added as part of that longer sequence (e.g. "foo::list<i>"
--     will add "foo", "foo::list", and "foo::list<i>" for a total of 3 possible
--     substitution candidates whereas "std::list<i>" will add "std::list" and
--     "std::list<i>" for only 2 possible substitution candidates.
--
--   * Template argument substutions are in a different namespace and recursive
--     template arguments are not substitition candidates (e.g. foo<bar<int>>)
--     results in only one template substitution candidate (bar<int>).


-- | Parse a substitution specification and get the raw Substitution' result;
-- these should always be translated and never actually returned in the Demangled
-- result.

substitution :: AnyNext Substitution'
substitution :: AnyNext Substitution'
substitution =
  forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Functor t, Alternative f) =>
t (a -> f b) -> a -> f b
asum' [ forall a. Text -> Next a a
match Text
"S" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> AnyNext Int
base36_num forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (Natural -> Substitution'
Subs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => Int -> a
toEnum) forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall a. Text -> Next a a
match Text
"_"
        , forall a. Text -> Next a a
match Text
"S_" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const Substitution'
SubsFirst)
        , forall a. Text -> Next a a
match Text
"St" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst Substitution
SubStd)
        , forall a. Text -> Next a a
match Text
"Sa" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst Substitution
SubAlloc)
        , forall a. Text -> Next a a
match Text
"Sb" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst Substitution
SubBasicString)
        , forall a. Text -> Next a a
match Text
"Ss" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst forall a b. (a -> b) -> a -> b
$ StdType -> Substitution
SubStdType StdType
BasicStringChar)
        , forall a. Text -> Next a a
match Text
"Si" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst forall a b. (a -> b) -> a -> b
$ StdType -> Substitution
SubStdType StdType
BasicIStream)
        , forall a. Text -> Next a a
match Text
"So" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst forall a b. (a -> b) -> a -> b
$ StdType -> Substitution
SubStdType StdType
BasicOStream)
        , forall a. Text -> Next a a
match Text
"Sd" forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (f :: * -> *) a b.
Applicative f =>
(a -> b) -> NextArg a -> f (NextArg b)
rmap (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ Substitution -> Substitution'
SubsConst forall a b. (a -> b) -> a -> b
$ StdType -> Substitution
SubStdType StdType
BasicIOStream)
        ]

-- Internal to lookup a parsed Substitution'
getSubst :: NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst :: NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i =
  case NextArg Substitution'
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal of
    Substitution'
SubsFirst -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. Int -> Seq a -> Maybe a
Seq.lookup Int
0 forall a b. (a -> b) -> a -> b
$ NextArg Substitution'
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) (Seq SubsCandidate)
nSubs
    Subs Natural
n -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. Int -> Seq a -> Maybe a
Seq.lookup (forall a. Enum a => a -> Int
fromEnum Natural
n forall a. Num a => a -> a -> a
+ Int
1) forall a b. (a -> b) -> a -> b
$ NextArg Substitution'
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) (Seq SubsCandidate)
nSubs
    SubsConst Substitution
s -> forall a b. a -> Either a b
Left Substitution
s


#ifdef MIN_VERSION_panic
dumpSubs :: (Monad f, Applicative f)
         => NextArg a -> String -> f (NextArg a)
dumpSubs spec what = do
    mapM_ (traceM . show) $ Seq.zip
             (Seq.fromList [0.. Seq.length (spec ^. nSubs)])
             ((\ue -> (ue, sez @"debug" (WC ue (spec ^. nContext))))
              <$> spec ^. nSubs)
    mapM_ (traceM . show) $ Seq.zip
             (Seq.fromList [0.. Seq.length (spec ^. nTmplSubs)])
             ((\ue -> ('T', ue, sez @"debug" (WC ue (spec ^. nContext))))
              <$> spec ^. nTmplSubs)
    traceM $ "Subs Total: " <> show ((Seq.length $ spec ^. nSubs) + (Seq.length $ spec ^. nTmplSubs)) <> " "
        <> show ((Seq.length $ spec ^. nSubs), (Seq.length $ spec ^. nTmplSubs))
        <> " --> " <> sez @"debug" what
    pure spec
#endif

invalidSubst :: Show a => String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst :: forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
for NextArg a
spec = \case
  Just SubsCandidate
s -> do
#ifdef MIN_VERSION_panic
    -- Debug details
    _ <- dumpSubs spec "Just"
#endif
    forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
for
         [ String
"Invalid " forall a. Semigroup a => a -> a -> a
<> String
for forall a. Semigroup a => a -> a -> a
<> String
" substitution (" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show (NextArg a
spec forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal) forall a. Semigroup a => a -> a -> a
<> String
"):"
         , forall a. Show a => a -> String
show SubsCandidate
s
         ]
  Maybe SubsCandidate
Nothing -> do
#ifdef MIN_VERSION_panic
    -- Debug details
    _ <- dumpSubs spec "Nothing"
#endif
    forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
for
         [ String
"Invalid " forall a. Semigroup a => a -> a -> a
<> String
for forall a. Semigroup a => a -> a -> a
<> String
" substitution reference:"
         , forall a. Show a => a -> String
show (NextArg a
spec forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal)
         ]

substituteUnqualifiedName :: Next Substitution UnqualifiedName
                          -> Next Substitution' UnqualifiedName
substituteUnqualifiedName :: Next Substitution UnqualifiedName
-> Next Substitution' UnqualifiedName
substituteUnqualifiedName Next Substitution UnqualifiedName
direct NextArg Substitution'
i =
  case NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i of
    Right (Just (SC_UQName Bool
_ UnqualifiedName
n)) -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i UnqualifiedName
n
    Right Maybe SubsCandidate
_ -> forall a. Maybe a
Nothing
    Left Substitution
s -> Next Substitution UnqualifiedName
direct forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Substitution
s

substituteType :: (Next Substitution Type_) -> Next Substitution' Type_
substituteType :: Next Substitution Type_ -> Next Substitution' Type_
substituteType Next Substitution Type_
embed NextArg Substitution'
i =
  case NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i of
    Right (Just (SC_Type Type_
t)) -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Type_
t
    Right (Just (SC_Prefix Prefix
p)) -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Prefix -> Maybe Type_
prefixToType Prefix
p
    Right (Just (SC_UQName Bool
isStd UnqualifiedName
uqn)) ->
      forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i forall a b. (a -> b) -> a -> b
$ Name -> Type_
ClassUnionStructEnum forall a b. (a -> b) -> a -> b
$ Bool -> UnqualifiedName -> Name
UnscopedName Bool
isStd UnqualifiedName
uqn
    Right Maybe SubsCandidate
o -> forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
"Type" NextArg Substitution'
i Maybe SubsCandidate
o
    Left Substitution
s -> Next Substitution Type_
embed forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Substitution
s


prefixToType :: Prefix -> Maybe Type_
prefixToType :: Prefix -> Maybe Type_
prefixToType Prefix
pfx =
  Name -> Type_
ClassUnionStructEnum
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> case Prefix -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
prefixInitLast Prefix
pfx of
      Maybe (Prefix, Either UnqualifiedName TemplateArgs)
Nothing -> forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"prefixToType"
                 [ String
"Cannot convert prefix to type: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Prefix
pfx ]
      Just (Prefix
iniPfx, Left UnqualifiedName
uqn) ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NestedName -> Name
NameNested forall a b. (a -> b) -> a -> b
$ Prefix
-> UnqualifiedName
-> [CVQualifier]
-> Maybe RefQualifier
-> NestedName
NestedName Prefix
iniPfx UnqualifiedName
uqn [] forall a. Maybe a
Nothing
      Just (Prefix
iniPfx, Right TemplateArgs
ta) ->
        let tmpltpfx :: Maybe TemplatePrefix
tmpltpfx =
              case Prefix -> Maybe (Prefix, Either UnqualifiedName TemplateArgs)
prefixInitLast Prefix
iniPfx of
                Just (Prefix
EmptyPrefix, Left UnqualifiedName
luqn) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NonEmpty UnqualifiedName -> TemplatePrefix
GlobalTemplate (UnqualifiedName
luqn forall a. a -> [a] -> NonEmpty a
:| [])
                Just (Prefix
p, Left UnqualifiedName
luqn) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Prefix -> NonEmpty UnqualifiedName -> TemplatePrefix
NestedTemplate Prefix
p (UnqualifiedName
luqn forall a. a -> [a] -> NonEmpty a
:| [])
                Maybe (Prefix, Either UnqualifiedName TemplateArgs)
_ -> forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"prefixToType"
                     [ String
"Cannot convert ta prefix to type: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Prefix
pfx ]
            mkntn :: TemplatePrefix -> NestedName
mkntn TemplatePrefix
tpfx = TemplatePrefix
-> TemplateArgs
-> [CVQualifier]
-> Maybe RefQualifier
-> NestedName
NestedTemplateName TemplatePrefix
tpfx TemplateArgs
ta [] forall a. Maybe a
Nothing
        in NestedName -> Name
NameNested forall b c a. (b -> c) -> (a -> b) -> a -> c
. TemplatePrefix -> NestedName
mkntn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe TemplatePrefix
tmpltpfx


substitutePrefix :: (Next Substitution Prefix) -> Next Substitution' Prefix
substitutePrefix :: Next Substitution Prefix -> Next Substitution' Prefix
substitutePrefix Next Substitution Prefix
direct NextArg Substitution'
i =
  case NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i of
    Right (Just (SC_Prefix Prefix
p)) -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Prefix
p
    Right Maybe SubsCandidate
o -> forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
"Prefix" NextArg Substitution'
i Maybe SubsCandidate
o
    Left Substitution
s -> Next Substitution Prefix
direct forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Substitution
s

substitutePrefixR :: (Next Substitution PrefixR) -> Next Substitution' PrefixR
substitutePrefixR :: Next Substitution PrefixR -> Next Substitution' PrefixR
substitutePrefixR Next Substitution PrefixR
direct NextArg Substitution'
i =
  case NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i of
    Right (Just (SC_Type (ClassUnionStructEnum (UnscopedName Bool
False UnqualifiedName
uqn)))) ->
      forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i forall a b. (a -> b) -> a -> b
$ UnqualifiedName -> PrefixR -> PrefixR
PrefixUQName UnqualifiedName
uqn PrefixR
PrefixEnd
    Right (Just (SC_Prefix (Prefix PrefixR
sp))) -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i PrefixR
sp
    Right Maybe SubsCandidate
o -> forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
"PrefixR" NextArg Substitution'
i Maybe SubsCandidate
o
    Left Substitution
s -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Substitution
s forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Next Substitution PrefixR
direct

substituteTemplatePrefix :: (Next Substitution TemplatePrefix)
                         -> Next Substitution' TemplatePrefix
substituteTemplatePrefix :: Next Substitution TemplatePrefix
-> Next Substitution' TemplatePrefix
substituteTemplatePrefix Next Substitution TemplatePrefix
direct NextArg Substitution'
i =
  case NextArg Substitution' -> Either Substitution (Maybe SubsCandidate)
getSubst NextArg Substitution'
i of
    Right o :: Maybe SubsCandidate
o@(Just (SC_Prefix (Prefix PrefixR
p2))) ->
      let go :: PrefixR -> Maybe TemplatePrefix
go = \case
            PrefixR
PrefixEnd -> forall a. Maybe a
Nothing
            PrefixUQName UnqualifiedName
uqn PrefixR
sp ->
              case PrefixR -> Maybe TemplatePrefix
go PrefixR
sp of
                Maybe TemplatePrefix
Nothing -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NonEmpty UnqualifiedName -> TemplatePrefix
GlobalTemplate forall a b. (a -> b) -> a -> b
$ UnqualifiedName
uqn forall a. a -> [a] -> NonEmpty a
:| []
                Just (GlobalTemplate NonEmpty UnqualifiedName
uqns) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ NonEmpty UnqualifiedName -> TemplatePrefix
GlobalTemplate forall a b. (a -> b) -> a -> b
$ forall a. a -> NonEmpty a -> NonEmpty a
NEL.cons UnqualifiedName
uqn NonEmpty UnqualifiedName
uqns
                Just (NestedTemplate (Prefix PrefixR
p) NonEmpty UnqualifiedName
uqns) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Prefix -> NonEmpty UnqualifiedName -> TemplatePrefix
NestedTemplate (PrefixR -> Prefix
Prefix forall a b. (a -> b) -> a -> b
$ UnqualifiedName -> PrefixR -> PrefixR
PrefixUQName UnqualifiedName
uqn PrefixR
p) NonEmpty UnqualifiedName
uqns
                Maybe TemplatePrefix
_ -> forall a. Maybe a
Nothing -- ??
            PrefixTemplateArgs TemplateArgs
ta PrefixR
sp ->
              case PrefixR -> Maybe TemplatePrefix
go PrefixR
sp of
                Maybe TemplatePrefix
Nothing -> forall a. Maybe a
Nothing
                Just (GlobalTemplate NonEmpty UnqualifiedName
uqns) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Prefix -> NonEmpty UnqualifiedName -> TemplatePrefix
NestedTemplate (PrefixR -> Prefix
Prefix forall a b. (a -> b) -> a -> b
$ TemplateArgs -> PrefixR -> PrefixR
PrefixTemplateArgs TemplateArgs
ta PrefixR
PrefixEnd) NonEmpty UnqualifiedName
uqns
                Just (NestedTemplate (Prefix PrefixR
p) NonEmpty UnqualifiedName
uqns) ->
                  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Prefix -> NonEmpty UnqualifiedName -> TemplatePrefix
NestedTemplate (PrefixR -> Prefix
Prefix forall a b. (a -> b) -> a -> b
$ TemplateArgs -> PrefixR -> PrefixR
PrefixTemplateArgs TemplateArgs
ta PrefixR
p) NonEmpty UnqualifiedName
uqns
                Maybe TemplatePrefix
_ -> forall a. Maybe a
Nothing -- ??
      in case PrefixR -> Maybe TemplatePrefix
go PrefixR
p2 of
           Maybe TemplatePrefix
Nothing -> forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
"Template Prefix (2)" NextArg Substitution'
i Maybe SubsCandidate
o
           Just TemplatePrefix
o' -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i TemplatePrefix
o'
    Right (Just (SC_Prefix (PrefixTemplateParam TemplateArg
p PrefixR
PrefixEnd))) ->
      forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i forall a b. (a -> b) -> a -> b
$ TemplateArg -> TemplatePrefix
TemplateTemplateParam TemplateArg
p
    Right Maybe SubsCandidate
o -> forall a b.
Show a =>
String -> NextArg a -> Maybe SubsCandidate -> Maybe b
invalidSubst String
"Template Prefix" NextArg Substitution'
i Maybe SubsCandidate
o
    Left Substitution
s -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution'
i Substitution
s forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Next Substitution TemplatePrefix
direct


-- | Calls to replace a template substitution ("T[n]_") with the replacement
-- value from the original template argument specification.  Note that these
-- substitutions are independent of the normal substitutions (i.e. "S[n]_").

substituteTemplateParam :: Next (Maybe Int) TemplateParam
substituteTemplateParam :: Next (Maybe Int) TemplateArg
substituteTemplateParam NextArg (Maybe Int)
i =
  let idx :: Int
idx = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 (forall a. Num a => a -> a -> a
+Int
1) forall a b. (a -> b) -> a -> b
$ NextArg (Maybe Int)
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal
  in case forall a. Int -> Seq a -> Maybe a
Seq.lookup Int
idx (NextArg (Maybe Int)
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) (Seq TemplateArg)
nTmplSubs) of
       Just TemplateArg
a -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg (Maybe Int)
i TemplateArg
a
       Maybe TemplateArg
_ ->
#ifdef MIN_VERSION_panic
            -- Debug details
            dumpSubs i "Nothing Template Param" >>
#endif
            forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"substituteTemplateParam"
              [ String
"Invalid Template Param substitution reference: "
              , forall a. Show a => a -> String
show (NextArg (Maybe Int)
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal)
              ]


-- | Called during parsing to add a SubsCandidate for future Substitution lookup.

canSubst :: SubsCandidate -> Next a a
canSubst :: forall a. SubsCandidate -> Next a a
canSubst SubsCandidate
what NextArg a
i = 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) (Seq SubsCandidate)
nSubs forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (forall a. Seq a -> a -> Seq a
|> SubsCandidate
what)

dropLastSubst :: Next a a
dropLastSubst :: forall a. Next a a
dropLastSubst NextArg a
i = 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) (Seq SubsCandidate)
nSubs forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ forall {a}. Seq a -> Seq a
dropLast
  where dropLast :: Seq a -> Seq a
dropLast Seq a
s = case forall a. Seq a -> ViewR a
Seq.viewr Seq a
s of
                       ViewR a
Seq.EmptyR -> Seq a
s
                       Seq a
s' :> a
_ -> Seq a
s'

-- | Called during parsing to add an unscoped template name for future
-- Substitution lookup.
canSubstUnscopedTemplateName :: Next Name Name
canSubstUnscopedTemplateName :: Next Name Name
canSubstUnscopedTemplateName NextArg Name
i =
  case NextArg Name
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal of
    UnscopedName Bool
isStd UnqualifiedName
uqn -> forall a. SubsCandidate -> Next a a
canSubst (Bool -> UnqualifiedName -> SubsCandidate
SC_UQName Bool
isStd UnqualifiedName
uqn) NextArg Name
i
    Name
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NextArg Name
i


-- | Called during parsing to add a NamePrefix SubsCandidate for future
-- Substitution lookup.  This one is a bit different because the Prefix may
-- contain a NonEmpty list of Unqualified names: each init of that list is a
-- substitutable.
canSubstPrefix :: Next Prefix Prefix
canSubstPrefix :: Next Prefix Prefix
canSubstPrefix NextArg Prefix
i = forall a. SubsCandidate -> Next a a
canSubst (Prefix -> SubsCandidate
SC_Prefix forall a b. (a -> b) -> a -> b
$ NextArg Prefix
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal) NextArg Prefix
i

-- | Called during parsing to add an Type_ SubsCandidate for future Substitution
-- lookup.

canSubstType :: Next Type_ Type_
canSubstType :: Next Type_ Type_
canSubstType NextArg Type_
i = forall a. SubsCandidate -> Next a a
canSubst (Type_ -> SubsCandidate
SC_Type forall a b. (a -> b) -> a -> b
$ NextArg Type_
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal) NextArg Type_
i

canSubstTypes :: Next (NEL.NonEmpty Type_) (NEL.NonEmpty Type_)
canSubstTypes :: Next (NonEmpty Type_) (NonEmpty Type_)
canSubstTypes NextArg (NonEmpty Type_)
i =
  let subT :: NextArg a -> Type_ -> Maybe (NextArg a)
subT NextArg a
i' Type_
ty = forall a. SubsCandidate -> Next a a
canSubst (Type_ -> SubsCandidate
SC_Type forall a b. (a -> b) -> a -> b
$ Type_
ty) NextArg a
i'
  in forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM forall {a}. NextArg a -> Type_ -> Maybe (NextArg a)
subT NextArg (NonEmpty Type_)
i (NextArg (NonEmpty Type_)
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal)

canSubstTemplatePrefix :: Next TemplatePrefix TemplatePrefix
canSubstTemplatePrefix :: Next TemplatePrefix TemplatePrefix
canSubstTemplatePrefix NextArg TemplatePrefix
i = forall a. SubsCandidate -> Next a a
canSubst (TemplatePrefix -> SubsCandidate
SC_TemplatePrefix forall a b. (a -> b) -> a -> b
$ NextArg TemplatePrefix
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal) NextArg TemplatePrefix
i

canSubstTemplateParam :: Next TemplateParam TemplateParam
canSubstTemplateParam :: Next TemplateArg TemplateArg
canSubstTemplateParam = Next TemplateArg TemplateArg
canSubstTemplateArg

canSubstTemplateArg :: Next TemplateArg TemplateArg
canSubstTemplateArg :: Next TemplateArg TemplateArg
canSubstTemplateArg NextArg TemplateArg
i =
  if NextArg TemplateArg
i forall s a. s -> Getting a s a -> a
^. forall a. Lens' (NextArg a) Bool
nTmplSubsLock
  then forall (f :: * -> *) a. Applicative f => a -> f a
pure NextArg TemplateArg
i
  else forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ NextArg TemplateArg
i forall a b. a -> (a -> b) -> b
& forall a. Lens' (NextArg a) (Seq TemplateArg)
nTmplSubs forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (forall a. Seq a -> a -> Seq a
|> (NextArg TemplateArg
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal))

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

stdSubstToType :: Next Substitution Type_
stdSubstToType :: Next Substitution Type_
stdSubstToType NextArg Substitution
i =
  case (NextArg Substitution
i forall s a. s -> Getting a s a -> a
^. forall a b. Lens (NextArg a) (NextArg b) a b
nVal) of
    SubStdType StdType
stdTy -> forall (f :: * -> *) a b.
Applicative f =>
NextArg a -> b -> f (NextArg b)
ret NextArg Substitution
i forall a b. (a -> b) -> a -> b
$ StdType -> Type_
StdType StdType
stdTy
    Substitution
s -> forall a b. a -> String -> [String] -> Maybe b
cannot Demangler
Demangler String
"stdSubstToType"
         [ String
"Substitution " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Substitution
s forall a. Semigroup a => a -> a -> a
<> String
" is not a type" ]