OCaml Project Directory Structure - ocaml

I would like to give two .ml sources files the same name in different directories in my source tree, but the OCaml documentation states that the a file A.ml is exported as a toplevel module A = struct ... end. If I have two files X/A.ml and Y/A.ml, how can I refer to them both from B.ml?

Modules can contain modules, i.e. you can have a hierarchy of modules.
From the B.ml point of view, you can see two modules named X.A and Y.A .
They can even both have a function named foo, those functions would be seen as X.A.foo and Y.A.foo .
Beware that if you open both modules X and Y, the module A from Y will hide the module A from X.
That was from the namespace point of view. Now, about the source tree.
One way would be to have those files:
x.ml
X/a.ml
y.ml
y/a.ml
The file x.ml is automatically generated and contains just this:
module A = struct
(*The contents of x/a.ml is included here*)
end
Likewise for y.ml
There are several preprocessors able to include a file: cpp, camlp4, camlp5, camlmix...
This set of automatically generated files (and regenerated each time the source changes) is not very satisfiying, I will look at other answers.
You can also have a look at ocamlc -pack, but when I tried it a long time ago there was a problem with ocamldoc unable to have x/a.ml and y/a.ml . So check this before you settle on a tool.

You cannot link modules with the same name into the same program. For example, extensions to the standard library, such as Batteries and Core, are forced to give standard modules a different name. In Batteries, the List module is called BatList. Then, they provide a wrapper module Batteries, within which the module is renamed with by doing module List = BatList. The overall path to this module is Batteries.List, so there is no clash with the Standard Library's top level List. Finally, the recommended way of using Batteries and Core is to do open Batteries and open Core, thereby giving you access to their additional list functions under the module name List.
Thus the only option is to rename your modules, but you can do this in two ways:
Change the base names of the modules, e.g. call them A and B.
Put the modules under another module, e.g. name them X.A and Y.A. If you want to keep your current directory structure, you can use OCaml's -pack option. Personally, I find this option too restrictive and always end up doing manual packing, i.e. the technique described above used by Batteries and Core.

Related

(Ocaml) unbound module error on visual code

I have just started to learn Ocaml.
I'm using visual code as my IDE on Ubuntu,
and I have OCaml extension and merlin installed.
and I have the following problem -
my workspace folder contains only 2 files:
a.ml and b.ml.
In the file a.ml I have defined a module named "COOL", and in the file b.ml I wrote:
~ b.ml ~
open COOL;;
I get an error that says "Unbound module COOL merlin"
Is there any way to make it see the module on file a.ml?
I tried searching for solution, I saw something with makefile and .merlin and B build
but I didn't understand it, I don't have anything but the 2 files I mentioned.
I would be happy if someone can tell me what exactly should be done in order for this little example to work.
tl; dr: do ocamlc -c a.ml (or whatever your compilation command is) in order to generate the a.cmi file that merlin will use to get the list of symbols defined in module A.
Apart the fact that in b.ml your module is indeed named A.COOL (unless you open A before open COOL) as mentioned by glennsl, the point is that merlin is, as far as I know, only watching the current file being edited, i.e. b.ml in your case. In order to have access to external symbols, you thus need to have compiled the other files (or at least their corresponding .mli if they exist), in order to have the relevant .cmi files available to merlin.
This is implicit in the paragraph of the documentation describing build paths, which says "[merlin] needs to know where to find the cmi files of the other modules of your project", i.e. those files need to exist in the first place.

Loading OCaml modules not in the current directory

I'm writing a large OCaml project. I wrote a file foo.ml, which works perfectly. In a subdirectory of foo.ml's directory, there is a file bar.ml.
bar.ml references code in foo.ml, so its opening line is:
open Foo
This gives me an error at compile time:
Unbound module Foo.
What can I do to fix this without changing the location of foo.ml?
The easy path is to use one of OCaml build system like ocamlbuild or oasis. Another option would be jbuilder but jbuilder is quite opiniated about file organization and does not allow for the kind of subdirectory structure that you are asking for.
The more explicit path comes with a warning: OCaml build process is complicated with many moving parts that can be hard to deal with.
After this customary warning, when looking for modules, OCaml compiler first looks for module in the current compilation environment, then looks for compiled interface ".cmi" files in the directories specified by the "-I" option flags (plus the current directory and the standard library directory).
Thus in order to compile your bar.ml file, you will need to add the parent directory in the list of included directories with the -I .. option.
After all this, you will discover that during the linking phase, all object files (i.e. .cmo or .cmx) need to be listed in a topological order compatible with the dependency graph of your project.
Consequently, let me repeat my advice: use a proper build system.

