Everything is an expression.
This sentence carries profound meaning. We will invoke it many times over the course of these articles.
If everything is an expression, then the language shouldn't have any problem with me defining two modules in the same source file.
Likewise, it shouldn't have any problem with me defining a module inside another module.
Of course, in the context of the Erlang VM, these two snippets
are equivalent; there is nothing preventing you from calling the
in_module module from any other module. The
instruction means a module should be created in the Erlang VM,
with no concept of scope attached.
Still we need to handle both. To do this we will add a step between the parser and the code generator that will walk over the abstract syntax tree, from here onward shortened as AST, and transform the AST by executing it where applicable.
What happens when you execute a
A module is created. Since we are compiling, that simply means
the compiler will branch out and create a module.
If everything is an expression, does that mean this will allow me to create modules at runtime using the same syntax? Yes, but let's not get ahead of ourselves yet.
For now we will just iterate over the AST, and will compile
a module for each
mod found. Modules cannot contain
expressions yet, so there's no need to recurse over it at this
point. This should solve the compilation of our first snippet.
compile/1 function becomes:
Running this compiler over the first snippet yields the following result:
Everything looks fine. And we can check that the two modules have been loaded into the VM:
So far so good!
What about the second snippet? It brings up many questions. What
happens once a
mod expression has been executed at
compile time? If it's an expression then it has to have a result,
right? Right. We are still a bit lacking with expressions for now,
though, so let's get back to it after we add more.