Topazdocs
Обзор

Знакомство с Топазом

Топаз — малый замкнутый язык для замысла приложения: один канонический способ сказать каждую вещь; пишут люди и агенты, проверяет тулчейн.

Примечание о версии: эта документация отражает канонический синтаксис Topaz v5.2 — строгого надмножества замороженного v5.1. Модули — новинка v5.2: см. Модули и видимость.

Топаз — малый замкнутый язык для замысла приложения: один канонический способ сказать каждую вещь; пишут люди и агенты, проверяет тулчейн. Он читается как Python или TypeScript, но поверхность сознательно замкнута: у каждого замысла ровно одна каноническая форма, зафиксированная в спецификации v5.2. О том, кому язык подходит и кому нет, см. Почему Топаз?.

Каждая программа на этой странице, показывающая вывод, выполняется верификатором сайта на тулчейне v5.2. Каждый блок вывода обязан байт в байт совпадать с записью реального запуска. Остальные фрагменты проходят проверку парсером.

Интероп с Lena Code: Топаз входит в число языков, охватываемых конвертационными процессами Lena Code. Он не является ядром или промежуточным языком Lena Code; Топаз остаётся независимым языком и используется как инженерный язык для части реализации и валидации CSKernel™.

Первое доказательство: Unicode-first

Идентификаторы — Unicode начиная с лексера: кириллица здесь гражданин первого класса, и слова предметной области остаются на вашем языке, а не превращаются в латинизированные приближения:

TOPAZ
function greet(name: string, language: string) -> string {
    return match language {
        case "한국어" => "안녕하세요, {name}님!"
        case "Русский" => "Привет, {name}!"
        case _ => "Hello, {name}!"
    }
}

let 사용자 = "김토파즈"
print(greet(사용자, "한국어"))
print(greet("Topaz", "Русский"))
OUTPUT
안녕하세요, 김토파즈님!
Привет, Topaz!

사용자 — обычная переменная. Unicode-идентичность не «терпимый крайний случай»: идентификатор — ровно та последовательность скаляров, которую вы написали, без тихой нормализации (§1), а резолвер модулей отвергает похожие имена модулей между файлами по ключам exact, NFC/NFD и case-fold (§17).

Четыре столпа

Малая замкнутая поверхность

У каждого замысла один способ записи. Политику решает язык: Result для восстановимых ошибок, опционалы для отсутствия, defer для очистки. Так ни людям, ни агентам не приходится решать это заново в каждом файле:

TOPAZ
function parsePort(raw: string) -> Result<int, string> {
    let n = toInt(raw) ?? -1
    if n < 1 {
        return Err("not a port: {raw}")
    }
    return Ok(n)
}

function startup(raw: string) -> Result<string, string> {
    defer print("config closed")
    let port = parsePort(raw)?
    return Ok("listening on {port}")
}

print("{startup("8080")}")
print("{startup("http")}")
OUTPUT
config closed
Ok(listening on 8080)
config closed
Err(not a port: http)

Оператор ? пробрасывает Err; defer выполняется на каждом пути выхода, поэтому config closed появляется в транскрипте дважды.

Unicode-first идентичность

Доказано выше. Строки — последовательности скаляров Unicode без неявной нормализации: что написано, то и сравнивается (§1). API кластеров графем отложены до будущего решения v5 (§20, §22).

Готовность к эпохе агентов

Спецификация, достаточно малая, чтобы агент держал её целиком; машинно-проверяемые профили; и документация, которая сама проверяется: каждый канонический фрагмент на этом сайте проходит проверку парсером, а исполняемые примеры выполняются с зафиксированным выводом. См. как проверяется этот сайт.

Шаблоны с замыслом

Строки sql, sh и path — это шаблоны: структурированные значения, в которых части и интерполяции остаются раздельными, а не схлопываются в строку:

TOPAZ
let table = "users"
let q = sql"select * from {table} where active = {true}"
print("{q}")
OUTPUT
<sql template, 3 part(s), 2 interpolation(s)>

Этот плейсхолдер — честное состояние сегодня: значение-шаблон существует, и ничего не было склеено; политики рендеринга по доменам (кавычки, экранирование) отложены до будущего решения v5. Безопасность остаётся грамматикой, а не дисциплиной.

Типовая дисциплина, честно

По спецификации Топаз статически типизирован: аннотации, вывод типов и литеральные типы входят в зафиксированную поверхность v5.2:

TOPAZ
type TrafficLight = "red" | "yellow" | "green"

function next(light: TrafficLight) -> TrafficLight {
    return match light {
        case "red" => "green"
        case "green" => "yellow"
        case _ => "red"
    }
}

Статическая проверка типов выпущена в v5.2: topaz check по умолчанию типизирует весь компилируемый юнит. Контракты, которые интерпретатор когда-то обеспечивал только во время выполнения как динамические страховки (TPZ5xxx), теперь повышаются до статической диагностики и ловятся до запуска программы. Страница состояния отслеживает гейты тулчейна.

Что работает сегодня

Topaz v5.2 работает от начала до конца: Unicode-first лексер, полный парсер и многофайловый резолвер модулей; статическая проверка типов на весь юнит (topaz check); эталонный интерпретатор за topaz run (сопоставление с образцом, defer, concurrent и фолты с указателями на исходный код); и бэкенд эмиссии Rust (topaz emit / topaz build), который понижает программу до самодостаточного нативного бинарника, дифференциально протестированного против интерпретатора, так что оба совпадают по построению. Количества и проверки сайт публикует на странице Состояние тулчейна.

Первая программа — в руководстве Начало работы: каждый транскрипт там записан с реального тулчейна.

Дорога вперёд

Поверхность языка зафиксирована на v5.2; перечисленное отложено намеренно, а не отсутствует:

  • API кластеров графем и рендеринг шаблонов по доменам (политика кавычек/экранирования) — будущее решение v5 (§20, §22).
  • Оптимизированное понижение — бэкенд Rust сегодня ориентирован на корректность; типизированное/мономорфное понижение — отдельная будущая запись.

Сверх этих ярлыков страница ничего не обещает. Источник истины: страница состояния.

С чего начать

Один способ сказать.