All selected work

GLaDOS

A compiler and virtual machine in Haskell. A C-like language compiled to custom bytecode.

Role
Co-built the compiler and the virtual machine
Team
Team of 5
When
Sep – Nov 2025
  • Haskell

Problem

An Epitech project: design a C-like language, compile it to our own bytecode and run it on our own virtual machine, all in Haskell.

What I built

In a team of five, I co-built the compiler and the VM.

How it works

GLaDOS toolchainSource code in a C-like language is compiled by a Haskell compiler into custom bytecode, which a Haskell virtual machine executes.SourceC-like languageCompilerHaskellCustom bytecodeVirtual machineHaskell

Results

A working toolchain for a C-like language with optional semicolons and static typing. Programs compile to a WebAssembly-like custom bytecode and run on our VM, and the toolchain can display the AST and the IR for debugging.

Programs can also be compiled to separate object files and linked. Errors report the line and column, and the Hspec test suite runs 208 tests with no failures.

Seen running

$ cat /g/tests/dotC/factorial.c
  int factorial(int n) {
      if (n <= 1) {
          return 1
      }
      return n * factorial(n - 1)
  }
  
  int main() {
      int result = factorial(5);
      return result
  }
$ glados  < factorial.c
VInt 120

$ glados --ir < factorial.c
// GLaDOS IR - Compiled Program
// Entry point: function 1

U0 factorial()  // Function 0
{
  // params: 1, locals: 0
     0: GET.LOCAL[0];
     1: PUSH.I64 1;
     2: CMP.LE;
     3: JZ @3;
     4: PUSH.I64 1;
     5: RET;
     6: GET.LOCAL[0];
     7: GET.LOCAL[0];
     8: PUSH.I64 1;
     9: SUB.I64;
    10: CALL func0;
    11: MUL.I64;
    12: RET;
}

U0 main()  // Function 1
{
  // params: 0, locals: 1
     0: PUSH.I64 5;
     1: CALL func0;
     2: SET.LOCAL[0];
     3: GET.LOCAL[0];
     4: RET;
}
Recursive factorial: run on the VM, then the IR the compiler emits.
$ cat /g/tests/linker/test_basic_lib.c
  // LinkTest: lib for test_basic_main.c
  // Library with utility functions
  int add(int a, int b) {
      return a + b;
  }
  
  int multiply(int x, int y) {
      return x * y;
  }
$ cat /g/tests/linker/test_basic_main.c
  // LinkTest: main
  // LinkWith: test_basic_lib.c
  // Expected: Success (return 16)
  // Main program that uses library functions
  int add(int a, int b);
  int multiply(int x, int y);
  
  int main() {
      int result;
      result = add(5, 3);
      result = multiply(result, 2);
      return result;
  }
$ glados --compile-obj < test_basic_lib.c > lib.gbo; glados --compile-obj < test_basic_main.c > main.gbo
$ glados --link lib.gbo main.gbo > out.gbc && glados --run out.gbc
[link exit 0]
VInt 16
Separate compilation: two object files linked into one program, then run.
$ cat /g/tests/dotC/test_3_2_undefined_func.c
  int main() {
      return multiply(5, 3);  // multiply not defined
  }
  
  /* Expected: Undefined function error */
$ glados  < test_3_2_undefined_func.c
Undefined function 'multiply' at SourcePos {sourceName = "input", sourceLine = Pos 2, sourceColumn = Pos 12}

[exit 84]

$ cat /g/tests/dotC/test_4_1_undef_var.c
  int main() {
      return x;  // x not defined
  }
  
  /* Expected: Undefined variable error */
$ glados  < test_4_1_undef_var.c
Undefined variable 'x' at SourcePos {sourceName = "input", sourceLine = Pos 2, sourceColumn = Pos 12}

[exit 84]
Errors carry the line and column, and exit with code 84.
    Comparison Operations
      executes EqInt (true) [✔]
      executes EqInt (false) [✔]
      executes LtInt [✔]
    Logical Operations
      executes AndBool (true && false) [✔]
      executes OrBool (true || false) [✔]
    Control Flow Operations
      executes Jump [✔]
      executes JumpIfFalse (condition is false, should jump) [✔]
      executes JumpIfFalse (condition is true, should not jump) [✔]
      executes Halt [✔]
  execute (main loop)
    executes a simple program: 5 + 3 [✔]
    executes with local variables [✔]
    executes with Jump [✔]
    executes JumpIfFalse (true, don't jump) [✔]
    executes JumpIfFalse (false, do jump) [✔]
    returns error on division by zero [✔]
    returns error when halting with empty stack [✔]
    executes Call and Return - simple function call [✔]
    executes Call and Return - nested calls [✔]
Finished in 0.0194 seconds
208 examples, 0 failures
glados> Test suite glados-test passed
End of the Hspec suite: 208 examples, 0 failures.

Links