Simple Project

A strict language and runtime stack focused on predictable behavior, explicit boundaries, and an inspectable pipeline.

Why Simple Exists

Simple is built around one clear execution story: source code lowers to a readable intermediate form, then to bytecode, then executes in a verified VM. The point is not clever syntax tricks. The point is control: deterministic behavior, clear failure modes, and an architecture you can embed and reason about.

Strict by default

Types are explicit and validated early. You get fewer hidden conversions and clearer diagnostics.

Pipeline visibility

You can inspect SIR and SBC artifacts directly, making compiler/runtime debugging practical.

Embeddable runtime

The VM is designed as a host boundary for app scripting, tools, and sandboxed execution.

Supported Surface

Language

Strict typing, explicit mutability, artifacts, enums, modules, and script-style top-level execution.

Pipeline

.simple -> SIR -> SBC -> VM execution with loader/verifier gates and deterministic diagnostics.

Runtime

Interpreter execution, heap/GC, arrays/lists/strings, and core system module dispatch.

Interop

DL-based C/C++ interop with strict extern signatures and ABI marshalling.

Authoritative Docs

Language

Docs/Lang.md - syntax, semantics, and validation.

Simple Lang: Core Ideas

Declarations are explicit

Variables, parameters, and returns are typed. Type mismatches fail at validation.

count : i32 = 42
label :: string = "ready"

add : i32 (a : i32, b : i32) {
  return a + b
}

Strict typing is enforced across variables, parameters, and returns.

Compilation + Execution Pipeline

.simpleSource program
->
.sirTyped/intermediate form
->
.sbcBytecode artifact
->
VMVerified execution
# compile + run source
simple run Tests/simple/hello.simple

# inspect IR
simple emit -ir Tests/simple/math.simple --out math.sir

# build bytecode artifact
simple emit -sbc Tests/simple/math.simple --out math.sbc

# execute bytecode directly
simplevm run math.sbc

Simple | SIR | SBC Explorer

Compare the same intent across source, IR, and bytecode layers.

Simple Lang Source

High-level typed source with explicit mutability/import boundaries.

import io

sum: i32 (a: i32, b: i32) {
  return a + b
}

total: i32 = sum(10, 32)
io.println("total={}", total)

VM Architecture

The VM is split into explicit subsystems so behavior remains auditable and testable.

Loader

Parses SBC sections, metadata, constants, and signatures into a runtime module representation.

Verifier

Rejects malformed bytecode and invalid type/control-flow combinations before any execution starts.

Interpreter

Executes opcodes with strict checks and deterministic semantics. Traps are explicit and testable.

System Boundary

System modules expose controlled host services for IO, files, math, OS, and dynamic loading.

Embedding Interface

Host apps can compile/load/run modules and control runtime lifecycle for plugin or script scenarios.

JIT Path (in progress)

Tiering exists; optimization is ongoing. Baseline correctness and coverage still take priority.

System Libraries and Responsibility Split

Simple keeps system features modular to avoid overlap and make dependency intent explicit.

FunctionPurpose
buffer_new(length)Create a new i32 buffer/list of requested length.
buffer_len(buffer)Return current buffer length.
buffer_fill(buffer, value, count)Fill up to count slots with value; returns written count.
buffer_copy(dst, src, count)Copy up to count elements from source to destination.
print(value) / println(value)Stream output for scalar/format-based text emission.

CLI Quick Reference

Commands

run, check, build, compile, emit, lsp

Inputs

.simple, .sir, .sbc (VM path)

Version

simple --version, simple -v, simple version

Build Scripts

./build_linux, ./build_macos, ./build_windows

Interop With C/C++

Use extern to declare native symbols and call them through DL.

import dl
import io

extern raylib.InitWindow : void (w: i32, h: i32, title: string)
extern raylib.CloseWindow : void ()

lib: i64 = dl.open("raylib.dll", raylib)
if (lib == 0) {
  io.println("raylib load failed: {}", dl.last_error())
}

raylib.InitWindow(800, 450, "Simple + raylib")
raylib.CloseWindow()

Practical Examples

Script-style execution

Top-level statements execute in order.

import io
io.println("hello")
io.println(10 + 20)

Structured data + behavior

Artifacts give explicit member layout and typed access.

Point :: Artifact { x: i32 y: i32 }

sum: i32 (p: Point) {
  return p.x + p.y
}

Inspect then run

Use the same program through each stage of the stack.

simple emit -ir app.simple --out app.sir
simple emit -sbc app.simple --out app.sbc
simplevm run app.sbc

Quick Start

git clone https://github.com/JJLDonley/Simple
cd Simple
./build.sh --suite all
./bin/simple run Tests/simple/hello.simple

Releases: github.com/JJLDonley/Simple/releases