# Converge compiler tools

Converge programs are compiled to bytecode, and the Converge Virtual Machine (VM) executes this bytecode. Converge uses a traditional compiling and linking scheme similar to many C compilers, where individual source files are converted into object files and linked to produce a Converge executable. Large projects may find it convenient to make use of the individual compiler tools; however most simpler projects work well with Converge's auto-make functionality.

## Using the auto-make facility

If we assume a simple hello world program is contained in `hello.cv`, it can be compiled and run automatically as follows:

    $ converge hello.cv
    Hello world!
    $

In other words, when the VM is passed a source script, it automatically compiles dependencies, links, and executes the file. It also caches the results of the compilation so that subsequent runs are much quicker. It is often instructive to see what steps are being taken prior to the file being run. The `-v` switch to the VM shows the auto-make steps in operation:

    $ converge -v hello.cv
    ===> Compiling /tmp/hello.cv...
    ===> Finished compiling /tmp/hello.cv.
    ===> Linking.
    Hello world!
    $

If no changes are made to the file or its dependencies, then subsequent runs of the VM execute the program directly without re-compiling any unneeded aspects.

    $ converge -v hello.cv
    Hello world!
    $

Converge's auto-make facility ensures that all files in a project are upto date; its chief limitation is that it sometimes has to compile individual files multiple times to ensure that this is the case, even when a user may know that this is not strictly necessary.

As auto-make runs, it attempts to write cached bytecode files to the local disk. These can on occasion be the cause of strange compilation problems (perhaps after moving files from one machine to another, or time shifts on your local machine). In such cases, converge can be instructed via the `-f` switch to ignore all cached bytecode files and perform compilation from scratch, updating all cached bytecode files. This is the equivalent of running `make clean && make` for projects built using `make`. Using the `-f` switch in the running example will always involve output along the lines of the following:

    $ converge -f -v hello.cv
    ===> Compiling /tmp/hello.cv...
    ===> Finished compiling /tmp/hello.cv.
    ===> Linking.
    Hello world!
    $

## Using `convergec` and `convergel` separately

Effectively what auto-make does is to call the following commands:

    $ convergec -o hello.cvb hello.cv
    $ convergel -o hello hello.cvb

`converegec` is the name of the Converge compiler; `convergel` is the name of the Converge linker. Both are written in Converge itself, hence the need to invoke the Converge virtual machine to execute them.

The linked program can then be run as follows:

    $ converge hello
    Hello world!
    $

If the underlying platform supports it, then the Converge executable is marked as executable and can be run directly:

    $ ./hello
    Hello world!
    $

## The Converge compiler `convergec`

`convergec` has two functions, firstly as a traditional compiler, and secondly as the auto-make front end.

### Traditional compilation

`convergec` produces `.cvb` files from `.cv` source files or packages. Each `.cvb` file represents a single module or package. `convergec` accepts the following command-line parameters:

    convergec [-I <directory> | library] -o <output> <input>

The `-I` switch specifies a directory or library (`.cvl` file) to be included in the import path. Multiple `-I` switches can be specified; the includes will be searched in the order they are defined on the command line.

Indicative executions of `convergec` to compile a module and package respectively are as follows:

    $ convergec -o M.cvb M.cv
    $ convergec -o P.cvb P

### Auto-make front end

If the `-m` switch is passed, `convergec` enters auto-make mode. It attempts to compile the input module, and all out of date dependencies, before linking them together and saving an executable into the output file (note that it does not run the resulting executable). `-I` switches may be used as in the traditional mode.

    convergec -m [-I <directory>] -o <output> <input>

## The Converge linker `convergel`

`convergel` has two related functions. It can combine one or more `.cvb` and `.cvl` files into a Converge executable. It can also combine one or more `.cvb` files into a Converge library (`.cvl`) file.

### Creating a Converge executable

`convergel` can combine one or more `.cvb` files into a converge executable. In this case `convergel` can be invoked thus:

    convergel -o <output> <input> [... <input>]

The first input file must be a `.cvb` file; it is known as the main module. When the executable is run, the main module is searched for an function called `main` which is then executed. During linking, the main module's dependencies must be listed in the form of `.cvb` or `.cvl` files on the command line after the main module has been listed. These subsequent files must contain all the files which the main module and its dependencies import.

As a trivial example, imagine we have a file `hello.cv`:

    import Sys
    import World

    func main():
        Sys::println("Hello " + World::world() + "!")

and a second file `world.cv`:

    func world():
        return "world"

then the following sequence would be needed to produce a functioning executable:

    $ converge convergec -o hello.cvb hello.cv
    $ converge convergec -o world.cvb world.cv
    $ converge convergel -o hello hello.cvb world.cvb

If the underlying platform supports it, then the Converge executable is marked as executable and can be run directly.

### Creating a Converge library

`convergel` can bundle a package into a single `.cvl` library. This makes distributing pre-compiled binaries trivial (and marginally speeds up compilation, which no longer needs to continually trek through directories looking for matching files). The `-l` switch tells `convergel` to create a library. In similar fashion to normal linking, the first input file must be the top level package the library represents; all of its sub-modules and sub-packages must then be specified on the command line.

    convergel -l -o <output.cvl> <top_level_pkg.cvb> [... <file.cvb>]