sep_comp: improve deadness management in compile_class_to_c
[nit.git] / src / loader.nit
index 312d02b..5d20c9c 100644 (file)
@@ -50,7 +50,9 @@ redef class ModelBuilder
                end
 
                var nit_dir = toolcontext.nit_dir
-               var libname = "{nit_dir}/lib"
+               var libname = nit_dir/"lib"
+               if libname.file_exists then paths.add(libname)
+               libname = nit_dir/"contrib"
                if libname.file_exists then paths.add(libname)
        end
 
@@ -222,6 +224,14 @@ redef class ModelBuilder
                                return res
                        end
 
+                       # Fourth, try if the requested module is itself a group with a src
+                       try_file = dirname + "/" + name + "/src/" + name + ".nit"
+                       if try_file.file_exists then
+                               var res = self.identify_file(try_file.simplify_path)
+                               assert res != null
+                               return res
+                       end
+
                        c = c.parent
                end
 
@@ -245,9 +255,9 @@ redef class ModelBuilder
 
                if candidate == null then
                        if mgroup != null then
-                               error(anode, "Error: cannot find module {name} from {mgroup.name}. tried {lookpaths.join(", ")}")
+                               error(anode, "Error: cannot find module `{name}` from `{mgroup.name}`. Tried: {lookpaths.join(", ")}.")
                        else
-                               error(anode, "Error: cannot find module {name}. tried {lookpaths.join(", ")}")
+                               error(anode, "Error: cannot find module `{name}`. Tried: {lookpaths.join(", ")}.")
                        end
                        return null
                end
@@ -284,7 +294,7 @@ redef class ModelBuilder
                                        var abs_candidate = module_absolute_path(candidate)
                                        var abs_try_file = module_absolute_path(try_file)
                                        if abs_candidate != abs_try_file then
-                                               toolcontext.error(location, "Error: conflicting module file for {name}: {candidate} {try_file}")
+                                               toolcontext.error(location, "Error: conflicting module file for `{name}`: `{candidate}` `{try_file}`")
                                        end
                                end
                        end
@@ -297,7 +307,20 @@ redef class ModelBuilder
                                        var abs_candidate = module_absolute_path(candidate)
                                        var abs_try_file = module_absolute_path(try_file)
                                        if abs_candidate != abs_try_file then
-                                               toolcontext.error(location, "Error: conflicting module file for {name}: {candidate} {try_file}")
+                                               toolcontext.error(location, "Error: conflicting module file for `{name}`: `{candidate}` `{try_file}`")
+                                       end
+                               end
+                       end
+                       try_file = (dirname + "/" + name + "/src/" + name + ".nit").simplify_path
+                       if try_file.file_exists then
+                               if candidate == null then
+                                       candidate = try_file
+                               else if candidate != try_file then
+                                       # try to disambiguate conflicting modules
+                                       var abs_candidate = module_absolute_path(candidate)
+                                       var abs_try_file = module_absolute_path(try_file)
+                                       if abs_candidate != abs_try_file then
+                                               toolcontext.error(location, "Error: conflicting module file for `{name}`: `{candidate}` `{try_file}`")
                                        end
                                end
                        end
@@ -456,11 +479,21 @@ redef class ModelBuilder
        # Load a markdown file as a documentation object
        fun load_markdown(filepath: String): MDoc
        do
-               var mdoc = new MDoc(new Location(new SourceFile.from_string(filepath, ""),0,0,0,0))
                var s = new FileReader.open(filepath)
+               var lines = new Array[String]
+               var line_starts = new Array[Int]
+               var len = 1
                while not s.eof do
-                       mdoc.content.add(s.read_line)
-               end
+                       var line = s.read_line
+                       lines.add(line)
+                       line_starts.add(len)
+                       len += line.length + 1
+               end
+               s.close
+               var source = new SourceFile.from_string(filepath, lines.join("\n"))
+               source.line_starts.add_all line_starts
+               var mdoc = new MDoc(new Location(source, 1, lines.length, 0, 0))
+               mdoc.content.add_all(lines)
                return mdoc
        end
 
@@ -485,11 +518,11 @@ redef class ModelBuilder
        fun load_module_ast(filename: String): nullable AModule
        do
                if filename.file_extension != "nit" then
-                       self.toolcontext.error(null, "Error: file {filename} is not a valid nit module.")
+                       self.toolcontext.error(null, "Error: file `{filename}` is not a valid nit module.")
                        return null
                end
                if not filename.file_exists then
-                       self.toolcontext.error(null, "Error: file {filename} not found.")
+                       self.toolcontext.error(null, "Error: file `{filename}` not found.")
                        return null
                end
 
@@ -607,7 +640,7 @@ redef class ModelBuilder
                if decl != null then
                        var decl_name = decl.n_name.n_id.text
                        if decl_name != mod_name then
-                               error(decl.n_name, "Error: module name missmatch; declared {decl_name} file named {mod_name}")
+                               error(decl.n_name, "Error: module name mismatch; declared {decl_name} file named {mod_name}.")
                        end
                end
 
@@ -618,7 +651,7 @@ redef class ModelBuilder
                                if other.mgroup!= null and other.mgroup.mproject == mgroup.mproject then
                                        var node: ANode
                                        if decl == null then node = nmodule else node = decl.n_name
-                                       error(node, "Error: A module named `{other.full_name}` already exists at {other.location}")
+                                       error(node, "Error: a module named `{other.full_name}` already exists at {other.location}.")
                                        break
                                end
                        end
@@ -672,24 +705,33 @@ redef class ModelBuilder
                        if aimport.n_name.n_quad != null then mgroup = null # Start from top level
                        for grp in aimport.n_name.n_path do
                                var path = search_mmodule_by_name(grp, mgroup, grp.text)
-                               if path == null then return # Skip error
+                               if path == null then
+                                       nmodule.mmodule = null # invalidate the module
+                                       return # Skip error
+                               end
                                mgroup = path.mgroup
                        end
                        var mod_name = aimport.n_name.n_id.text
                        var sup = self.get_mmodule_by_name(aimport.n_name, mgroup, mod_name)
-                       if sup == null then continue # Skip error
+                       if sup == null then
+                               nmodule.mmodule = null # invalidate the module
+                               continue # Skip error
+                       end
                        aimport.mmodule = sup
                        imported_modules.add(sup)
                        var mvisibility = aimport.n_visibility.mvisibility
                        if mvisibility == protected_visibility then
                                error(aimport.n_visibility, "Error: only properties can be protected.")
+                               nmodule.mmodule = null # invalidate the module
                                return
                        end
                        if sup == mmodule then
-                               error(aimport.n_name, "Error: Dependency loop in module {mmodule}.")
+                               error(aimport.n_name, "Error: dependency loop in module {mmodule}.")
+                               nmodule.mmodule = null # invalidate the module
                        end
                        if sup.in_importation < mmodule then
-                               error(aimport.n_name, "Error: Dependency loop between modules {mmodule} and {sup}.")
+                               error(aimport.n_name, "Error: dependency loop between modules {mmodule} and {sup}.")
+                               nmodule.mmodule = null # invalidate the module
                                return
                        end
                        mmodule.set_visibility_for(sup, mvisibility)
@@ -697,7 +739,9 @@ redef class ModelBuilder
                if stdimport then
                        var mod_name = "standard"
                        var sup = self.get_mmodule_by_name(nmodule, null, mod_name)
-                       if sup != null then # Skip error
+                       if sup == null then
+                               nmodule.mmodule = null # invalidate the module
+                       else # Skip error
                                imported_modules.add(sup)
                                mmodule.set_visibility_for(sup, public_visibility)
                        end