~ubuntu-branches/ubuntu/lucid/gtk2hs/lucid

« back to all changes in this revision

Viewing changes to tools/c2hs/base/syms/NameSpaces.hs

  • Committer: Bazaar Package Importer
  • Author(s): Liyang HU
  • Date: 2006-07-22 21:31:58 UTC
  • Revision ID: james.westby@ubuntu.com-20060722213158-he81wo6uam30m9aw
Tags: upstream-0.9.10
ImportĀ upstreamĀ versionĀ 0.9.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
--  Compiler Toolkit: name space management
 
2
--
 
3
--  Author : Manuel M. T. Chakravarty
 
4
--  Created: 12 November 95
 
5
--
 
6
--  Version $Revision: 1.2 $ from $Date: 2004/11/13 17:26:50 $
 
7
--
 
8
--  Copyright (c) [1995..1999] Manuel M. T. Chakravarty
 
9
--
 
10
--  This file is free software; you can redistribute it and/or modify
 
11
--  it under the terms of the GNU General Public License as published by
 
12
--  the Free Software Foundation; either version 2 of the License, or
 
13
--  (at your option) any later version.
 
14
--
 
15
--  This file is distributed in the hope that it will be useful,
 
16
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
--  GNU General Public License for more details.
 
19
--
 
20
--- DESCRIPTION ---------------------------------------------------------------
 
21
--
 
22
--  This module manages name spaces.
 
23
--
 
24
--- DOCU ----------------------------------------------------------------------
 
25
--
 
26
--  language: Haskell 98
 
27
--
 
28
--  * A name space associates identifiers with their definition.
 
29
--
 
30
--  * Each name space is organized in a hierarchical way using the notion of
 
31
--    ranges. A name space, at any moment, always has a global range and may
 
32
--    have several local ranges. Definitions in inner ranges hide definitions
 
33
--    of the same identifiert in outer ranges.
 
34
--
 
35
--- TODO ----------------------------------------------------------------------
 
36
--
 
37
--  * evaluate the performance gain that a hashtable would bring
 
38
--
 
39
 
 
40
module NameSpaces (NameSpace, nameSpace, defGlobal, enterNewRange, leaveRange,
 
41
                   defLocal, find, nameSpaceToList)
 
42
where
 
