О проекте

Переход на 5.21

Смените языковой режим, замените каждую удалённую в 5.21 форму методом значения или вызовом модуля std и проверьте результат. Исходный код до v5 описан в последнем разделе.

Топаз 5.21 удаляет глобальные функции вроде print, статические пространства имён вроде Math и FS и шесть стандартных модулей. Их вызовы переходят в методы значений и модули std. Сначала смените языковой режим, а затем исправляйте удалённые формы в тех местах, на которые укажет topaz check.

Установите Топаз и сохраните копии исходного кода, входных данных и результатов.

Смените языковой режим

В topaz.toml задайте для language и std значение "5.21".

TOML
[package]
language = "5.21"

[dependencies]
std = "5.21"

Топаз 5.21 принимает только языковой режим topaz-5.21. Пакет, оставшийся в языковом режиме 5.20, останавливается с ошибкой unsupported language mode. Отдельный файл без topaz.toml уже проверяется по правилам 5.21.

Найдите удалённые формы

Этот файл всё ещё вызывает print, удалённый в 5.21.

print("ready")

Сохраните его как old-forms.tpz и проверьте.

BASH
topaz check old-forms.tpz

Для удалённого вызова, как print здесь, средство проверки сообщает TPZ5002 и называет вызов для 5.21. Для импорта удалённого стандартного модуля, например import std.math, оно сообщает TPZ3001 и называет методы, которые его заменяют.

Вывод
error[TPZ5002]: `print` is not bound; import std.io and use io.writeLine(value) in 5.21
 --> old-forms.tpz:1:1
  |
1 | print("ready")
  | ^^^^^

old-forms.tpz: 1 type diagnostic

Исправьте файл по сообщению и сохраните его снова.

TOPAZ
import std.io

io.writeLine("ready")

Теперь topaz check old-forms.tpz завершается успешно, а topaz run old-forms.tpz печатает ready.

Замените удалённые формы

Замените форму из первого столбца формой из второго. Если в третьем столбце указан импорт, добавьте его один раз в начало файла.

Удалено в 5.21Что писать вместоСначала импортируйте
print(x)io.writeLine(x)import std.io
input()io.readStdin()import std.io
open(p)io.open(p)import std.io
assert(c)test.assert(c)import std.test
map(xs, f), filter(xs, f), reduce(xs, z, f)xs.map(f), xs.filter(f), xs.reduce(z, f)
toFloat(n), toInt(s), toIntRadix(s, r), fromCodePoint(n)n.toFloat(), s.toInt(), s.toIntRadix(r), n.toCodePoint()
Math.sqrt(x), Math.abs(x), Math.sin(x), Math.cos(x), Math.tan(x), Math.isNaN(x), Math.isFinite(x)x.sqrt(), x.abs(), x.sin(), x.cos(), x.tan(), x.isNaN(), x.isFinite()
Math.floor(x), Math.ceil(x), Math.round(x)x.floor(), x.ceil(), x.round()
Math.parseFloat(s)s.parseFloat()
Math.min(a, b), Math.max(a, b)a.atMost(b), a.atLeast(b)
JSON.parse(s), JSON.stringify(v), JSON.parseAs<T>(s)json.parse(s), json.stringify(v), json.parseAs<T>(s)import std.json
JSON.decode<T>(v)v.decode<T>()
FS.readText(p), FS.writeText(p, text), FS.readBytes(p), FS.writeBytes(p, bytes), FS.list(p)fs.readText(p), fs.writeText(p, text), fs.readBytes(p), fs.writeBytes(p, bytes), fs.list(p)import std.fs
CSV.parse(s), CSV.parseWithHeader(s), CSV.stringify(rows), CSV.stringifyWithHeader(rows, columns)csv.parse(s), csv.parseWithHeader(s), csv.stringify(rows), csv.stringifyWithHeader(rows, columns)import std.csv
TOML.parse(s), TOML.stringify(v), TOML.fromJson(v)toml.parse(s), toml.stringify(v), toml.fromJson(v)import std.toml
TOML.toJson(t)t.toJson()
Test.assert(c), Test.assertEq(a, b), Test.assertNe(a, b), Test.assertContains(text, part)test.assert(c), test.assertEq(a, b), test.assertNe(a, b), test.assertContains(text, part)import std.test
Test.assertOk(result), Test.assertErr(result), Test.assertSome(option), Test.assertNone(option), Test.assertGolden(name, actual)test.assertOk(result), test.assertErr(result), test.assertSome(option), test.assertNone(option), test.assertGolden(name, actual)import std.test
Encoding.utf8Encode(s), Encoding.utf8Decode(b)s.encodeUtf8(), b.decodeUtf8()
Encoding.hexEncode(b), Encoding.hexDecode(s)b.toHex(), Bytes.fromHex(s)
Encoding.base64Encode(b), Encoding.base64Decode(s)b.toBase64(), Bytes.fromBase64(s)
Hash.sha256(b), Hash.sha512(b), Hash.crc32(b)b.sha256(), b.sha512(), b.crc32()
Hash.hmacSha256(key, data)key.hmacSha256(data)
Codec.gzipCompress(b), Codec.gzipDecompress(b), Codec.deflateCompress(b), Codec.deflateDecompress(b)b.gzipCompress(), b.gzipDecompress(), b.deflateCompress(), b.deflateDecompress()
Codec.deflateFixedCompress(b), Codec.zlibFixedCompress(b), Codec.reedSolomon255223Protect(b)b.deflateFixedCompress(), b.zlibFixedCompress(), b.reedSolomon255223Protect()
Codec.zstdCompress(b, level), Codec.zstdDecompress(b)b.zstdCompress(level), b.zstdDecompress()
Cli.hasFlag(args, name), Cli.option(args, name), Cli.options(args, name), Cli.positionals(args)args.hasFlag(name), args.option(name), args.options(name), args.positionals()
Array.of(a, b)[a, b]
Set.of(a, b)set { a, b }
Map.new()map {}
Bytes.encodeUtf8(s), Bytes.concat(a, b)s.encodeUtf8(), a.concat(b)
BigInt.fromInt(n), Decimal.fromInt(n)n.toBigInt(), n.toDecimal()
import std.math, import std.encoding, import std.hash, import std.codec, import std.cliУдалите импорт и вызывайте методы из строк выше
import std.gen[for x in lo..hi => x], [false, true]
topaz lispex runlispex run для исходников Лиспекса, topaz lispex embed run для встроенного вычислителя
topaz lispex infotopaz lispex embed info

