root/src/Pugs/Prim/Keyed.hs

Revision 15573, 4.6 kB (checked in by audreyt, 19 months ago)

Pugs.Prim.*: Chase retError/Sym changes.

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1{-# OPTIONS_GHC -fglasgow-exts -fno-warn-orphans #-}
2
3module Pugs.Prim.Keyed (
4  -- keyed values (Val)
5  pairsFromVal, keysFromVal, valuesFromVal,
6
7  -- keyed references (VRef)
8  pairsFromRef, keysFromRef, valuesFromRef,
9  existsFromRef, deleteFromRef,
10) where
11import Pugs.Internals
12import Pugs.AST
13import Pugs.Types
14import qualified Data.Map as Map
15import qualified Data.Set as Set
16
17pairsFromVal :: Val -> Eval [Val]
18pairsFromVal VUndef = return []
19pairsFromVal (PerlSV sv) = do
20    keys    <- hash_fetchKeys sv
21    return $ VList (map castV keys)
22    elems   <- mapM (hash_fetchElem sv) keys
23    return $ map (VRef . MkRef . IPair) (keys `zip` elems)
24pairsFromVal (VRef ref) = pairsFromRef ref
25pairsFromVal v = fallback pairsFromVal v
26
27fallback :: (Val -> Eval b) -> Val -> Eval b
28fallback f v@(VV vv) = do
29    val <- vvToVal vv
30    case val of
31        VV{} -> die "Not a keyed object" v
32        _    -> f val
33fallback _ v = die "Not a keyed value" v
34
35keysFromVal :: Val -> Eval Val
36keysFromVal VUndef = return $ VList []
37keysFromVal (PerlSV sv) = do
38    keys    <- hash_fetchKeys sv
39    return $ VList (map castV keys)
40keysFromVal (VList vs) = return . VList $ map VInt [0 .. (genericLength vs) - 1]
41keysFromVal (VRef ref) = do
42    vals <- keysFromRef ref
43    return $ VList vals
44keysFromVal v = fallback keysFromVal v
45
46valuesFromVal :: Val -> Eval Val
47valuesFromVal VUndef = return $ VList []
48valuesFromVal (VJunc j) = return . VList . Set.elems $ juncSet j
49valuesFromVal v@(VList _) = return v
50valuesFromVal (VRef ref) = do
51    vals <- valuesFromRef ref
52    return $ VList vals
53valuesFromVal (PerlSV sv) = do
54    pairs <- hash_fetch sv
55    return . VList $ Map.elems pairs
56valuesFromVal v = fallback valuesFromVal v
57
58-- XXX These bulks of code below screams for refactoring
59
60pairsFromRef :: VRef -> Eval [Val]
61pairsFromRef r@(MkRef (IPair _)) = do
62    return [VRef r]
63pairsFromRef (MkRef (IHash hv)) = do
64    keys    <- hash_fetchKeys hv
65    elems   <- mapM (hash_fetchElem hv) keys
66    return $ map (VRef . MkRef . IPair) (keys `zip` elems)
67pairsFromRef (MkRef (IArray av)) = do
68    vals    <- array_fetch av
69    return $ map castV ((map VInt [0..]) `zip` vals)
70pairsFromRef (MkRef (IScalar sv)) = do
71    refVal  <- scalar_fetch' sv
72    pairsFromVal refVal
73pairsFromRef ref = die "Not a keyed reference" ref
74
75keysFromRef :: VRef -> Eval [Val]
76keysFromRef (MkRef (IPair pv)) = do
77    key     <- pair_fetchKey pv
78    return [key]
79keysFromRef (MkRef (IHash hv)) = do
80    keys    <- hash_fetchKeys hv
81    return $ map castV keys
82keysFromRef (MkRef (IArray av)) = do
83    keys    <- array_fetchKeys av
84    return $ map castV keys
85keysFromRef (MkRef (IScalar sv)) = do
86    refVal  <- scalar_fetch' sv
87    if defined refVal
88        then fromVal =<< keysFromVal refVal
89        else return []
90keysFromRef ref = die "Not a keyed reference" ref
91
92valuesFromRef :: VRef -> Eval [Val]
93valuesFromRef (MkRef (IPair pv)) = do
94    val   <- pair_fetchVal pv
95    return [val]
96valuesFromRef (MkRef (IHash hv)) = do
97    pairs <- hash_fetch hv
98    return $ Map.elems pairs
99valuesFromRef (MkRef (IArray av)) = array_fetch av
100valuesFromRef (MkRef (IScalar sv)) = do
101    refVal  <- scalar_fetch' sv
102    if defined refVal
103        then fromVal =<< valuesFromVal refVal
104        else return []
105valuesFromRef ref = die "Not a keyed reference" ref
106
107existsFromRef :: VRef -> Val -> Eval VBool
108existsFromRef (MkRef (IHash hv)) val = do
109    idx     <- fromVal val
110    hash_existsElem hv idx
111existsFromRef (MkRef (IArray av)) val = do
112    idx     <- fromVal val
113    array_existsElem av idx
114existsFromRef (MkRef (IScalar sv)) val = do
115    refVal  <- scalar_fetch' sv
116    case refVal of
117        VRef ref    -> existsFromRef ref val
118        VList _     -> (`existsFromRef` val) =<< fromVal refVal
119        _           -> return False
120existsFromRef ref _ = die "Not a keyed reference" ref
121
122deleteFromRef :: VRef -> Val -> Eval Val
123deleteFromRef (MkRef (IHash hv)) val = do
124    idxs    <- fromVals val
125    rv      <- forM idxs $ \idx -> do
126        val <- hash_fetchVal hv idx
127        hash_deleteElem hv idx
128        return val
129    return $ VList rv
130deleteFromRef (MkRef (IArray av)) val = do
131    idxs    <- fromVals val
132    rv      <- forM idxs $ \idx -> do
133        val <- array_fetchVal av idx
134        array_deleteElem av idx
135        return val
136    return $ VList rv
137deleteFromRef (MkRef (IScalar sv)) val = do
138    refVal  <- scalar_fetch' sv
139    case refVal of
140        VRef ref    -> deleteFromRef ref val
141        VList _     -> (`deleteFromRef` val) =<< fromVal refVal
142        v           -> die "Argument is not a Hash or Array element or slice in delete" v
143deleteFromRef ref _ = die "Argument is not a Hash or Array element or slice in delete" ref
Note: See TracBrowser for help on using the browser.