Merges syntax trees to a single syntax tree. This is the main
code merging "engine". Name specifies the name of the
resulting module. Sources is a list of syntax trees of
type form_list and/or lists of "source code form" syntax
trees, each entry representing a module definition. All the input
modules must be distinctly named.
Unless otherwise specified by the options, all modules are assumed
to be at least "static", and all except the target module are assumed
to be "safe". See the static and safe
options for details.
If Name is also the name of one of the input modules,
the code from that module will occur at the top of the resulting
code, and no extra "header" comments will be added. In other words,
the look of that module will be preserved.
The result is a pair {Tree, Stubs}, where
Tree represents the source code that is the result of
merging all the code in Sources, and Stubs
is a list of stub module descriptors (see below).
Stubs contains one entry for each exported input
module (cf. the export option), each entry describing a
stub module that redirects calls of functions in the original module
to the corresponding (possibly renamed) functions in the new module.
The stub descriptors can be used to automatically generate stub
modules; see create_stubs/2.
Options:
- {export, [atom()]}
Specifies a list of names of input modules whose interfaces
should be exported by the output module. A stub descriptor is
generated for each specified module, unless its name is
Name. If no modules are specified, then if
Name is also the name of an input module, that
module will be exported; otherwise the first listed module in
Sources will be exported. The default value is the
empty list.
- {export_all, boolean()}
If the value is true, this is equivalent to
listing all of the input modules in the export
option. The default value is false.
- {file_attributes, Preserve}
-
If the value is yes, all file attributes
-file(...) in the input sources will be preserved in
the resulting code. If the value is comment, they
will be turned into comments, but remain in their original
positions in the code relative to the other source code forms. If
the value is no, all file attributes will be removed
from the code, unless they have attached comments, in which case
they will be handled as in the comment case. The
default value is no.
- {no_banner, boolean()}
If the value is true, no banner comment will be
added at the top of the resulting module, even if the target
module does not have the same name as any of the input modules.
Instead, Igor will try to preserve the look of the module whose
code is at the top of the output. The default value is
false.
- {no_headers, boolean()}
If the value is true, no header comments will be
added to the resulting module at the beginning of each section of
code that originates from a particular input module. The default
value is false, which means that section headers are
normally added whenever more than two or more modules are
merged.
- {no_imports, boolean()}
If the value is true, all
-import(...) declarations in the original code will
be expanded in the result; otherwise, as much as possible of the
original import declarations will be preserved. The default value
is false.
- {notes, Notes}
-
If the value is yes, comments will be inserted where
important changes have been made in the code. If the value is
always, all changes to the code will be
commented. If the value is no, changes will be made
without comments. The default value is yes.
- {redirect, [{atom(), atom()}]}
Specifies a list of pairs of module names, representing a
mapping from old names to new. The set of old names may not
include any of the names of the input modules. All calls to
the listed old modules will be rewritten to refer to the
corresponding new modules. The redirected calls will not be
further processed, even if the new destination is in one of the
input modules. This option mainly exists to support module
renaming; cf. rename/3. The default value is the
empty list.
- {safe, [atom()]}
Specifies a list of names of input modules such that calls to
these "safe" modules may be turned into direct local calls, that
do not test for code replacement. Typically, this can be done for
e.g. standard library modules. If a module is "safe", it is per
definition also "static" (cf. below). The list may be empty. By
default, all involved modules except the target module
are considered "safe".
- {static, [atom()]}
Specifies a list of names of input modules which will be
assumed never to be replaced (reloaded) unless the target module
is also first replaced. The list may be empty. The target module
itself (which may also be one of the input modules) is always
regarded as "static", regardless of the value of this option. By
default, all involved modules are assumed to be static.
- {tidy, boolean()}
If the value is true, the resulting code will be
processed using the erl_tidy module, which removes
unused functions and does general code cleanup. (See
erl_tidy:module/2 for additional options.) The
default value is true.
- {verbose, boolean()}
If the value is true, progress messages will be
output while the program is running; the default value is
false.
Note: The distinction between "static" and "safe" modules is
necessary in order not to break the semantics of dynamic code
replacement. A "static" source module will not be replaced unless the
target module also is. Now imagine a state machine implemented by
placing the code for each state in a separate module, and suppose
that we want to merge this into a single target module, marking all
source modules as static. At each point in the original code where a
call is made from one of the modules to another (i.e., the state
transitions), code replacement is expected to be detected. Then, if
we in the merged code do not check at these points if the
target module (the result of the merge) has been replaced,
we cannot be sure in general that we will be able to do code
replacement of the merged state machine - it could run forever
without detecting the code change. Therefore, all such calls must
remain remote-calls (detecting code changes), but may call the target
module directly.
If we are sure that this kind of situation cannot ensue, we may
specify the involved modules as "safe", and all calls between them
will become local. Note that if the target module itself is specified
as safe, "remote" calls to itself will be turned into local calls.
This would destroy the code replacement properties of e.g. a typical
server loop.
See also: create_stubs/2, rename/3, erl_tidy:module/2.