Sol is a toy programming language, which is supposed to teach me how to build a compiler. The Sol compiler is implemented in C++23 using ANTLR4 and LLVM.
The name "Sol" is derived from "Operating Systems Language", as it started out as pseudocode which I used to solve synchronization exercises during an operating systems course at my university. "Sol" it's also the name for the Sun, and "Sól" is the name for the Norse goddess of the Sun.
The project uses exceptions and RTTI, but only because the ANTLR4 runtime requires it. I prefer to not use them if possible.
As an end goal, the language should look like this:
/*
* Having access to a binary semaphore, implement a general semaphore, which can
* be incremented or decremented by 1 or 3 (operations P1, P3, V1, V3) – the
* semaphore must of course never be negative.
*/
type GeneralSemaphore {
let n: integer;
let no_waiting: integer;
let mutex(1): BinarySemaphore;
let semP(0): BinarySemaphore;
Semaphore(n: integer) {
this.n = n;
this.no_waiting = 0;
}
// [n > 0]
procedure P1() {
mutex.p();
if (n == 0) {
no_waiting += 1;
mutex.v();
semP.p();
no_waiting -= 1;
}
n--;
mutex.v();
}
procedure V1() {
mutex.p();
n++;
if (no_waiting > 0) {
semP.v();
} else {
mutex.v();
}
}
}
But we're currently far away from that goal. Current iteration only supports:
- integers,
- expressions,
- procedures.
Programs which can be written using these building blocks are limited:
procedure foo(x: int, y: int): int {
return x + y * y - x / 2;
}
procedure pow2(x: int) {
return x * x;
}
procedure main() {
return pow2(10) / foo(2, 2);
}
Repository structure:
design/- design documents for the language,examples/- example programs in Sol; keep in mind that only programs fromexamples/first_iterationwork for now,src- source code ofsolc, the Sol compiler; the entry point forsolcis insrc/driver.cpp.
Project uses CMake as it's build system. Packages are managed via Conan.
To build you must first install:
- a C++ compiler which supports C++23, eg. GCC14
- cmake
- make or ninja
You can do so using your distributions package manager. Building on Windows and MacOS is currently unsupported, although the code should be portable.
To build, first install the packages specified in conanfile.py:
project_root/$ conan install . --output-folder=./dependencies --build=missing
WARNING: for certain conan profiles, conan may need to build llvm locally. It has to be done once, and takes about 1.5h on my hardware.
To build, first create a build folder and configure CMake:
project_root/$ mkdir build && cd build
project_root/$ cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../dependencies/build/Release/generators/conan_toolchain.cmake
To build the compiler:
project_root/build/$ cmake --build
To run unit tests:
project_root/build/$ ctest
IMPORTANT: to link object files resulting from compilation, the Sol compiler
invokes clang. As such, it must be installed and present in your $PATH. A
more sophisticated approach to linking, including a custom language runtime and
support for the GNU ld and LLVM lld linkers is in the works.
Current iteration of the compiler can only compile single file programs.
An example sol program, procs.sol is given below:
procedure foo(x: int, y: int): int {
return x + y * y - x / 2;
}
procedure pow2(x: int) {
return x * x;
}
procedure main() {
return pow2(10) / foo(2, 2);
}
The general usage of the Sol compiler is:
$ solc <program_filename> -o <executable_filename>
If -o is ommited, the resulting executable is named after the program.
Given <progname>.sol, the executable will be named <progname>. For
example, the procs.sol program will produce the procs executable.
All options of solc can be displayed using -h:
$ solc -h
Compiler debugging information can be showed using -v:
$ solc -v