1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
22 # Simple way to store an HashMap[K, Array[V]]
23 # FIXME: this should move to its own module
24 class MultiHashMap[K
: Object, V
]
25 super HashMap[K
, Array[V
]]
27 # Add `v' to the array associated with `k'.
28 # If there is no array associated, then create it.
29 fun add_one
(k
: K
, v
: V
)
31 if self.has_key
(k
) then
41 # Simple way to store an HashMap[K1, HashMap[K2, V]]
42 # FIXME: this should move to its own module
43 class HashMap2[K1: Object, K2: Object, V
]
44 private var level1
: HashMap[K1, HashMap[K2, V
]] = new HashMap[K1, HashMap[K2, V
]]
45 fun [](k1
: K1, k2
: K2): nullable V
47 var level1
= self.level1
48 if not level1
.has_key
(k1
) then return null
49 var level2
= level1
[k1
]
50 if not level2
.has_key
(k2
) then return null
53 fun []=(k1
: K1, k2
: K2, v
: V
)
55 var level1
= self.level1
56 var level2
: HashMap[K2, V
]
57 if not level1
.has_key
(k1
) then
58 level2
= new HashMap[K2, V
]
67 # Simple way to store an HashMap[K1, HashMap[K2, HashMap[K3, V]]]
68 # FIXME: this should move to its own module
69 class HashMap3[K1: Object, K2: Object, K3: Object, V
]
70 private var level1
: HashMap[K1, HashMap2[K2, K3, V
]] = new HashMap[K1, HashMap2[K2, K3, V
]]
71 fun [](k1
: K1, k2
: K2, k3
: K3): nullable V
73 var level1
= self.level1
74 if not level1
.has_key
(k1
) then return null
75 var level2
= level1
[k1
]
78 fun []=(k1
: K1, k2
: K2, k3
: K3, v
: V
)
80 var level1
= self.level1
81 var level2
: HashMap2[K2, K3, V
]
82 if not level1
.has_key
(k1
) then
83 level2
= new HashMap2[K2, K3, V
]
92 # The container class of a Nit object-oriented model.
93 # A model knows modules, classes and properties and can retrieve them.
96 var mmodules
: Array[MModule] = new Array[MModule]
98 # Module nesting hierarchy.
99 # where mainmodule < mainmodule::nestedmodule
100 var mmodule_nesting_hierarchy
: POSet[MModule] = new POSet[MModule]
102 # Full module importation hierarchy including private or nested links.
103 var mmodule_importation_hierarchy
: POSet[MModule] = new POSet[MModule]
105 # Collections of modules grouped by their short names
106 private var mmodules_by_name
: MultiHashMap[String, MModule] = new MultiHashMap[String, MModule]
108 # Return all module named `name'
109 # If such a module does not exist, null is returned (instead of an empty array)
111 # Visibility or modules are not considered
112 fun get_mmodules_by_name
(name
: String): nullable Array[MModule]
114 if mmodules_by_name
.has_key
(name
) then
115 return mmodules_by_name
[name
]
122 # A Nit module is usually associated with a Nit source file.
123 # Modules can be nested (see `direct_owner', `public_owner', and `in_nesting')
125 # The model considered
128 # The direct nesting module, return null if self is not nested (ie. is a top-level module)
129 var direct_owner
: nullable MModule
131 # The short name of the module
134 # The origin of the definition
135 var location
: Location
138 redef fun to_s
do return self.name
140 # The view of the module in the module_nesting_hierarchy
141 var in_nesting
: POSetElement[MModule]
143 # The view of the module in the module_importation_hierarchy
144 var in_importation
: POSetElement[MModule]
146 # The canonical name of the module
147 # Example: "owner::name"
148 fun full_name
: String
150 var owner
= self.public_owner
151 if owner
== null then
154 return "{owner.full_name}::{self.name}"
158 # Create a new empty module and register it to a model
159 # `direct_owner' is the direct owner (null if top-level module)
160 init(model
: Model, direct_owner
: nullable MModule, name
: String, location
: Location)
164 self.location
= location
165 model
.mmodules_by_name
.add_one
(name
, self)
166 model
.mmodules
.add
(self)
167 self.in_nesting
= model
.mmodule_nesting_hierarchy
.add_node
(self)
168 self.direct_owner
= direct_owner
169 if direct_owner
!= null then
170 model
.mmodule_nesting_hierarchy
.add_edge
(direct_owner
, self)
172 self.in_importation
= model
.mmodule_importation_hierarchy
.add_node
(self)
175 # Register the imported modules (ie "import some_module")
176 # This function can only invoked once by mmodule.
177 # The visibility must be set with `se_visibility_for'.
178 fun set_imported_mmodules
(imported_mmodules
: Array[MModule])
180 assert unique_invocation
: self.in_importation
.direct_greaters
.is_empty
181 for m
in imported_mmodules
do
182 self.model
.mmodule_importation_hierarchy
.add_edge
(self, m
)
186 private var intrude_mmodules
: HashSet[MModule] = new HashSet[MModule]
187 private var public_mmodules
: HashSet[MModule] = new HashSet[MModule]
188 private var private_mmodules
: HashSet[MModule] = new HashSet[MModule]
190 # Return the visibility level of an imported module `m`
191 fun visibility_for
(m
: MModule): MVisibility
193 if m
== self then return intrude_visibility
194 if self.intrude_mmodules
.has
(m
) then return intrude_visibility
195 if self.public_mmodules
.has
(m
) then return public_visibility
196 if self.private_mmodules
.has
(m
) then return private_visibility
197 return none_visibility
200 # Set the visibility of an imported module
201 # REQUIRE: the visibility of the modules imported by `m' are already set for `m'
202 fun set_visibility_for
(m
: MModule, v
: MVisibility)
204 if v
== intrude_visibility
then
205 self.intrude_mmodules
.add
(m
)
206 self.intrude_mmodules
.add_all
(m
.intrude_mmodules
)
207 self.public_mmodules
.add_all
(m
.public_mmodules
)
208 self.private_mmodules
.add_all
(m
.private_mmodules
)
209 else if v
== public_visibility
then
210 self.public_mmodules
.add
(m
)
211 self.public_mmodules
.add_all
(m
.intrude_mmodules
)
212 self.public_mmodules
.add_all
(m
.public_mmodules
)
213 else if v
== private_visibility
then
214 self.private_mmodules
.add
(m
)
215 self.private_mmodules
.add_all
(m
.intrude_mmodules
)
216 self.private_mmodules
.add_all
(m
.public_mmodules
)
218 print
"{self} visibility for {m} = {v}"
219 abort # invalid visibility
223 # The first module in the nesting hierarchy to export self as public
224 # This function is used to determine the canonical name of modules, classes and properties.
225 # REQUIRE: the visibility of all nesting modules is already set for `m'.
226 fun public_owner
: nullable MModule
228 var res
= self.direct_owner
230 while last
!= null do
231 if last
.visibility_for
(self) >= public_visibility
then res
= last
232 last
= last
.direct_owner
237 # Return true if a class or a property introduced in `intro_mmodule' with a visibility of 'visibility' is visible in self.
238 fun is_visible
(intro_mmodule
: MModule, visibility
: MVisibility): Bool
240 var v
= visibility_for
(intro_mmodule
)
241 if v
== intrude_visibility
then
242 return visibility
>= private_visibility
243 else if v
== public_visibility
then
244 return visibility
> private_visibility
245 else if v
== private_visibility
then
246 return visibility
> private_visibility
247 else if v
== none_visibility
then
255 # A visibility (for modules, class and properties)
256 # Valid visibility are:
258 # * intrude_visibility
259 # * public_visibility
260 # * protected_visibility
263 # Note this class is basically an enum.
264 # FIXME: use a real enum once user-defined enums are available
267 redef type OTHER: MVisibility
269 redef var to_s
: String
271 private var level
: Int
273 private init(s
: String, level
: Int)
279 # Is self give less visibility than other
280 # none < private < protected < public < intrude
283 return self.level
< other
.level
287 fun intrude_visibility
: MVisibility do return once
new MVisibility("intrude", 4)
288 fun public_visibility
: MVisibility do return once
new MVisibility("public", 4)
289 fun protected_visibility
: MVisibility do return once
new MVisibility("protected", 3)
290 fun private_visibility
: MVisibility do return once
new MVisibility("private", 2)
291 fun none_visibility
: MVisibility do return once
new MVisibility("none", 2)