funcons-tools-0.1.0.0: manual/Funcons/Core/Values/Composite/Collections/Maps.hs
{-# LANGUAGE OverloadedStrings #-}
module Funcons.Core.Values.Composite.Collections.Maps where
import Funcons.EDSL
import Funcons.Types
import Funcons.Core.Values.Primitive.BoolBuiltin
import qualified Data.Set as S
import qualified Data.Map as M
library = libFromList [
("map-empty", NullaryFuncon (rewritten (Map M.empty)))
, ("lookup", ValueOp lookup_op)
, ("domain", ValueOp stepDomain)
, ("map-override", ValueOp stepMapOverride)
, ("map-unite", ValueOp unite_maps)
, ("map-delete", ValueOp stepMapDelete)
, ("map-to-list", ValueOp stepMapToList)
, ("is-map-empty", ValueOp stepIsMapEmpty)
, ("list-to-map", ValueOp list_to_map_op)
, ("set-to-map", ValueOp set_to_map_op)
]
is_map_empty = applyFuncon "is-map-empty"
stepIsMapEmpty [Map m] = rewriteTo $ FValue $ tobool (null m)
stepIsMapEmpty vs = sortErr (is_map_empty (fvalues vs)) "is-map-empty not applied to a map"
map_to_list = applyFuncon "map-to-list"
stepMapToList [Map m] = rewriteTo $ FValue $ List $ map toTup $ M.assocs m
where toTup (k,v) = NonEmptyTuple k v []
stepMapToList vs = sortErr (map_to_list (fvalues vs)) "map-to-list not applied to a map"
map_delete = applyFuncon "map-delete"
stepMapDelete [Map m, Set s] = rewriteTo $ FValue $ Map (foldr M.delete m s)
stepMapDelete vs = sortErr (map_delete (fvalues vs))
"map-delete not applied to a map and set of values"
-- |
-- Computes the union over a sequence of maps.
-- If the maps do not have disjoint domains a failure signal is raised.
map_unite_ = FApp "map-unite" . FTuple
unite_maps vs
| not (all isMap vs) = sortErr (map_unite_ (fvalues vs))
"map-unite not applied to a sequence of maps"
| otherwise =
let maps = map toMap vs
domains = map (M.keysSet) maps
in if S.null (foldr S.intersection S.empty domains)
then rewriteTo $ FValue $ Map $ M.unions maps
else partialOp (map_unite_ (fvalues vs))
"map-unite not applied to maps with disjoint domains"
where toMap (Map m) = m
toMap _ = error "unite-maps, toMap"
isMap (Map m) = True
isMap _ = False
lookup_ = applyFuncon "lookup"
lookup_op v@[k, Map m] = case M.lookup k m of
Nothing -> partialOp (lookup_ (fvalues v)) "failed to lookup"
Just v -> rewriteTo $ FValue v
lookup_op vs = sortErr (lookup_ (fvalues vs)) "lookup not given a key and a map"
-- |
-- Computes the left-biased union over two maps.
map_override_ :: [Funcons] -> Funcons
map_override_ = applyFuncon "map-override"
stepMapOverride [x,y] = rewriteTo =<< map_override_op x y
where
map_override_op :: Values -> Values -> Rewrite Funcons
map_override_op (Map m1) (Map m2) = return (FValue $ Map $ M.union m1 m2)
map_override_op v1 v2 = sortErr (applyFuncon "map-override" [FValue v1, FValue v2]) "map-override not applied to maps"
stepMapOverride vs = sortErr (applyFuncon "map-override" (fvalues vs)) "map-override(M1,M2)"
stepDomain m = rewriteTo =<< domain m
where
domain :: [Values] -> Rewrite Funcons
domain [Map m] = return $ FValue $ Set $ S.fromList $ M.keys m
domain vs = sortErr (applyFuncon "domain" (fvalues vs)) "domain not given a map"
set_to_map = applyFuncon "set-to-map"
set_to_map_op :: [Values] -> Rewrite Rewritten
set_to_map_op [Set vs]
| all isPair_ vs = rewriteTo $ FValue $ Map $ M.fromList $ map unPair $ S.toList vs
where isPair_ (NonEmptyTuple _ _ []) = True
isPair_ _ = False
unPair (NonEmptyTuple k v []) = (k,v)
unPair _ = error "set-to-map not applied to a set of key-value pairs"
set_to_map_op vs = sortErr (set_to_map (fvalues vs))
"set-to-map not applied to a set of key-value pairs"
list_to_map = applyFuncon "list-to-map"
list_to_map_op :: [Values] -> Rewrite Rewritten
list_to_map_op [List vs]
| all isPair_ vs = rewriteTo $ FValue $ Map $ M.fromList $ map unPair $ vs
where isPair_ (NonEmptyTuple _ _ []) = True
isPair_ _ = False
unPair (NonEmptyTuple k v []) = (k,v)
unPair _ = error "set-to-map not applied to a set of key-value pairs"
list_to_map_op vs = sortErr (list_to_map (fvalues vs))
"list-to-map not applied a lit of key-value pairs"