x.floor(), x.ceil(), x.round() и x.trunc() возвращают int. Если нужно вещественное число, как у Math.floor(x), пишите x.floor().toFloat() и так же поступайте с ceil и round. Новое преобразование в целое проверяет диапазон результата.

std.bytes, std.path, std.regex, std.url, std.date, std.bigint и std.decimal экспортируют только типы. Их функции вызываются как методы значений или как функции типов, например Bytes.fromHex.

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

Перенесите исходный код, написанный до v5

Перенесите исходный код Топаза, написанный до v5, на текущий синтаксис вручную. Сохраняйте прежнее поведение и сравнивайте результаты после каждого изменения. Совместимые обновления продукта не требуют отдельного переноса исходников.

Перенесите один файл

В этом историческом примере использованы старые формы объявления и типа массива.

mut let имена: [string] = ["Ada"]
let первое = имена[0]

Сохраните приведённый ниже код с текущим синтаксисом в рабочей папке как from-pre-v5.tpz.

TOPAZ
import std.io

let mut имена: Array<string> = ["Ada"]
let первое: Option<string> = имена.get(0)
io.writeLine("{первое}")

Выполните эти команды из той же папки.

BASH
topaz check from-pre-v5.tpz
topaz run from-pre-v5.tpz

Проверка завершается с кодом 0. Запуск также завершается с кодом 0 и печатает следующий результат.

Вывод
Some(Ada)

имена.get(0) возвращает Option<string>. Первый элемент существует, поэтому результат равен Some(Ada). Индекс вне массива возвращает None. Прямая индексация массива также поддерживается и вызывает ошибку выполнения при выходе за границы. Выберите нужное программе поведение.

В документации помещайте старый код в блок text. Для текущего синтаксиса используйте блок topaz.

Запишите поведение перед изменением проекта

Запишите входные файлы, корни модулей, входные данные, ожидаемый вывод, ошибки выполнения, файловые и сетевые действия. Сохраните результаты запусков для сравнения. Отделите примеры на Rust, JavaScript и синтаксисе фреймворков от исходников Топаза.

Приведите исходный код и метаданные пакета к текущему режиму языка. Настройки пакета описаны в разделе Пакеты и зависимости. Прежний синтаксис смотрите в Классике, а нужную сейчас форму ищите в текущем руководстве.

Замените повторяющиеся формы

Старая формаТекущая формаЧто сохранить
mut let xlet mut xВозможность повторного присваивания привязке
[T]Array<T>Тип элемента
function(T) -> U(T) -> UТипы параметра и результата
[head, ...tail][head, ..tail]Остаток элементов в шаблоне списка
args: ...T...args: TТип вариативного аргумента
Анонимная function(x: T) => exprПараметры, результат и захваченные привязки
s[i], s.lengths.scalars() и явные строковые APIПозиции и количество скаляров Unicode
Обратные кавычки, ${expr}Двойные кавычки, {expr}Содержимое строки и интерполяцию

Скаляр Unicode представляет одно значение Unicode и может отличаться от байта или видимого символа. Индексация и зарегистрированные теги шаблонов описаны в разделе Строки и шаблоны. Используйте self в тех местах, где его допускает текущее объявление метода.

Для обрабатываемых ошибок используйте Result, для отсутствующих значений используйте Option или тип с null. Различайте ошибки выполнения и возвращаемые значения ошибок. Перенесите очистку в defer или поддерживаемые конструкции using. Обновите import, export, видимость и инициализацию по разделу Модули и видимость.

Код других языков оставляйте в явно обозначенных шагах сборки или преобразования. Вставлять его в модуль Топаза как синтаксис Топаза нельзя.

Сравните переписанную программу

Выполните topaz check для изменённого исходника, затем запустите тесты проекта. Для файла выше сравните вывод с Some(Ada). Для проекта сравните сохранённые входные данные и результаты.

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

Соберите программу для нужных нативных сред, Web или Worker по разделу Результат сборки. Неподдерживаемые формы должны вызывать диагностику до создания результата сборки. Перенос завершён, когда проверки и тесты проходят, а каждая выбранная сборка ведёт себя ожидаемым образом.

Связанная документация