8000 GitHub - berbicanes/NovaCompiler: Complete compiler for a custom statically-typed language. VM, JIT, and LLVM IR backends, generics, traits, GC, debugger, and LSP server. Built in C++17. · GitHub
[go: up one dir, main page]

Skip to content

About

Complete compiler for a custom statically-typed language. VM, JIT, and LLVM IR backends, generics, traits, GC, debugger, and LSP server. Built in C++17.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

The Nova Compiler

A complete compiler and toolchain for Nova, a statically-typed programming language built from scratch in C++17. Features a full compilation pipeline with three execution backends, generics with monomorphization, traits with bounded generics, a step-through debugger, an LSP server for editor integration, a mark-and-sweep garbage collector, a module system, and rich error diagnostics.

Language Features

  • Static typing with type inference (int, float, string, bool, arrays, structs, enums)
  • Generics with monomorphization (fn identity<T>(x: T) -> T)
  • Traits with bounded generics (trait Printable, impl Printable for Point, <T: Printable>)
  • Enums with variant access (enum Direction { North, South }, Direction::North)
  • Structs with methods via impl blocks
  • First-class functions and closures
  • Pattern matching with match expressions and block arms
  • Module system with import / export
  • Mark-and-sweep garbage collector for heap objects
  • Multi-pass optimizer (constant folding, dead code elimination, common subexpression elimination)
  • Rich error diagnostics with source context and "did you mean?" suggestions

Execution Backends

Backend Description Use Case
VM Stack-based bytecode interpreter Default, portable, easy to debug
JIT Bytecode → x86-64 machine code at runtime Maximum performance
LLVM IR Generates LLVM IR text output Integration with LLVM toolchain

Developer Tools

Tool Description
Step-through Debugger Breakpoints, step over/into/out, variable inspection — integrated into the WASM playground
LSP Server Diagnostics, go-to-definition, hover, completion, document symbols for VS Code
WASM Playground Browser-based editor with live error checking and all execution backends
REPL Interactive read-eval-print loop

Quick Start

make                                    # Build everything
./bin/nova examples/01_syntax_and_types.nova   # Run with VM
./bin/nova --jit examples/09_jit_benchmark.nova  # Run with JIT
./bin/nova --target=llvm examples/01_syntax_and_types.nova  # Generate LLVM IR
./bin/nova-repl                         # Interactive REPL
make test                               # Run 196 tests

Nova by Example

Variables and Types

let name: string = "Nova";
let age = 25;              // type inferred as int
const PI = 3.14159;        // immutable
let active = true;

Functions and Recursion

fn factorial(n: int) -> int {
    if (n <= 1) { return 1; }
    return n * factorial(n - 1);
}

print(factorial(10));  // 3628800

Generics

fn identity<T>(x: T) -> T {
    return x;
}

let a = identity<int>(42);
let b = identity<string>("hello");

fn first<T, U>(x: T, y: U) -> T {
    return x;
}

Traits and Bounded Generics

trait Describable {
    fn describe(self) -> string;
}

struct Cat { name: string, age: int }
struct Dog { name: string, breed: string }

impl Describable for Cat {
    fn describe(self) -> string { return self.name; }
}

impl Describable for Dog {
    fn describe(self) -> string { return self.name; }
}

fn show<T: Describable>(item: T) -> string {
    return item.describe();
}

let cat = Cat { name: "Whiskers", age: 3 };
print(show<Cat>(cat));  // Whiskers

Structs and Methods

struct Point { x: int, y: int }

impl Point {
    fn manhattan(self, other: Point) -> int {
        return abs(self.x - other.x) + abs(self.y - other.y);
    }
}

let p = Point { x: 3, y: 4 };
let q = Point { x: 0, y: 0 };
print(p.manhattan(q));  // 7

Enums and Pattern Matching

enum Direction { North, South, East, West }

fn describe(d: Direction) -> string {
    let result = match d {
        Direction::North => { "Going north" },
        Direction::South => { "Going south" },
        _ => { "Other direction" }
    };
    return result;
}

print(describe(Direction::North));  // Going north

Arrays

