+ var candidate = search_module_in_paths(anode.hot_location, name, lookpaths)
+
+ if candidate == null then
+ if mgroup != null then
+ error(anode, "Error: cannot find module {name} from {mgroup.name}. tried {lookpaths.join(", ")}")
+ else
+ error(anode, "Error: cannot find module {name}. tried {lookpaths.join(", ")}")
+ end
+ return null
+ end
+ return candidate
+ end
+
+ # Get a module by its short name; if required, the module is loaded, parsed and its hierarchies computed.
+ # If `mgroup` is set, then the module search starts from it up to the top level (see `paths`);
+ # if `mgroup` is null then the module is searched in the top level only.
+ # If no module exists or there is a name conflict, then an error on `anode` is displayed and null is returned.
+ fun get_mmodule_by_name(anode: ANode, mgroup: nullable MGroup, name: String): nullable MModule
+ do
+ var path = search_mmodule_by_name(anode, mgroup, name)
+ if path == null then return null # Forward error
+ var res = self.load_module(path.filepath)
+ if res == null then return null # Forward error
+ return res.mmodule.as(not null)
+ end
+
+ # Search a module `name` from path `lookpaths`.
+ # If found, the path of the file is returned
+ private fun search_module_in_paths(location: nullable Location, name: String, lookpaths: Collection[String]): nullable ModulePath
+ do