module Stylish.Style.Index ( StyleIndex ) where -- TODO do performance tests to decide beside between strict/lazy. import Data.HashMap.Strict import Stylish.Parse import Data.Hashable import Data.Text (unpack) data StyleIndex = StyleIndex { indexed :: HashMap SimpleSelector [StyleRule], unindexed :: [StyleRule] } styleIndex = StyleIndex {indexed = empty, unindexed = []} lookup' :: SimpleSelector -> HashMap SimpleSelector [a] -> [a] lookup' = lookupDefault [] instance StyleSheet StyleIndex where addRule self (StyleRule _ []) = self addRule self rule@(StyleRule selector _) = addRuleForSelector self rule $ simpleSelector selector simpleSelector (Element s) = s simpleSelector (Child _ s) = s simpleSelector (Descendant _ s) = s simpleSelector (Adjacent _ s) = s simpleSelector (Sibling _ s) = s addRuleForSelector self rule [] = self {unindexed = rule : unindexed self} addRuleForSelector self rule selector = self { indexed = insert key (rule : lookup' key index) index } where key = selectorKey selector index = indexed self selectorKey (tok@(Tag _) : _) = tok selectorKey (tok@(Id _) : _) = tok selectorKey (tok@(Class _) : _) = tok selectorKey (Property prop _ : _) = Property prop Exists -- Implement hashable for SimpleSelector here because it proved challenging to automatically derive it. instance Hashable SimpleSelector where hashWithSalt seed (Tag tag) = seed `hashWithSalt` (0::Int) `hashWithSalt` unpack tag hashWithSalt seed (Id id) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack id hashWithSalt seed (Class class_) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack class_ hashWithSalt seed (Property prop test) = seed `hashWithSalt` (3::Int) `hashWithSalt` unpack prop `hashWithSalt` test instance Hashable PropertyTest where hashWithSalt seed Exists = seed `hashWithSalt` (0::Int) hashWithSalt seed (Equals val) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack val hashWithSalt seed (Suffix val) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack val hashWithSalt seed (Prefix val) = seed `hashWithSalt` (3::Int) `hashWithSalt` unpack val hashWithSalt seed (Substring val) = seed `hashWithSalt` (4::Int) `hashWithSalt` unpack val hashWithSalt seed (Include val) = seed `hashWithSalt` (5::Int) `hashWithSalt` unpack val hashWithSalt seed (Dash val) = seed `hashWithSalt` (6::Int) `hashWithSalt` unpack val