packages feed

hiccup-0.40: TclLib/ArrayProcs.hs

module TclLib.ArrayProcs (arrayProcs) where
import Common

import Util
import qualified TclObj as T
import TclObj ((.==))
import Control.Monad
import qualified Data.Map as Map
import VarName 
import Text.Printf

arrayProcs = makeCmdMap [("array", procArray), ("parray", procParray)]

procParray args = case args of
     [name] -> do let n = T.asBStr name 
                  arr <- getArray n `orElse` (tclErr ((show n) ++ " isn't an array"))
                  mapM_ (showFun n) (Map.toList arr)
                  ret
     _      -> argErr "parray"
 where showFun n (a,b) = io (printf "%s(%s) = %s\n" (unpack n) (unpack a) (T.asStr b))


procArray = makeEnsemble "array" [
              ("get", array_get), ("size", array_size), 
              ("exists", array_exists), ("set", array_set), 
              ("names", array_names), ("unset", array_unset)
    ]

arrSet n i v = varSetHere (arrName n i) v

toPairs (a:b:xs) = (a,b) : toPairs xs
toPairs _ = [] 

getOrEmpty name = getArray (T.asBStr name) `ifFails` Map.empty

array_get args = case args of
         [name] -> runGet name (const True)
         [name,pat] ->  runGet name (globMatch (T.asBStr pat))
         _      -> argErr "array get"
 where runGet name filt = do
        arr <- getOrEmpty name
        return . T.mkTclList $ concatMap (\(k,v) -> [T.mkTclBStr k, v]) (filter (filt . fst) (Map.toList arr))
 

array_names args = case args of
         [name] -> getKeys name >>= retlist
         [name,pat] -> getKeys name >>= retlist . globMatches (T.asBStr pat)
         [name,mode,pat] -> do 
                      keys <- getKeys name
                      let bpat = T.asBStr pat
                      if mode .== "-glob" 
                         then retlist (globMatches bpat keys)
                         else if mode .== "-exact" 
                                then retlist (exactMatches bpat keys)
                                else tclErr $ "bad option " ++ show mode
                      
         _      -> argErr "array names"
 where getKeys n = getOrEmpty n >>= return . Map.keys
       retlist = return . T.mkTclList . map T.mkTclBStr

array_set args = case args of
          [a2,a3] -> do l <- T.asList a3
                        if even (length l)
                           then mapM_ (\(a,b) -> arrSet (T.asBStr a2) (T.asBStr a) b) (toPairs l) >> ret
                           else tclErr "list must have even number of elements"
          _       -> argErr "array set"

array_unset args = case args of
     [name]     -> varUnset (T.asBStr name)
     [name,pat] -> do let n = T.asBStr name 
                      arr <- getArray n
                      let (NSQual nst (VarName vn x)) = parseVarName n
                      when (x /= Nothing) $ tclErr "what the heck just happened"
                      let withInd i = (NSQual nst (VarName vn (Just i)))
                      mapM_ (\ind -> varUnsetNS (withInd ind)) (globMatches (T.asBStr pat) (Map.keys arr))
                      ret
     _          -> argErr "array unset"

array_exists args = case args of
       [a2] -> do b <- (getArray (T.asBStr a2) >> return True) `ifFails` False
                  return (T.fromBool b)
       _    -> argErr "array exists"

array_size args = case args of
       [name] -> do arr <- getOrEmpty name
                    return $ T.mkTclInt (Map.size arr)
       _    -> argErr "array exists"