------------------------------------------------------------------------------------------- --- 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 #-}