synth-lang
v1.2.0
Published
Synth — AI-native programming language that transpiles to JavaScript
Maintainers
Readme
⬡ Synth
An AI-native programming language that transpiles to JavaScript.
Synth is designed from the ground up to be written, read, and reasoned about by language models — with unambiguous grammar, intent-first declarations, constraint-enforced types, and explicit effect tracking. It compiles to clean, readable JavaScript with no runtime dependency.
type Health = int where value >= 0 && value <= 100
record Hero {
name: string
hp: Health
level: int
alive: bool
}
fn level_title :: (class: string, level: int) -> string {
@pure @total
@intent "Human-readable rank for a hero given class and level"
match class {
| "mage" => level >= 10 ? "Archmage" : "Apprentice"
| "knight" => level >= 5 ? "Champion" : "Squire"
| _ => "Adventurer"
}
}
@test "mage lv10 is Archmage" { level_title("mage", 10) === "Archmage" }
@test "knight lv3 is Squire" { level_title("knight", 3) === "Squire" }node tools/synth_bootstrap_cli.js --test examples/rpg.syn
✓ level_title: mage lv10 = Archmage
✓ hp_status_label: 0 = DEAD
15 passed, 0 failed, 15 totalWhy Synth?
OOP and mutable state exist to help humans manage large codebases. AI code generators don't have those constraints — they benefit from the opposite: unambiguous data flow, explicit effects, and constraints that are machine-checkable at the type level.
| Feature | What it does |
|---|---|
| @intent | Machine-readable natural language description, embedded in JS output as JSDoc |
| @pure / @total | Compiler-checked contracts — no side effects, no partial functions |
| where constraints | Types carry predicates; guard clauses are injected automatically |
| @memo | Compile-time memoization for pure total functions |
| Tagged unions | Sum types with exhaustive pattern matching |
| @test | Inline test declarations, runnable with --test |
| \|> pipelines | Left-to-right functional composition with optional as naming |
| import / export | Multi-file modules — bundled to a single JS file with synth --bundle |
Installation
npm install -g synth-langOr run from source:
git clone https://github.com/synth-pl/synth
cd synth
npm install
npm run build:toolchain
node tools/synth_bootstrap_cli.js --test examples/rpg.synUsage
# Transpile a single file
synth input.syn output.js
# Bundle a multi-file project (v0.5)
synth --bundle main.syn output.js
# Run @test declarations
synth --test input.synLanguage Tour
Functions
// Full form
fn add :: (a: int, b: int) -> int {
@pure @total
a + b
}
// Short form
fn double(n: int) = n * 2
// Lambda
let square = x => x * xConstrained types
type EmailAddress = string where value.includes("@") && value.length > 3
type Percentage = int where value >= 0 && value <= 100
// Guard clause injected automatically at function entry
fn send_welcome :: (email: EmailAddress) -> void {
@effects ["email"]
@intent "Send a welcome email — address validated by type constraint"
console.log("Sending to {email}")
}Pattern matching with guards
fn classify :: (score: int) -> string =
match score {
| n when n >= 90 => "A"
| n when n >= 80 => "B"
| n when n >= 70 => "C"
| _ => "F"
}Tagged unions
type Shape =
| Circle { r: float }
| Rect { w: float, h: float }
| Point
fn area :: (s: Shape) -> float =
@exhaustive
match s {
| Circle { r } => 3.14159 * r * r
| Rect { w, h } => w * h
| Point => 0.0
}Pipelines
let result =
heroes
|> filter(.alive)
|> map(.score)
|> sum
// Named intermediates
let total =
party
|> filter(.alive) |> as alive
|> map(.hp)
|> sumTriple-quote strings
let intro = """
In the realm of ALDENMOOR, a great evil has awakened.
Crops wilt. Rivers run backwards.
Something must be done."""Modules (v0.5)
// tiles.syn
export type Tile = | Floor | Wall | Door | Stairs | Chest | Water | Torch
export fn tile_glyph(tag: string) -> string =
match tag {
| "Floor" => "·" | "Wall" => "█"
| "Stairs" => "≋" | _ => "?"
}
// main.syn
import { tile_glyph } from "./tiles"
import { generate } from "./generator"
import { render_map } from "./renderer"
fn mount() {
let map = generate(22, 48, 1, 7777)
document.getElementById("out").innerHTML = render_map(map)
}
mount()synth --bundle main.syn bundle.js
# ✓ Bundled tiles.syn + generator.syn + renderer.syn + main.syn
# 4 modules → 407 lines JSBuilt-in testing
@test "circle area r=1" { area(Circle(1.0)) > 3.14 }
@test "rect 4x3 = 12" { area(Rect(4.0, 3.0)) === 12.0 }synth --test shapes.syn
✓ circle area r=1
✓ rect 4x3 = 12
2 passed, 0 failed, 2 totalDemos
| Demo | Description |
|---|---|
| Chronicle | v0.8 — Reactive fantasy kingdom log; store, async fn, await, on...change |
| The Bazaar | v0.7 — RPG item shop; generics, interface, let infer, immutable state |
| Dungeon Map Toolkit | v0.5–v0.6 — 4-file module demo with Result config parser |
| RPG Adventure | 50-battle dungeon crawl — 1576 lines of pure Synth game logic |
| Combat Engine | Turn-based combat system |
| Music Library | Synthwave track browser |
Documentation
Full language reference at synth-pl.github.io/synth/docs.html
Roadmap
| Version | Theme | Key features |
|---|---|---|
| v0.4 ✓ | Guards & Unions | when guards, tagged unions, @test, ?. / ??, destructuring, heredocs |
| v0.5 ✓ | Modules | import / export, synth --bundle — multi-file projects |
| v0.5.2 ✓ | Ergonomics | for loops (range + forEach), break/continue, let mut |
| v0.6 ✓ | Safety | Result<T>, ? propagation, error contracts, refine x: "claim" semantic narrowing |
| v0.7 ✓ | Type System | Generics <T,U>, interface, fn(T)->U type expr, let infer model-resolved types |
| v0.8 ✓ | Async & Reactive | async fn, await, store reactive state, on...change subscriptions, enforced @effects |
| v0.9 ✓ | Tooling | LSP foundations, synth fmt, rich errors |
| v1.0 ✓ | Stability | Semver promise, npm package, bootstrap compiler |
| v1.1 ✓ | AI-Native | likely arms — probabilistic pattern matching by semantic similarity |
| v1.2 ✓ | Spec Extraction | synth --spec extracts @intent / constraints / likely / refine as JSON |
| v1.3 | Explain | explain { } blocks join the spec export |
| v1.4–1.5 | LSP | Thin then rich language server |
| v1.6–1.7 | Maps & DX | Source maps, polish |
| v2.0 | Ecosystem | Frozen agent protocol (spec schema 1.0) |
VS Code Extension
Syntax highlighting for .syn files is available in vscode-extension/. Install via Extensions: Install from VSIX in the command palette.
Contributing
See CONTRIBUTING.md. Issues and PRs welcome.
License
MIT — © 2026 synth-pl
Support
If Synth is useful to you, consider sponsoring the project on GitHub. It helps keep development going.