let nums = [10, 20, 30];
nums.push(40);
print(nums.length);     // 4
print(nums[2]);          // 30

Closures

fn make_adder(n: int) -> fn(int) -> int {
    return |x: int| -> int { return n + x; };
}

let add5 = make_adder(5);
print(add5(10));  // 15

Modules

// lib/math.nova
export fn square(x: int) -> int { return x * x; }

// main.nova
import math;
print(square(5));  // 25

Error Diagnostics

The compiler produces Rust-style error messages with source context:

error[E200]: undefined variable 'nme'
 --> examples/test.nova:5:12
  |
5 |     let y = nme + 1;
  |             ^^^ undefined variable 'nme'
  = help: did you mean 'name'?

JIT Performance

The JIT compiler translates bytecode to native x86-64 machine code, achieving orders-of-magnitude speedup over the VM interpreter:

# VM: ~80 seconds
time ./bin/nova examples/9_jit_vs_vm_benchmark.nova

# JIT: ~0.01 seconds
time ./bin/nova --jit examples/9_jit_vs_vm_benchmark.nova

Both produce the same correct result: 200000010000000.

WASM Playground

Try Nova in the browser with the interactive playground:

make wasm                                        # Build WASM (requires Emscripten)
python3 -m http.server 8080 --directory playground  # Serve locally

Features:

  • Monaco editor with Nova syntax highlighting and autocomplete
  • Live error checking as you type
  • Run, AST view, bytecode disassembly, and LLVM IR output tabs
  • Step-through debugger with breakpoints, variable inspection, and call stack
  • Example programs dropdown

LSP Server

Full language server for VS Code with diagnostics, go-to-definition, hover, completion, and document symbols.

make lsp              # Build the LSP server

A VS Code extension is included in editors/vscode/. It provides:

  • Syntax highlighting for .nova files
  • Language server integration (auto-starts nova-lsp)
  • Bracket matching and auto-closing pairs

Project Structure

NovaCompiler/
  include/            C++ headers (AST, Bytecode, Type, GC, VM, JIT, ...)
  src/                C++ implementations
  tests/              Test suite (196 tests, 391 assertions)
  examples/           Example Nova programs
  lib/                Standard library modules (math, strings, collections)
  playground/         WASM-powered browser playground
  editors/vscode/     VS Code extension with LSP support
  docs/               Documentation (BYTECODE.md, TYPE_SYSTEM.md)
  .github/workflows/  CI configuration

Compiler Pipeline

Source (.nova) → Lexer → Parser → Semantic Analyzer → Optimizer → CodeGen → VM/JIT/LLVM

Each stage is implemented from scratch — no parser generators, no external dependencies.

Stage Description
Lexer Tokenizes source into a stream of tokens with position tracking
Parser Recursive descent parser, builds AST with operator precedence climbing
Semantic Analyzer Type checking, scope resolution, generic monomorphization, trait validation, module imports
Optimizer Multi-pass: constant folding, algebraic simplification, dead code elimination
CodeGen Emits bytecode (64 opcodes) or LLVM IR
VM Stack-based interpreter with GC-managed heap and debug execution mode
JIT x86-64 native code generation via mmap + PROT_EXEC

See ARCHITECTURE.md for the full architecture document.

Standard Library

Nova ships with built-in functions and importable standard library modules:

Built-in functions: print, abs, max, min, parseInt, toString, toUpper, toLower

Standard library modules (in lib/):

  • math — square, cube, is_even
  • strings — repeat, starts_with, is_empty, char_at
  • collections — range, sum, contains

Building and Testing

make              # Build all binaries (nova, nova-repl, nova-bench, nova-jit)
make test         # Run the test suite
make lsp          # Build the LSP server
make wasm         # Build WASM playground (requires Emscripten)
make all_examples # Run all example programs
make clean        # Remove build artifacts
make help         # Show all targets

Requires g++ with C++17 support and make. WASM build requires Emscripten.

Documentation

About

Complete compiler for a custom statically-typed language. VM, JIT, and LLVM IR backends, generics, traits, GC, debugger, and LSP server. Built in C++17.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

0