root/src/Pugs/Types/Hash.hs

Revision 21673, 5.5 kB (checked in by audreyt, 4 months ago)

* Import Pugs 6.2.13.11 from Hackage into our source tree.
* Highlights:

  • Much faster startup time
  • Slightly faster compilation time (mostly due to refactored Pugs.AST.Internals)
  • Portable-to-Win32 readline thanks to Haskeline
  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1type HashIndex = VStr
2
3class (Typeable a) => HashClass a where
4    hash_iType :: a -> Type
5    hash_iType = const $ mkType "Hash"
6    hash_fetch       :: a -> Eval VHash
7    hash_fetch hv = do
8        keys <- hash_fetchKeys hv
9        vals <- mapM (hash_fetchVal hv) keys
10        let ps = keys `zip` vals
11        return (length ps `seq` Map.fromList ps)
12    hash_store       :: a -> VHash -> Eval ()
13    hash_store hv vals = do
14        hash_clear hv
15        forM_ (Map.assocs vals) $ \(key, val) -> do
16            hash_storeVal hv key val
17    hash_fetchElem   :: a -> HashIndex -> Eval (IVar VScalar) -- autovivify
18    hash_fetchElem hv key = do
19        return $ proxyScalar (hash_fetchVal hv key) (hash_storeVal hv key)
20    hash_storeElem   :: a -> HashIndex -> IVar VScalar -> Eval () -- binding
21    hash_storeElem hv idx sv = do
22        val <- readIVar sv
23        hash_storeVal hv idx val
24    hash_fetchVal    :: a -> HashIndex -> Eval Val
25    hash_fetchVal hv key = do
26        rv <- hash_existsElem hv key
27        if rv then readIVar =<< hash_fetchElem hv key
28              else return undef
29    hash_storeVal    :: a -> HashIndex -> Val -> Eval ()
30    hash_storeVal hv key val = do
31        sv <- hash_fetchElem hv key
32        writeIVar sv val
33    hash_fetchKeys   :: a -> Eval [HashIndex]
34    hash_fetchKeys hv = do
35        vals <- hash_fetch hv
36        return $ Map.keys vals
37    hash_fetchSize   :: a -> Eval Int
38    hash_fetchSize hv = do
39        vals <- hash_fetch hv
40        return $ Map.size vals
41    hash_deleteElem  :: a -> HashIndex -> Eval ()
42    hash_existsElem  :: a -> HashIndex -> Eval VBool
43    hash_existsElem hv idx = do
44        keys <- hash_fetchKeys hv
45        return $ idx `elem` keys
46    hash_clear       :: a -> Eval ()
47    hash_clear hv = do
48        keys <- hash_fetchKeys hv
49        mapM_ (hash_deleteElem hv) keys
50    hash_isEmpty     :: a -> Eval VBool
51    hash_isEmpty hv = do
52        keys <- hash_fetchKeys hv
53        return $ null keys
54    hash_clone :: a -> STM a
55    hash_clone = return
56
57instance HashClass (IVar VPair) where
58    hash_iType = const $ mkType "Pair"
59    hash_fetch pv = do
60        (k, v)  <- readIVar pv
61        str     <- fromVal k
62        return $ Map.singleton str v
63    hash_fetchVal pv idx = do
64        (k, v)  <- readIVar pv
65        str     <- fromVal k
66        if str == idx
67            then return v
68            else return undef
69    hash_storeVal _ _ _ = retConstError undef
70    hash_deleteElem _ _ = retConstError undef
71
72instance HashClass VHash where
73    hash_iType = const $ mkType "Hash::Const"
74    hash_fetch = return
75    hash_fetchKeys = return . Map.keys
76    hash_fetchVal hv idx = return $ Map.findWithDefault undef idx hv
77    hash_clear _ = retConstError undef
78    hash_store _ _ = retConstError undef
79    hash_storeVal _ _ _ = retConstError undef
80    hash_storeElem _ _ _ = retConstError undef
81    hash_deleteElem _ _ = retConstError undef
82
83instance HashClass IHashEnv where
84    hash_iType = const $ mkType "Hash::Env"
85    hash_fetch _ = do
86        envs <- io getEnvironment
87        return . Map.map (VStr . decodeUTF8) $ Map.fromList envs
88    hash_fetchVal _ key = tryIO undef $ do
89        str <- getEnv key
90        return $ fromMaybe VUndef (fmap (VStr . decodeUTF8) str)
91    hash_storeVal _ key val = do
92        str <- fromVal val
93        io $ setEnv key (encodeUTF8 str) True
94    hash_existsElem _ key = tryIO False $ do
95        str <- getEnv key
96        return (isJust str)
97    hash_deleteElem _ key = do
98        io $ unsetEnv key
99
100encodeKey, decodeKey :: HashIndex -> HashIndex
101encodeKey x = x
102decodeKey x = x
103
104instance HashClass IHash where
105    hash_iType = const $ mkType "Hash"
106    hash_clone hv = do
107        ps  <- unsafeIOToSTM $ H.toList hv
108        ps' <- forM ps $ \(k, sv) -> do
109            sv' <- cloneIVar sv
110            return (k, sv')
111        unsafeIOToSTM $ H.fromList H.hashString ps'
112    hash_fetch hv = do
113        ps  <- io $ H.toList hv
114        ps' <- forM ps $ \(k, sv) -> do
115            val <- readIVar sv
116            return (decodeKey k, val)
117        return (length ps' `seq` Map.fromList ps')
118    hash_fetchKeys hv = do
119        fmap (map (decodeKey . fst)) (io $ H.toList hv)
120    hash_fetchElem hv idx = do
121        let idx' = encodeKey idx
122        r <- io $ H.lookup hv idx'
123        case r of
124             Just sv -> return sv
125             Nothing -> do
126                sv <- newScalar undef
127                io $ H.insert hv idx' sv
128                return sv
129    hash_storeElem hv idx sv = do
130        io $ H.insert hv (encodeKey idx) sv
131    hash_deleteElem hv idx = do
132        io $ H.delete hv (encodeKey idx)
133        return ()
134    hash_existsElem hv idx = do
135        io $ fmap isJust (H.lookup hv (encodeKey idx))
136
137instance HashClass PerlSV where
138    hash_iType = const $ mkType "Hash::Perl"
139    hash_fetchVal sv key = do
140        keySV   <- fromVal $ castV key
141        perl5EvalApply "sub { $_[0]->{$_[1]} }" [sv, keySV]
142    hash_clear sv = do
143        perl5EvalApply "sub { undef %{$_[0]} }" [sv]
144        return ()
145    hash_storeVal sv key val = do
146        keySV   <- fromVal $ castV key
147        valSV   <- fromVal val
148        perl5EvalApply "sub { $_[0]->{$_[1]} = $_[2] }" [sv, keySV, valSV]
149        return ()
150    hash_fetchKeys sv = do
151        keysSV  <- perl5EvalApply "sub { join $/, keys %{$_[0]} }" [sv]
152        keysStr <- fromVal keysSV
153        return $ lines keysStr
154    hash_deleteElem sv key = do
155        keySV   <- fromVal $ castV key
156        perl5EvalApply "sub { delete $_[0]->{$_[1]} }" [sv, keySV]
157        return ()
158    hash_isEmpty sv = do
159        fromVal =<< perl5EvalApply "sub { !!%{$_[0]} }" [sv]
Note: See TracBrowser for help on using the browser.