Don't Link all Standard Library Modules when Compiling OCaml

I'm putting together an intro OCaml project for a CS class and part of it involves implementing list operations. I want them to be able to use Pervasives, but not List or any other standard library modules. Is there a way to set up ocamlbuild so it only links against Pervasives in the standard library?
You can use the -nostdlib option of the compilers but that will hide both Pervasives and List.
What you want is difficult to achieve since both compilation units are part of the same library archive namely stdlib.cma.
You could maybe try to compile your own copy of Pervasives and use the above flag.
I see two opportunities: either remove module directly from the OCaml standard library or hide them by overloading with a module with different (possibly empty) signature.
The first variant requires editing OCaml distribution Makefiles. With opam and is not that scary, actually, as you can patch OCaml quite easily and distribute each patched OCaml as a separate compiler. To remove module from the stdlib archive you will need to edit stdlib/Makefile.shared, stdlib/StdlibModules, and stdlib.mllib. After you've removed the unnecessary modules, you can do:
./configure
make world.opt
make install
Another option is to (ab)use the -open command line argument of ocamlc. When this option is specified with a name of a module, this module will be automatically opened in the compiled program. For example, you can write your own overlay over a standard library, that has the following interface (minimal.mli):
module List = sig end (* or whatever you want to expose *)
and then you can compile either with ocamlc -open minimal ..., or, with ocamlbuild: ocamlbuild -cflags -open,minimal ... (you can also use _tags file to pass the open flag, or write an ocamlbuild plugin).

node.js Internals: How can I find out where `process.binding('eval')` gets defined?

How can I find out where in the C++ source code of node.js the JavaScript object gets defined which I can access through process.binding('eval')? - I already found out that it's in /src/node_script.cc in this special case, but: How can I know where I can find that module just when I just take a look on the /src/ directory overview? I don't want to step through all the files in /src/ in order to look for a module.
Where can I find some deep going information about the internals of process.binding()s?
Thanks.
I was looking for the same myself today. I cannot guarantee that there isn't more to it, but this is what I discovered.
src/node_extensions.h contains a list of built-in modules, defined like:
ITEM(node_module_name)
where module_name is the name of the module (obviously)
You can find out which file defines that module by searching for which file has a line that starts with
NODE_MODULE(node_module_name,
So, to find the file that defines the 'evals' module for process.bindings:
$ grep "NODE_MODULE(node_evals" src/*.cc
src/node_script.cc:NODE_MODULE(node_evals, node::InitEvals)

2 ocaml modules with same (file)name

What I want is to have the following source tree layout:
src/
a.ml
b.ml
...
tests/
a.ml
b.ml
...
Is it possible to distinct these modules and access
src/a.ml module as A and tests/a.ml module as something like Tests.A ?
Actually, there also is a problem with ocamlfind (UPD: omake) it thinks that tests/a.ml depends on itself rather than on src/a.ml
Of course, I can just rename the tests as, like, tests/aTest.ml, but I would like to avoid having to do it. And I just don't believe that it's impossible to have any similarly-named files in the whole source tree (regarding distinction purposes -- isn't it what folders and the whole hierarchical file systems thing are for?)
Thank you very much!
-pack option can be used to group the set of compiled objects under the single module name.
Actually, there also is a problem with
ocamlfind: it thinks that tests/a.ml
depends on itself rather than on
src/a.ml
ocamlfind doesn't deal with deps between source files. ocaml compiler itself will not be able to resolve module names in such setup.
And yes, it is better to avoid similarily named files in source tree :)