1 %************************************************************************
3 \subsection[MatchEnv]{Matching environments}
5 %************************************************************************
8 #include "HsVersions.h"
11 MatchEnv, nullMEnv, mkMEnv,
12 lookupMEnv, insertMEnv,
16 CHK_Ubiq() -- debugging consistency check
18 import Maybes ( MaybeErr(..), returnMaB, thenMaB, failMaB )
21 ``Matching'' environments allow you to bind a template to a value;
22 when you look up in it, you supply a value which is matched against
26 data MatchEnv key value
27 = EmptyME -- Common, so special-cased
31 For now we just use association lists. The list is maintained sorted
32 in order of {\em decreasing specificness} of @key@, so that the first
33 match will be the most specific.
36 nullMEnv :: MatchEnv a b
39 mkMEnv :: [(key, value)] -> MatchEnv key value
40 mkMEnv stuff = ME stuff
42 mEnvToList :: MatchEnv key value -> [(key, value)]
43 mEnvToList EmptyME = []
44 mEnvToList (ME stuff) = stuff
47 @lookupMEnv@ looks up in a @MatchEnv@. It simply takes the first
48 match, which should be the most specific.
51 lookupMEnv :: (key1 {- template -} -> -- Matching function
52 key2 {- instance -} ->
54 -> MatchEnv key1 value -- The envt
56 -> Maybe (value, -- Value
57 match_info) -- Match info returned by matching fn
60 lookupMEnv key_match EmptyME key = Nothing
61 lookupMEnv key_match (ME alist) key
65 find ((tpl, val) : rest)
66 = case (key_match tpl key) of
68 Just match_info -> Just (val,match_info)
71 @insertMEnv@ extends a match environment, checking for overlaps.
74 insertMEnv :: (key {- template -} -> -- Matching function
77 -> MatchEnv key value -- Envt
78 -> key -> value -- New item
79 -> MaybeErr (MatchEnv key value) -- Success...
80 (key, value) -- Failure: Offending overlap
82 insertMEnv match_fn EmptyME key value = returnMaB (ME [(key, value)])
83 insertMEnv match_fn (ME alist) key value
86 -- insertMEnv has to put the new item in BEFORE any keys which are
87 -- LESS SPECIFIC than the new key, and AFTER any keys which are
88 -- MORE SPECIFIC The list is maintained in specific-ness order, so
89 -- we just stick it in either last, or just before the first key
90 -- of which the new key is an instance. We check for overlap at
93 insert [] = returnMaB (ME [(key, value)])
95 = case (match_fn t key) of
97 -- New key is not an instance of this existing one, so
98 -- continue down the list.
99 insert rest `thenMaB` \ (ME rest') ->
100 returnMaB (ME((t,v):rest'))
103 -- New key *is* an instance of the old one, so check the
104 -- other way round in case of identity.
106 case (match_fn key t) of
107 Just _ -> failMaB (t,v)
110 Nothing -> returnMaB (ME ((key,value):(t,v):rest))
111 -- All ok; insert here