About The Language

A small compiled language: Python ish syntax, static types, native binaries via LLVM.

License: MIT · Version: 1.0.4 · Releases

Quick start (Windows)

hello.vpp
# 1. Install vpp-1.0.4-setup.exe from GitHub Releases
# 2. Install "v++ Language" in VS Code (publisher: vpp-lang)
vpp run examples\hello.vpp
vpp --version
vpp doctor

Docs: website · hello-world guide

What works

  • vpp run interpreter + vpp build native codegen
  • LSP, debugger (F5), tests, fmt, packages (vpp.toml)
  • VS Code extension on Marketplace
  • Windows installer with bundled LLVM; Unix from source

Build from source

terminal
git clone https://github.com/shauryaR790/VPP.git
cd VPP
cargo build --release --features codegen,lsp
cargo test --all-targets
# Verify install: vpp doctor

See CONTRIBUTING.md · SPEC.md

Releases https://github.com/shauryaR790/VPP/releases
Extension https://marketplace.visualstudio.com/items?itemName=vpp-lang.vplusplus
Issues https://github.com/shauryaR790/VPP/issues
CMake docs/guides/cmake.md

V++ Compiler Architecture (v0.2)

Overview

V++ is a statically typed language with a single front end and two backends:

  • Interpreter tree walking evaluation for development and teaching
  • Native compiler lowers to V++ IR, then LLVM, links the C runtime

Both backends consume the same typed AST produced by the type checker.

text
.vpp source
    │
    ▼
 Lexer (src/lexer)
    │
    ▼
 Parser → AST (src/parser, src/ast)
    │
    ▼
 Module loader (src/modules)  -  flat merge, path imports (v0.2)
    │
    ▼
 Type checker (src/types/check.rs) → TypedProgram
    │
    ├──────────────────────┐
    ▼                      ▼
 Interpreter           IR lower (src/ir/lower.rs)
 (src/interp)                │
    │                        ▼
    │                   v++ IR (src/ir)
    │                        │
    │                        ▼
    │                   LLVM emit (src/codegen/emit.rs)
    │                        │
    │                        ▼
    │                   C runtime (runtime/vpp_runtime.c)
    │                        │
    └──────── same semantics ─┴──► native executable

Components

Lexer / Parser

Hand written lexer with significant newlines. Recursive descent parser with Pratt precedence for expressions.

Type checker

Two pass: register types and functions, then check bodies. Uses src/builtins for builtin signatures.

V++ IR

Thin intermediate representation between typed AST and LLVM. Makes memory operations, control flow, and calling conventions explicit. See src/ir/mod.rs.

LLVM backend

Inkwell based. Emits LLVM IR, invokes clang to produce object files, links runtime. Feature gated: --features codegen.

Runtime

C ABI documented in MEMORY_MODEL.md. Heap strings and arrays use ARC reference counting.

Builtins

Single registry in src/builtins/mod.rs consumed by type checker, interpreter, and codegen.

Feature parity (v0.2 target)

See CHANGELOG.md and tests/parity/ for the live matrix. Native codegen must match interpreter output for all supported features.

Version notes

  • v0.2 native foundation, IR, ABI, parity tests
  • v0.3 module redesign, package manager (not in v0.2)
  • v0.4 generics, traits, mut, compile time match exhaustiveness

V++ Memory Model (v0.2 bootstrap)

Goals

  • Predictable behavior for beginners
  • Efficient native executables
  • Clear C ABI between compiler and runtime
  • Extensible toward v1.0 production model

v0.2 does not implement a borrow checker or garbage collector.

Representation

Stack (by value in LLVM)

Type Native representation Notes
int i64 Signed 64 bit
float double IEEE 64 bit
bool i1 / zero extended
fixed size struct LLVM struct Field layout computed by codegen

Heap (ARC)

Type C type Header
string VppString* { char* data; int64_t ref_count; }
array[T] VppArray* { void* data; int64_t len; int64_t elem_size; int64_t ref_count; }

String ABI (v0.2)

1. String literals compiler emits a nul terminated i8* constant, calls vpp_string_new(cstr)VppString*

2. String locals stored as VppString* (pointer to heap object)

3. print(s) calls vpp_print_str(VppString* s)

4. len(s) calls vpp_strlen(VppString* s)

5. Concatenation vpp_string_concat(VppString* a, VppString* b) → new VppString* (retain inputs during call)

Never pass raw i8* to vpp_print_str.

Array ABI (v0.2)

1. Literals vpp_make_array(len, elem_size) then fill element slots via typed GEP

2. Value type VppArray* everywhere (locals, parameters, returns)

3. Elements inline in buffer; string elements store VppString* (8 bytes); bool uses 1 byte

4. len(a) vpp_array_len(VppArray*)

5. a[i] vpp_array_index_ptr(arr, i) with bounds check (abort on OOB, matches interpreter error)

6. Ownership vpp_array_retain on pass to functions; vpp_array_release at scope exit

7. String elements vpp_string_retain when stored into array literal

