packages feed

demangler-1.1.0.0: src/Demangler/Context.hs

{-# LANGUAGE TemplateHaskell #-}
module Demangler.Context
  (
    Context
  , Coord
  , newDemangling
  , contextFindOrAdd
  , contextStr
  , WithContext(..)
  , sayableConstraints
  )
where

import           Data.Sequence ( (|>) )
import qualified Data.Sequence as Seq
import           Data.Text ( Text )
import qualified Language.Haskell.TH as TH

import Text.Sayable


-- | The Context provides a persistent information and collection over a set of
-- demangling calls.  This allows for additional efficiency in memory storage.

-- Note that it can be observed that the stored data here is identifiers, and
-- therefore there are 64 initial characters ('A-Za-z0-9_' + 1 bucket for all
-- others).  This might lead to the use of an Array of Seq or an IntMap of Seq.
-- Both of these were tested in both single and batched mode against
-- approximately 13,000 demanglings: there was no significant different between
-- those more complicated forms and this simple Seq in either time, memory
-- consumption, or garbage collection, so this simplest form is sufficient.

data Context = Context (Seq.Seq Text)

-- | Return an initial Context useable for calls to 'demangle'.

newDemangling :: Context
newDemangling = Context mempty

type Coord = Int


contextFindOrAdd :: Text -> Context -> (Coord, Context)
contextFindOrAdd s c@(Context l) =
  case Seq.elemIndexL s l of
    Just n -> (n, c)
    Nothing -> (Seq.length l, Context $ l |> s)

contextStr :: Context -> Coord -> Text
contextStr (Context l) i = l `Seq.index` i

data WithContext a = WC a Context

sayableConstraints :: TH.Name -> TH.PredQ
sayableConstraints forTy = do
  let rTy = TH.ConT forTy
  wctxt <- [t|WithContext|]
  sayableSubConstraints $ do ofType forTy
                             paramTH rTy
                             subElemFilter (not
                                            . (`elem` [ "Context"
                                                      , "Bool"
                                                      , "Natural"
                                                      , "Float"
                                                      ])
                                             . TH.nameBase)
                             subWrapper wctxt
                             tagVar "saytag"