Compiler
Implementation status and execution modes
What the reference promises, what unreleased means on a page, and the four ways to run a Leviathan program.
since 0.1.0-alpha.1linux
Description
This reference describes Leviathan as the compiler implements it today. Every statement on a page is checked against the compiler: if a page and the compiler ever disagree, the compiler is right and the page is a defect. Features that are designed but not built yet are not described as if they worked; where a page has to mention one, it says so in a sentence that starts with "Not implemented" in the page's Notes section.
The compiler is the program leviathan, and Leviathan source files use the .lev extension. The
package manager and build driver is a separate program, trident (see trident.overview).
The compiler at this point reports its version as 0.1; the first release is planned as
0.1.0-alpha.1.
The four ways to run a program
The compiler turns a source file into a running program in one of four modes. All four accept the same language, and a valid program does the same thing in each of them.
| Flag | What it does |
|---|---|
--run |
Checks the program, then executes it directly with the tree-walking evaluator. No compiler toolchain is needed and nothing is written to disk. |
--ir |
Checks the program, lowers it to bytecode, and executes the bytecode. |
--build <out> |
Checks the program, translates it to C++, and builds an executable named <out> with the system C++ compiler. |
--build-native <out> |
Checks the program, generates machine code with the LLVM backend, and links an executable named <out>. |
--build-native is the primary way to produce an executable: it is the one backend that covers
the whole language and every target the compiler supports. --run is the quickest way to try
a program while you work on it, and its behaviour is the reference the other three are held to.
--build is a transitional path that does not support the programs that use files, timers,
sockets and other system services (see lang.native-backends).
One program, any mode
int sumTo(int n) {
int total = 0;
for (int i in 1..n) {
total = total + i;
}
return total;
}
console.writeln("sum of 1..10 = ${sumTo(10)}");
sum of 1..10 = 55
Saved as sum.lev, that program can be run in any of the four modes:
leviathan --run sum.lev
leviathan --ir sum.lev
leviathan --build sum_cpp sum.lev && ./sum_cpp
leviathan --build-native sum_native sum.lev && ./sum_native
Each command prints sum of 1..10 = 55.
Rules
- A page describes the compiler at the commit the site was built from. A statement that the compiler does not honour is a bug in the page.
- A valid program has the same observable behaviour, meaning the same output and exit status, in
all four modes. The only differences are the documented limits of a mode or of a target: for
example
--buildrejects a program that uses timers, and the browser target rejects programs that read files. - A page or library symbol marked
unreleasedexists in the development sources but has not appeared in any tagged release yet. Its behaviour may still change before it does. - Anything described as "Not implemented" in a Notes section is a design that is not available in the compiler. Do not rely on it.
Examples
The same source file, run in the fastest mode and then built natively:
leviathan --run app.lev
leviathan --build-native app app.lev
./app
A program the reference examples are made of
console.writeln("hello from Leviathan");
Notes
Platforms: the leviathan and trident programs run on Linux. They can build executables for
Linux, Windows and a browser (WebAssembly); see lang.cross-compilation and lang.wasm-target.
See also
- The leviathan command line — Every option of the
leviathancompiler, grouped by what it does, with the exit statuses and how arguments reach your program. - The execution engines — The four ways the compiler runs a program, why they always agree, and the few places where one of them has to refuse a program.
- Native backends: LLVM and C++ — The two ways to turn a program into a native executable, what each one covers, and the runtime limits of natively built programs.