ARC rules (v0.2 bootstrap)

  • vpp_string_new / vpp_make_array ref_count = 1
  • vpp_*_retain increment
  • vpp_*_release decrement; free at zero
  • Function arguments: retain on pass (caller keeps ownership)
  • Scope exit: release heap locals (v0.2: strings in nested scopes)

Full ARC at scope boundaries is implemented incrementally. Leaks are acceptable in v0.2 for top level only programs; crashes are not.

Interpreter mapping

Native Interpreter
VppString* Rc<String>
VppArray* Rc<Vec<Value>>

Semantics must match observable behavior (print output, len, indexing).

Future (v1.0)

  • Move semantics at assignment for heap types
  • Struct/enums with explicit layout in spec
  • Optional unsafe blocks
  • No hidden GC

V++ Language Specification

> v1.0 FROZEN (2026 08 21). Breaking changes require v2.0. See PARITY_PROMISE.md.

This document describes V++ as implemented in v1.0. If code and spec disagree, parity tests and native execution are authoritative.

Types

Type Syntax Notes
int int 64 bit signed
float float 64 bit IEEE
bool bool true / false
string string UTF 8 heap string (ARC native)
array array[T] Homogeneous array
struct Name User defined product type
enum Name User defined sum type
Option Option[T] Some(x) / None
Result Result[T, E] Ok(x) / Err(e)

Variables

text
let x = 10              // immutable int
let mut total = 0       // mutable; required for reassignment
total = total + 1
# ...
# See docs for full examples

Functions

text
fn add(a: int, b: int) -> int {
    return a + b
}
fn id[T](x: T) -> T {
    return x
}
fn main() -> int {
    let n = id[int](42)
    return n
}

Generic calls require explicit type arguments: idint.

When present, fn main() -> int is the program entry point (interpreter and native both invoke it).

Traits

text
trait Display {
    fn to_text(self) -> string
}
impl Display for User {
    fn to_text(self) -> string {
        return self.name
    }
}
// method call (static dispatch)
print(user.to_text())

Control flow

if / else, while, for i in start..end (half open), for item in arr, break, continue, match.

Match arms use blocks:

text
match status {
    Active => {
        print("active")
    }
    Inactive => {
        print("inactive")
    }
}

User enum variants in expressions use bare names when the expected type is known (e.g. struct field status: Active).

Builtins

Name Signature Behavior
print printable values Print line per argument
len array or string → int Length
assert bool → void Fail if false
assert_eq T, T → void Fail if not equal
read_file / write_file / file_exists fs File I/O (also via std.fs)
json_parse / json_stringify json JSON helpers (also via std.json)
process_run process Run shell command (also via std.process)

Modules (v0.3)

text
import std.io
import std.fs
import "legacy/path.vpp"   // still supported
# ...
# See docs for full examples
  • Canonical paths: import std.iostd/io.vpp
  • pub fn / pub struct / pub enum for exports
  • Namespaced calls: math.add(1, 2)
  • Circular imports and duplicate imports are errors

Projects and packages

vpp.toml manifest, vpp.lock, dependencies via path, git, or registry semver (hello-lib = "0.1.0").

Standard library

std/io, std/math, std/string, std/collections, std/fs, std/json, std/process.

Execution

  • vpp run file.vpp interpreter (calls fn main() when defined)
  • vpp build file.vpp -o out.exe native executable (requires LLVM + codegen)
  • .\stress.ps1 compare interpreter vs native output for stress.vpp

Interpreter and native must produce identical stdout for supported programs.

Known limitations (v0.4)

  • Generics use monomorphization with explicit type arguments at call sites (no inference yet)
  • Traits use static dispatch only (no trait objects or bounds)
  • Hosted package registry is local (registry/index.toml); no remote publish yet

Roadmap

v1.0 (shipped)

  • [x] Frozen language spec SPEC.md
  • [x] Parity Promise PARITY_PROMISE.md
  • [x] Compatibility CI all examples on every push
  • [x] Debugger (CLI + VS Code F5)
  • [x] Test Explorer UI
  • [x] Package registry search (vpp search)

v0.9 (shipped)

  • [x] Test Explorer UI
  • [x] vpp test --list for IDE integration
  • [x] vpp search registry command
  • [x] SPEC v1.0 release candidate

v0.8 (shipped)

  • [x] Interpreter line debugger (vpp debug)
  • [x] VS Code debug launch (DAP)

v0.7 (shipped)

  • [x] vpp watch live re run on save
  • [x] vpp bench interpreter timing
  • [x] Cross platform doctor hints
  • [x] Extension 0.7 Watch + Benchmark commands

v0.6 (shipped)

  • [x] vpp repl interactive interpreter session
  • [x] Extension 0.6 format on save, REPL command, snippets, lazy LSP

Post v1.0 (ideas)

  • Native debug symbols
  • Hosted registry on GitHub Pages
  • v2.0 language extensions (only with major version)

Track issues: GitHub Issues