Перейти к содержимому
Топаз6.0 · До релиза
Загрузка

Поиск в документации

Specification 6.0

Выберите результат стрелками и нажмите Enter, чтобы открыть его.

Введите имя API, номер диагностики, правило или тему проекта.

    Топаз 6.0

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

    Топаз является универсальным языком программирования со встроенной вёрсткой. Код, который делает одно и то же, выглядит одинаково, кто бы его ни писал.

    Руководство 6.0 доступно на английском языке.

    ТурЯзыкБиблиотекаИнструментыДиагностикаПесочница

    591правило15глав340API в 19 модулях109диагностик1 332примера

    oneway-ru.tpz
    1. import std.io
    2. import std.bigint { BigInt }
    3. let подписи = ["12", "обложка", "14"]
    4. let номера = подписи.map((текст) => match (BigInt.parse(текст, 10)) {
    5. case Some(число) => число.toInt()
    6. case None() => None()
    7. })
    8. io.writeLine("{номера}")
    Ожидаемый вывод
    [Some(12), None, Some(14)]

    map пишется после списка. BigInt.parse разбирает каждую строку, а toInt преобразует полученное число. На месте метки «обложка» остаётся None.

    Для кого и для чего

    Создан для таких команд

    Команды, которые делают движок вёрстки книг

    От рукописи к полосам

    Движок принимает рукопись и решает, где закончатся строки и страницы. Разбиение абзацев и правила переноса для корейского, японского и китайского берутся из стандартной библиотеки. Один и тот же код разбиения строк работает в предпросмотре в браузере и в вёрстке для печати.

    Пакет для браузера · Исполняемый файл

    Справочник std.typeset → (на английском)

    Команды, у которых правила зависят от издательства

    Решения для каждой книги в файлах правил

    С какой страницы начинать главу и сколько висячих строк допустимо, у каждого издательства и каждой книги свои решения. Они живут в файлах правил Лиспекса, а код разбиения строк общий для всех книг. Если у каждого клиента свой стиль учебника или отчёта, код приложения не меняется.

    Исполняемый файл · Правила Лиспекса

    Вызов правил Лиспекса → (на английском)

    Команды, которые делают веб-инструменты

    Обработка данных в веб-приложении

    Функцию, которая разбирает входные данные, например проверяет JSON, пишут на Топазе и собирают в пакет для браузера. Существующее веб-приложение вызывает её из JavaScript. Так работают браузерные инструменты jeni.kr.

    npm · Пакет для браузера

    Вызов из JavaScript → (на английском)

    std.typeset

    Вёрстка в стандартной библиотеке

    Модуль std.typeset в Топазе 6.0 разбивает абзацы на строки. Программа ниже разбивает корейское предложение на строки шириной в десять слогов хангыля. Если учитывать весь абзац, последнее слово не остаётся в строке одно.

    typeset-ru.tpz
    1. import std.io
    2. import std.typeset {
    3. BreakCluster, BreakPolicy, BreakMode, KinsokuRules, BreakOpportunity, Paragraph, Item,
    4. Box, Penalty, BreakRule, DistanceGrid, CostModel, LineGeometry, JustificationPolicy,
    5. JustificationMode, KnuthPlassPolicy, ParagraphPlan, classifyBreaks,
    6. breakParagraph,
    7. }
    8. let предложение = "문단 전체를 보고 줄을 나누면 마지막 줄이 짧게 남지 않고 줄마다 길이가 고르게 됩니다."
    9. let знаки = предложение.scalars().map(знак)
    10. let итог = match (classifyBreaks(знаки, корейскиеПравила(знаки))) {
    11. case Ok(места) => breakParagraph(абзац(знаки, места))
    12. case Err(ошибка) => Err(ошибка)
    13. }
    14. match (итог) {
    15. case Ok(разбиения) => {
    16. io.writeLine("С учётом всего абзаца\n{строкиИз(знаки, разбиения.optimized)}\n")
    17. io.writeLine("Строка за строкой\n{строкиИз(знаки, разбиения.greedy)}")
    18. }
    19. case Err(ошибка) => io.writeLine("{ошибка}")
    20. }
    Ожидаемый вывод
    С учётом всего абзаца
    문단 전체를 보고
    줄을 나누면 마지막
    줄이 짧게 남지
    않고 줄마다 길이가
    고르게 됩니다.
    
    Строка за строкой
    문단 전체를 보고 줄을
    나누면 마지막 줄이
    짧게 남지 않고 줄마다
    길이가 고르게
    됩니다.

    Основная часть программы. Вспомогательные функции, которые задают ширину знаков и собирают абзац, есть в полном исходном коде.

    Разбиение абзаца

    Вы получаете разбиение с учётом всего абзаца и жадное разбиение строка за строкой. Модель стоимости можно выбрать между Knuth-Plass и моделью с фиксированной точкой.

    Правила переноса Юникода

    Места возможного разрыва строки находятся по алгоритму Юникода 16.0 (UAX #14).

    Правила для языков

    С корейскими (KLReq), японскими (JLReq) или китайскими (CLReq) правилами открывающая скобка не остаётся в конце строки, а закрывающая скобка и точка не начинают строку. Японские правила следуют классам символов JLReq.

    Ширина восточноазиатских символов

    Свойство Юникода East Asian Width помогает решить, где разрывать строку у кавычек и скобок рядом с китайскими, японскими и корейскими символами.

    Интервалы

    При выключке задаётся, насколько можно растянуть или сжать пробелы между латинскими словами и насколько можно растянуть интервалы между символами CJK.

    Единицы длины

    Длины 12pt, 3mm, 1cm, 1in и 1em записываются прямо в коде и переводятся из одних единиц в другие.

    Справочник std.typeset (на английском)

    ATLAS

    Инструмент вёрстки на Топазе

    ATLAS превращает рукопись в готовые к печати страницы книги. Ниже показаны страница, свёрстанная в ATLAS, и две функции проверки правил переноса, переписанные для Топаза 6.0. В ATLAS эти функции названы корейскими терминами вёрстки, здесь они переведены на русский.

    Страница 18 корейской книги, свёрстанной в ATLAS
    Страница 18 книги, свёрстанной в ATLAS

    atlas-ru.tpz
    1. function неЛатинскийПробел(следующий: Option<string>) -> bool {
    2. match (следующий) {
    3. case Some(текст) => !латинскийПробел(текст)
    4. case None() => true
    5. }
    6. }
    7. function безЗапретаВНачале(следующий: Option<string>) -> bool {
    8. match (следующий) {
    9. case Some(текст) => !запрещёнВНачале(текст)
    10. case None() => true
    11. }
    12. }
    Ожидаемый вывод
    false true
    false true

    Две функции проверки правил переноса ATLAS переписаны для Топаза 6.0 с русскими именами. Полный пример добавляет простые вспомогательные функции и входные данные для этих двух правил.

    Открыть ATLAS

    Почему Топаз хорошо справляется с вёрсткой

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

    Для частых задач есть один способ записи. Кто бы ни писал код, человек или агент, он выглядит одинаково, поэтому при проверке достаточно следить за тем, что код делает.

    Один способ записи

    Преобразование числа в строку и операции с коллекциями записываются как методы значений. Для массива используйте map, для числа toString. Исходный код форматирует topaz fmt.

    Операции с коллекциями (на английском)

    Отсутствие и сбой различаются

    Если значение может отсутствовать, функция возвращает Option, если операция может завершиться сбоем, она возвращает Result, а очистку ресурсов задаёт defer. В конце абзаца правило переноса получает None вместо следующего символа, и это не ошибка.

    Null, Option, Result и ошибки выполнения (на английском)

    Внешний мир виден в импортах

    Вывод на экран и чтение файлов используют импортируемые стандартные модули. По импортам при проверке кода сразу видно, где программа обменивается данными с внешним миром.

    Обзор стандартной библиотеки (на английском)

    Пропущенный случай остановит сборку

    Задайте фиксированный набор случаев, например классы разрыва строки, перечислением, и компилятор проверит, что каждое сопоставление match обрабатывает все варианты. Если позже добавить вариант, сборка покажет каждое сопоставление, которое его ещё не обрабатывает.

    Образцы и управление потоком (на английском)

    Переполнение останавливает программу сразу

    Тип int представляет знаковое 64-разрядное целое число. При переполнении программа останавливается на этом месте и не продолжает работу с неверным значением. Если считать ширину строк и стоимость раскладки в целых числах, переполнение не останется в результате незамеченным.

    Поведение среды выполнения (на английском)

    Одни правила на любой платформе

    Прямой запуск, нативные исполняемые файлы и пакеты для браузера следуют одним правилам языка. Поэтому предварительный просмотр на экране и вёрстка для печати разбивают строки в одних и тех же местах.

    Целевые платформы (на английском)

    Лиспекс

    Расчёт на Топазе, решения на Лиспексе

    Расчёты вроде разбиения на строки выполняет код на Топазе. Решения, которые меняются от издательства к издательству и от книги к книге, например с какой страницы начинать главу или сколько висячих строк допустимо, записываются отдельно в правилах Лиспекса. Топаз 6.0 выполняет правила Лиспекса 2.0 через std.lispex с отдельными лимитами подготовки, преобразования значений и вычисления. Замените исходный код правила и подготовьте его заново, и та же рукопись получит другой стиль без изменений в коде приложения.

    • Правила не обращаются к файлам, системным часам и сети.
    • Правило останавливается там, где превышает лимит.
    • Одинаковые правило, вход и настройки каждый раз дают одно и то же решение.
    lispex-ru.scm
    1. (define rule
    2. (lambda (input)
    3. (let ((min-lines 2))
    4. (if (< input min-lines) "перенести" "оставить"))))

    Файл lispex-ru.scm целиком

    lispex-ru.tpz
    1. import std.io
    2. import std.bigint { BigInt }
    3. import std.lispex {
    4. LispexPackage, LispexHostLimits, LispexPreparationLimits, LispexSource,
    5. LispexSourceBundle, PreparedLispexRule, LispexDatumView, LispexValue,
    6. applicationPackage, defaultLimits, prepare, valueFromDatum, valueView, evaluate,
    7. }
    8. export function main(args: Array<string>, stdin: string) -> Result<int, string> {
    9. let приложение = packageOf()?
    10. let пределы = defaultLimits()
    11. let правило = ruleFrom(приложение, stdin, пределы.preparation)?
    12. for осталосьСтрок in ([1, 2]) {
    13. let вход = numberOf(приложение, "{осталосьСтрок}", пределы.host)?
    14. let оценка = match (evaluate(правило, вход, пределы.evaluation)) {
    15. case Ok(значение) => значение
    16. case Err(_) => { return Err("The evaluation could not complete.") }
    17. }
    18. match (оценка.settlement) {
    19. case Complete(итог) => io.writeLine("осталось строк {осталосьСтрок} {textOf(итог, пределы.host)?}")
    20. case SemanticFailure(_) => { return Err("The rule returned a language failure.") }
    21. case LimitExhaustion(_) => { return Err("The rule reached its evaluation limit.") }
    22. }
    23. }
    24. return Ok(0)
    25. }
    Ожидаемый вывод
    осталось строк 1 перенести
    осталось строк 2 оставить

    Основная часть lispex-ru.tpz. В полном исходном коде есть вспомогательные функции подготовки и преобразования значений.

    Подготовьте правило с помощью prepare и выполните его с помощью evaluate.

    Открыть Лиспекс

    Сделано на Топазе

    И не только вёрстка

    Ядро компилятора Топаза написано на Топазе. На том же языке написаны и браузерные инструменты.

    compiler.tpz
    1. function assignmentRoot(node: SyntaxNode) -> Option<SyntaxNode> {
    2. if (node.kind == "expression/identifier") {
    3. return Some(node)
    4. }
    5. match (child(node, "object")) {
    6. case Some(object) => assignmentRoot(object)
    7. case None() => None()
    8. }
    9. }
    Ожидаемый вывод
    expression/identifier
    None

    Обход корня присваивания из compiler/crates/topaz_self_frontend/topaz/checker/expression_core.tpz переписан для Топаза 6.0

    Компилятор

    Имена и типы проверяет и код Rust генерирует код, написанный на Топазе. Команда topaz check проверяет программу, а topaz build создаёт исполняемый файл.

    Программы на Топазе

    Браузерные инструменты

    JSON-форматер на jeni.kr обрабатывает ввод парсером на Топазе и сообщает строку и столбец ошибки, если пропущена закрывающая скобка.

    Вызов из JavaScript (на английском)

    Обзор Топаза

    Выберите, куда идти дальше

    Меню

    Загрузка