@@ 0,0 1,59 @@
+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
@@ 57,7 57,7 @@ library
-- other-extensions:
-- Other library packages from which modules are imported.
- build-depends: base >=4.9 && <4.10, css-syntax, text
+ build-depends: base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable
-- Directories containing source files.
hs-source-dirs: src
@@ 71,4 71,4 @@ test-suite test-stylish
type: exitcode-stdio-1.0
main-is: Test.hs
other-modules: Stylish.Parse
- build-depends: base >=4.9 && <4.10, css-syntax, text, hspec, QuickCheck
+ build-depends: base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable, hspec, QuickCheck