Topaz is a programming language designed for typesetting. Use it for programs that produce print-ready documents, from books to reports and invoices, and for command-line tools and application logic as well. Run the same source on your computer or build a package for the browser.
Run this program today and get the output shown here.
function greet(name: string) -> string {
return "Hello, {name}!"
}
print(greet("Topaz"))Hello, Topaz!
ATLAS
ATLAS turns a manuscript into print-ready book pages. Here is a page it set, with part of its line-breaking rules in Topaz. ATLAS names these functions with Korean typesetting terms, shown here in English.

function nextIsNotLatinSpace(next: Option<string>) -> bool {
match next {
case Some(text) => !isLatinSpace(text)
case None => true
}
}
function nextHasNoLineStartBan(next: Option<string>) -> bool {
match next {
case Some(text) => !hasLineStartBan(text)
case None => true
}
}Part of the ATLAS line-breaking rules
Name functions and variables with the words of typesetting, such as badness, in Korean, Russian, or English. Topaz also keeps the characters of a manuscript exactly as entered.
Strings & Templates →Write a typesetting rule once and build the same source as an executable for your computer and a package for the browser. Both follow the same language rules, so the rule you check on screen is the rule your output uses.
Interpreter & Backends →An int is a signed 64-bit integer, and overflow stops the program at that point instead of continuing with a wrong value. When you measure line widths and layout costs in integers, an overflow cannot hide in the result.
Runtime Behavior →Put a fixed set of cases, such as line-break classes, in an enum, and the compiler checks that each match handles every one. When you add a case later, the build reports each match that does not handle it yet.
Patterns & Control Flow →Lispex
Topaz does the computing that breaks lines and builds pages. Decisions that change with each publisher and book, such as which page a chapter starts on or how many lines may stand alone, go into separate Lispex rules. The evaluator built into Topaz runs those rules within set limits. Change a rule file and lock the package again, and the same manuscript takes another style without any change to the application code.
(let ((min-lines 2))
(if (< input min-lines) "next-page" "keep"))All of rules/widow-lines.lspx
import src.values { singleDigit, textOf }
import std.lispex { defaultLimits, evaluate }
import std.lispex.rules as rules
export function main(args: Array<string>, stdin: string) -> Result<int, string> {
let rule = rules.widow_lines()
for linesLeft in [1, 2] {
match evaluate(rule, singleDigit(linesLeft)?, defaultLimits(rule)) {
case Ok(Complete(result)) => print("lines left {linesLeft}: {textOf(result)}")
case _ => return Err("the rule did not finish")
}
}
Ok(0)
}lines left 1: next-page lines left 2: keep
All of src/main.tpz. singleDigit and textOf are small helpers that convert Lispex values.
Lispex rules run in the interpreter and in native builds. For the full setup, including the manifest and limit files, see Run Lispex Rules.
function discount(customer: { tier: string, years: int }) -> float {
return match customer {
case { tier: "vip", years } if years > 5 => 0.3
case { tier: "vip" } => 0.2
case { years } if years > 1 => 0.1
case _ => 0.0
}
}
print("{discount({ tier: "vip", years: 7 })}")
print("{discount({ tier: "new", years: 0 })}")0.3 0.0
function clean(words: Array<string>) -> Array<string> {
return filter(words, (w: string) => w != "")
}
function shout(words: Array<string>) -> Array<string> {
return map(words, (w: string) => w + "!")
}
let line = ["one", "", "way", "", "to", "say", "it"]
|> clean
|> shout
print("{line}")[one!, way!, to!, say!, it!]
Concurrency and cleanup examples are in Concurrency and Defer & Resources.
Explore Topaz
Start with what Topaz is for. Then follow the guided path, scan the syntax map when you need a quick answer, or choose a toolchain destination. The compiler you install is itself written in Topaz. How the compiler checks its own build →
See what Topaz is designed for, what its code looks like, and where it fits before writing your first program.
Meet Topaz →02Start with one small program and continue step by step to a checked, tested, two-module application.
Start learning →03Scan everyday syntax and jump straight to the focused manual page for each language feature.
Open the syntax map →04Run files, manage packages, and build for your computer or browser.
Explore the tools →