faster scope resolution

This commit is contained in:
Zachary Snow 2020-07-15 18:44:36 -06:00
parent 5667bdb589
commit efe8de3933
1 changed files with 36 additions and 32 deletions

View File

@ -43,8 +43,7 @@ module Convert.Scoper
import Control.Monad.State import Control.Monad.State
import Data.Functor.Identity (runIdentity) import Data.Functor.Identity (runIdentity)
import Data.List (inits) import Data.Maybe (isNothing)
import Data.Maybe (catMaybes)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Convert.Traverse import Convert.Traverse
@ -130,10 +129,6 @@ exitProcedure = do
then error "exitProcedure invariant failed" then error "exitProcedure invariant failed"
else put $ s { sProcedure = False } else put $ s { sProcedure = False }
tierToAccess :: Tier -> Access
tierToAccess (Tier x "") = Access x Nil
tierToAccess (Tier x y) = Access x (Ident y)
exprToAccesses :: Expr -> Maybe [Access] exprToAccesses :: Expr -> Maybe [Access]
exprToAccesses (Ident x) = Just [Access x Nil] exprToAccesses (Ident x) = Just [Access x Nil]
exprToAccesses (Bit (Ident x) y) = Just [Access x y] exprToAccesses (Bit (Ident x) y) = Just [Access x y]
@ -166,21 +161,38 @@ injectItem item =
type Replacements = Map.Map Identifier Expr type Replacements = Map.Map Identifier Expr
attemptResolve :: Mapping a -> [Access] -> Maybe (Replacements, a) -- lookup accesses by direct match (no search)
attemptResolve _ [] = Nothing directResolve :: Mapping a -> [Access] -> Maybe (Replacements, a)
attemptResolve mapping (Access x e : rest) = do directResolve _ [] = Nothing
Entry maybeElement index subMapping <- Map.lookup x mapping directResolve mapping [Access x Nil] = do
if null rest && e == Nil then Entry maybeElement _ _ <- Map.lookup x mapping
fmap (Map.empty, ) maybeElement fmap (Map.empty, ) maybeElement
else do directResolve _ [_] = Nothing
(replacements, element) <- attemptResolve subMapping rest directResolve mapping (Access x Nil : rest) = do
if e /= Nil && not (null index) then do Entry _ "" subMapping <- Map.lookup x mapping
let replacements' = Map.insert index e replacements directResolve subMapping rest
Just (replacements', element) directResolve mapping (Access x e : rest) = do
else if e == Nil && null index then Entry _ (index @ (_ : _)) subMapping <- Map.lookup x mapping
Just (replacements, element) (replacements, element) <- directResolve subMapping rest
else let replacements' = Map.insert index e replacements
Nothing Just (replacements', element)
-- lookup accesses given a current scope prefix
resolveInScope :: Mapping a -> [Tier] -> [Access] -> LookupResult a
resolveInScope mapping [] accesses = do
(replacements, element) <- directResolve mapping accesses
Just (accesses, replacements, element)
resolveInScope mapping (Tier x y : rest) accesses = do
Entry _ _ subMapping <- Map.lookup x mapping
let deep = resolveInScope subMapping rest accesses
let side = resolveInScope subMapping [] accesses
let chosen = if isNothing deep then side else deep
(accesses', replacements, element) <- chosen
if null y
then Just (Access x Nil : accesses', replacements, element)
else do
let replacements' = Map.insert y (Ident y) replacements
Just (Access x (Ident y) : accesses', replacements', element)
type LookupResult a = Maybe ([Access], Replacements, a) type LookupResult a = Maybe ([Access], Replacements, a)
@ -200,17 +212,9 @@ instance ScopeKey Identifier where
lookupAccesses :: Scopes a -> [Access] -> LookupResult a lookupAccesses :: Scopes a -> [Access] -> LookupResult a
lookupAccesses scopes accesses = do lookupAccesses scopes accesses = do
if null results let deep = resolveInScope (sMapping scopes) (sCurrent scopes) accesses
then Nothing let side = resolveInScope (sMapping scopes) [] accesses
else Just $ last results if isNothing deep then side else deep
where
options = inits $ map tierToAccess (sCurrent scopes)
try option =
fmap toResult $ attemptResolve (sMapping scopes) full
where
full = option ++ accesses
toResult (a, b) = (full, a, b)
results = catMaybes $ map try options
withinProcedureM :: Monad m => ScoperT a m Bool withinProcedureM :: Monad m => ScoperT a m Bool
withinProcedureM = gets sProcedure withinProcedureM = gets sProcedure