--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Define and retrieve data in modules
+# This module help analysis and tool to store piece of data in `MModule` then
+# retrieve them through the importation relation.
+module mmodule_data
+
+import mmodule
+
+# A map-like structure to associate `E` to` MModule`
+# The advantage of this class is the various `lookup_*` method that
+# allow to retrieve values trough the importation relation.
+class MModuleData[E: Object]
+ # The model associated with the data
+ # Used to execute correclty mmodule-related operation
+ var model: Model
+
+ # is a value locally defined in `mmodule`
+ fun has_mmodule(mmodule: MModule): Bool
+ do
+ return defs.has_key(mmodule)
+ end
+
+ # The value locally defined in `mmodule`.
+ # Return null if no value locally defined.
+ fun [](mmodule: MModule): nullable E
+ do
+ return defs.get_or_null(mmodule)
+ end
+
+ # Set the value locally defined in `mmodule`.
+ # Gining `null` just undefine the value
+ fun []=(mmodule: MModule, value: nullable E)
+ do
+ if value == null then
+ defs.keys.remove(mmodule)
+ else
+ defs[mmodule] = value
+ end
+ end
+
+ private var defs = new HashMap[MModule, E]
+
+ # Return all the super modules that defines a value
+ # `min_visibility` is used to filter modules by their visibility in `mmodule`.
+ fun lookup_all_modules(mmodule: MModule, min_visibility: MVisibility): Sequence[MModule]
+ do
+ var res = new Array[MModule]
+ for m in mmodule.in_importation.greaters do
+ if mmodule.visibility_for(m) < min_visibility then continue
+ if self.defs.has_key(m) then res.add(m)
+ end
+ return res
+ end
+
+ # Return all the values defined in `mmodule` and its imported modules.
+ # `min_visibility` is used to filter modules by their visibility in `mmodule`.
+ # This method could be usefull to check possible static conflicts.
+ fun lookup_all_values(mmodule: MModule, min_visibility: MVisibility): Sequence[E]
+ do
+ var mmodules = lookup_all_modules(mmodule, min_visibility)
+ mmodules = model.mmodule_importation_hierarchy.linearize(mmodules)
+ var res = new Array[E]
+ for m in mmodules do res.add defs[m]
+ return res
+ end
+
+ # Return the most specific values defined in `mmodule` and its imported modules.
+ # `min_visibility_` is used to filter modules by their visibility in `mmodule`.
+ # Unlike `lookup_all_values`, redefined values are hidden,
+ # However, in case of conflit, all conflicting definitions are returned
+ fun lookup_values(mmodule: MModule, min_visibility: MVisibility): Sequence[E]
+ do
+ var mmodules = lookup_all_modules(mmodule, min_visibility)
+ mmodules = model.mmodule_importation_hierarchy.select_smallest(mmodules)
+ var res = new Array[E]
+ for m in mmodules do res.add defs[m]
+ return res
+ end
+
+ # Return the most specific values defined in `mmodule` and its imported modules.
+ # Unlike `lookup_values`, only the most specific value, according to importation, is returned.
+ fun lookup_first_value(mmodule: MModule, min_visibility: MVisibility): nullable E
+ do
+ var mmodules = lookup_all_modules(mmodule, min_visibility)
+ if mmodules.is_empty then return null
+ mmodules = model.mmodule_importation_hierarchy.linearize(mmodules)
+ return defs[mmodules.last]
+ end
+end
+
+# A `MModuleData` where multiples values could be set on a single module
+# a-la `MultiHashMap`
+class MModuleMultiData[E]
+ super MModuleData[Array[E]]
+
+ # Instead of `null` return an empty array usable
+ redef fun [](mmodule)
+ do
+ var res = super
+ if res == null then
+ res = new Array[E]
+ defs[mmodule] = res
+ end
+ return res
+ end
+
+ # like `lookup_all_values` but return a big concatenated sequence (instead of a sequence of array)
+ fun lookup_joined_values(mmodule: MModule, min_visibility: MVisibility): Sequence[E]
+ do
+ var mmodules = lookup_all_modules(mmodule, min_visibility)
+ mmodules = model.mmodule_importation_hierarchy.linearize(mmodules)
+ var res = new Array[E]
+ for m in mmodules do res.add_all defs[m]
+ return res
+ end
+end