43
 
 
44
import Common     (Position, Pos(posOf))              -- for importing `Idents'
 
45
import Data.FiniteMap (FiniteMap, emptyFM, addToFM, lookupFM, fmToList, listToFM)
 
46
import Idents     (Ident)
 
47
import Errors     (interr)
 
48
import Binary     (Binary(..))
 
49
 
 
50
 
 
51
-- name space (EXPORTED ABSTRACT)
 
52
--
 
53
-- * the definitions in the global ranges are stored in a finite map, because
 
54
--   they tend to be a lot and are normally not updated after the global range
 
55
--   is constructed
 
56
--
 
57
-- * the definitions of the local ranges are stored in a single list, usually
 
58
--   they are not very many and the definitions entered last are the most
 
59
--   frequently accessed ones; the list structure naturally hides older
 
60
--   definitions, i.e., definitions from outer ranges; adding new definitions
 
61
--   is done in time proportinal to the current size of the range; removing a
 
62
--   range is done in constant time (and the definitions of a range can be
 
63
--   returned as a result of leaving the range); lookup is proportional to the
 
64
--   number of definitions in the local ranges and the logarithm of the number
 
65
--   of definitions in the global range---i.e., efficiency relies on a
 
66
--   relatively low number of local definitions together with frequent lookup
 
67
--   of the most recently defined local identifiers
 
68
--
 
69
data NameSpace a = NameSpace (FiniteMap Ident a)  -- defs in global range
 
70
                             [[(Ident, a)]]       -- stack of local ranges
 
71
 
 
72
-- create a name space (EXPORTED)
 
73
--
 
74
nameSpace :: NameSpace a
 
75
nameSpace  = NameSpace emptyFM []
 
76
 
 
77
-- add global definition (EXPORTED)
 
78
--
 
79
-- * returns the modfied name space 
 
80
--
 
81
-- * if the identfier is already declared, the resulting name space contains
 
82
--   the new binding and the second component of the result contains the
 
83
--   definition declared previosuly (which is henceforth not contained in the
 
84
--   name space anymore)
 
85
--
 
86
defGlobal :: NameSpace a -> Ident -> a -> (NameSpace a, Maybe a)
 
87
defGlobal (NameSpace gs lss) id def  = (NameSpace (addToFM gs id def) lss, 
 
88
                                        lookupFM gs id)
 
89
 
 
90
-- add new range (EXPORTED)
 
91
--
 
92
enterNewRange                    :: NameSpace a -> NameSpace a
 
93
enterNewRange (NameSpace gs lss)  = NameSpace gs ([]:lss)
 
94
 
 
95
-- pop topmost range and return its definitions (EXPORTED)
 
96
--
 
97
leaveRange :: NameSpace a -> (NameSpace a, [(Ident, a)])
 
98
leaveRange (NameSpace gs [])        = interr "NameSpaces.leaveRange: \
 
99
                                             \No local range!"
 
100
leaveRange (NameSpace gs (ls:lss))  = (NameSpace gs lss, ls)
 
101
 
 
102
-- add local definition (EXPORTED)
 
103
--
 
104
-- * returns the modfied name space 
 
105
--
 
106
-- * if there is no local range, the definition is entered globally
 
107
--
 
108
-- * if the identfier is already declared, the resulting name space contains
 
109
--   the new binding and the second component of the result contains the
 
110
--   definition declared previosuly (which is henceforth not contained in the
 
111
--   name space anymore)
 
112
--
 
113
defLocal :: NameSpace a -> Ident -> a -> (NameSpace a, Maybe a)
 
114
defLocal ns@(NameSpace gs []      ) id def = defGlobal ns id def
 
115
defLocal (NameSpace    gs (ls:lss)) id def = 
 
116
  (NameSpace gs (((id, def):ls):lss),
 
117
   lookup ls)
 
118
  where
 
119
    lookup []                          = Nothing
 
120
    lookup ((id', def):ls) | id == id' = Just def
 
121
                           | otherwise = lookup ls
 
122
 
 
123
-- search for a definition (EXPORTED)
 
124
--
 
125
-- * the definition from the innermost range is returned, if any
 
126
--
 
127
find                       :: NameSpace a -> Ident -> Maybe a
 
128
find (NameSpace gs lss) id  = case (lookup lss) of
 
129
                                Nothing  -> lookupFM gs id
 
130
                                Just def -> Just def
 
131
                              where
 
132
                                lookup []       = Nothing
 
133
                                lookup (ls:lss) = case (lookup' ls) of
 
134
                                                    Nothing  -> lookup lss
 
135
                                                    Just def -> Just def
 
136
 
 
137
                                lookup' []              = Nothing
 
138
                                lookup' ((id', def):ls)
 
139
                                        | id' == id     = Just def
 
140
                                        | otherwise     = lookup' ls
 
141
 
 
142
-- dump a name space into a list (EXPORTED)
 
143
--
 
144
-- * local ranges are concatenated
 
145
--
 
146
nameSpaceToList                    :: NameSpace a -> [(Ident, a)]
 
147
nameSpaceToList (NameSpace gs lss)  = fmToList gs ++ concat lss
 
148
 
 
149
 
 
150
{-! for NameSpace derive : GhcBinary !-}
 
151
{-* Generated by DrIFT : Look, but Don't Touch. *-}
 
152
instance (Binary a) => Binary (NameSpace a) where
 
153
    put_ bh (NameSpace aa ab) = do
 
154
            put_ bh aa
 
155
            put_ bh ab
 
156
    get bh = do
 
157
    aa <- get bh
 
158
    ab <- get bh
 
159
    return (NameSpace aa ab)