uhc-util-0.1.6.6: src/UHC/Util/RLList/LexScope.hs
-------------------------------------------------------------------------------------------
--- Run length encoded list, interpretation/usage as encoding of lexical scope
-------------------------------------------------------------------------------------------
{- |
LexScope represents a lexical scoping, encoded as a list of Int.
-}
module UHC.Util.RLList.LexScope
( -- * Lexical scope
LexScope
, enter
, leave
, isVisibleIn
, common
, parents
, compareByLength
-- * Re-export
, module RLL
)
where
import UHC.Util.RLList as RLL
import Prelude hiding (concat, null, init, length)
import Data.Maybe
-------------------------------------------------------------------------------------------
--- Lexical scope: construction
-------------------------------------------------------------------------------------------
type LexScope = RLList Int
-- | Enter a new scope
enter :: Int -> LexScope -> LexScope
enter x s = s `concat` singleton x
{-# INLINE enter #-}
-- | Leave a scope, if possible
leave :: LexScope -> Maybe LexScope
leave s = fmap fst $ initLast s
{-# INLINE leave #-}
-------------------------------------------------------------------------------------------
--- Lexical scope: observations
-------------------------------------------------------------------------------------------
-- | Is scope visible from other scope?
isVisibleIn :: LexScope -> LexScope -> Bool
isVisibleIn sOuter sInner = sOuter `isPrefixOf` sInner
{-# INLINE isVisibleIn #-}
-- | The common outer scope, which is empty if there is no common scope
common :: LexScope -> LexScope -> LexScope
common s1 s2
= commonPrefix s1 s2
where commonPrefix xxs yys
| isJust ht1 && isJust ht2 && x == y = singleton x `concat` commonPrefix xs ys
| otherwise = empty
where ht1@(~(Just (x,xs))) = headTail xxs
ht2@(~(Just (y,ys))) = headTail yys
-- | All possible parent scopes
parents :: LexScope -> [LexScope]
parents s | not (null s) = inits $ init s
parents _ = []
-- | Compare by length
compareByLength :: LexScope -> LexScope -> Ordering
compareByLength s t = length s `compare` length t
{-# INLINE compareByLength #-}