Modern development has a variety of needs. Leaf tries to serve many of them by offering multiple ways to get your code running. From the traditional compile and link for distribution, to just-in-time compilation for quick testing.
The key supported aspects are:
- generating static object files for later linking
- generating shared libraries for dynamic loading and static linking
- creating standalone executable files
- executing Leaf code directly with a JIT compiler
A module is compiled as a shared library. These are genuine OS libraries and are loaded by the native runtime linker. This allows Leaf functions to be exported to other languages and called directly.
In addition to the native library a special Leaf exports module is generated. This contains definitions intended for importing into Leaf programs. All necessary details for importing are contained within this file -- there are no source code dependencies required to import libraries.
Leaf executables run as independent applications on the host platform. There is no runtime layer, or VM, between the application and the operating system. A minimal set of Leaf support functions must be available: either they are linked statically in the Leaf program or as a shared library.
Instead of generating an executable the main code of a Leaf program can also be run via LLVM's JIT. This allows for very rapid testing of source code changes. It would also allow for small Leaf programs to exist as source only and not need executables to be built.
Modules are still compiled to shared libraries and loaded dynamically.
Using a JIT saves only a minimal amount of time compared to generating object files. Leaf parsing and IR construction must still be done. The main intent is to provide an easy pipeline for executing Leaf code.