A proposal by Nicolas Pouillard: > This proposition would introduce two new kind of files, let's call > them .mln and .cmn but as we will see these names are not the best > ones. > > In a .mln file we have a tiny OCaml like language where we can > describe modules (and maybe functors). > > Here is the language for .mln files: > > m ::= module M = struct m end > | module M = filepath > | m* > | include filepath > > As an example, let's follow this session: > > $ cat base_std.mln > (* Std is a bit like a -pack but without the size/granularity issue. *) > module Std = struct > (* For each unit we describe where to find the relevant source files. *) > (* Internally Array and List are not fields of Std but are toplevel > units: Std.Array and Std.List *) > module Array = stdlib/array > module List = stdlib/list > end > > $ cat ext_std.mln > (* Modules described in .mln files follows an merge policy. > So we are not in conflict with the previous Std module > but extending it. *) > module Std = struct > module List = struct > (* Notice that Lazy will not be compiled as a field > of List but as a toplevel unit of name Std.List.Lazy. > Notice as well that the name for the file is not > relevant here. *) > module Lazy = ext/llist > end > end > > $ cat std.mln > include base_std > include ext_std > > $ cat ex.ml > (* No extension to the main language is required. > While improving the expressiveness of `open' could > be useful this is matter for another proposal. *) > open Std > open List.Lazy > (* ... *) > > # Compiling .mln files produces .cmn files. > # We can easily merge .cmn files by concatenating them. > # However we keep them separated here. > $ ocamlc -c *.mln > > # Three .cmn files where built > $ ls *.cmn > base_std.cmn ext_std.cmn std.cmn > > # Compiling the interface and implementation of the Std.Array unit > $ ocamlc -c std.cmn stdlib/array.mli > $ ocamlc -c std.cmn stdlib/array.ml > > # alternatively one can call for the build of a unit by its module name > $ ocamlc -c std.cmn Std.List > > # Building a library for base_std > $ ocamlc stdlib/array.com stdlib/list.cmo -o base_std.cma > > $ ocamlc -c std.cmn ext/llist.mli > $ ocamlc -c std.cmn ext/llist.ml > > # Compiling and linking our example file > $ ocamlc std.cmn base_std.cma ext/llist.cmo ex.ml > > Now let's look at the .cmn files, there contents is close to Alain's > proposal, namely a list of lines, where each line associates a > module path (not just a module name) and a base file path (not just > a base file). > > c ::= (module_path ':' blank* file_path '\n')* > > Examples: > > $ cat base_std.cmn > Std.Array: stdlib/array > Std.List: stdlib/list > > $ cat ext_std.cmn > Std.List.Lazy: ext/llist > > $ cat std.cmn > Std.Array: stdlib/array > Std.List: stdlib/list > Std.List.Lazy: ext/llist > > Notice that any conflicting declarations will be considered as an > error. > > I've ideas on how to extend this to functors and this would fill the > same need as the "big functors" feature from Fabrice. > > The pros of this propositions are the following: > * Tools are kept simple. They will have to read .cmn files but > they are kept flat and simple. > * In particular ocamldep becomes correct if fed with the .cmn files > for complete environment and using a strict mode. > * When using exclusively this mode, there is no need to pass -I > flags to the different tools only .cmn files which are more > robust. The behavior of the compiler then becomes simpler to > describe. The .cmn files are concatenated and form the initial > environment. > * No addition of a concept different from modules (I was arguing the > opposite previously but I think that if we want to open > namespaces then this solution seems satisfying). > > The cons I see are the following: > * A new source language > * This could create confusion w.r.t the compilation of > modules. Inside a compilation unit modules are like records and > outside they are compiled field by field. > * What can we do with `Std' stays an open question. If we want to > keep things light I would only allow opening and projections.