From 81d07aa6e54243858aa201ecb05576e13f62790c Mon Sep 17 00:00:00 2001 From: samsonium Date: Mon, 19 Oct 2026 11:11:43 +0300 Subject: [PATCH] doc: add book,internal,reference,builtins sections --- docs/ru/book/01_getting-started.md | 3 +- docs/ru/book/02_basics-and-types.md | 53 ++++++++++++++++++++++ docs/ru/book/03_control-flow.md | 43 ++++++++++++++++++ docs/ru/book/04_functions-and-recursion.md | 44 ++++++++++++++++++ docs/ru/book/05_classes-and-objects.md | 46 +++++++++++++++++++ docs/ru/book/06_memory-model.md | 36 +++++++++++++++ docs/ru/internals/object_layout.md | 21 +++++++++ docs/ru/internals/stacks.md | 24 ++++++++++ docs/ru/philosopy.md | 31 +++++++++++++ docs/ru/reference/compiler_cli.md | 19 ++++++++ docs/ru/reference/grammar_ebnf.md | 33 ++++++++++++++ docs/ru/reference/operators.md | 17 +++++++ docs/ru/reference/types_system.md | 22 +++++++++ docs/ru/stdlib/builtins.md | 30 ++++++++++++ 14 files changed, 420 insertions(+), 2 deletions(-) create mode 100644 docs/ru/book/02_basics-and-types.md create mode 100644 docs/ru/book/03_control-flow.md create mode 100644 docs/ru/book/04_functions-and-recursion.md create mode 100644 docs/ru/book/05_classes-and-objects.md create mode 100644 docs/ru/book/06_memory-model.md create mode 100644 docs/ru/internals/object_layout.md create mode 100644 docs/ru/internals/stacks.md create mode 100644 docs/ru/philosopy.md create mode 100644 docs/ru/reference/compiler_cli.md create mode 100644 docs/ru/reference/grammar_ebnf.md create mode 100644 docs/ru/reference/operators.md create mode 100644 docs/ru/reference/types_system.md create mode 100644 docs/ru/stdlib/builtins.md diff --git a/docs/ru/book/01_getting-started.md b/docs/ru/book/01_getting-started.md index fd30a64..b489371 100644 --- a/docs/ru/book/01_getting-started.md +++ b/docs/ru/book/01_getting-started.md @@ -41,7 +41,6 @@ Available flags: --- -Далее: [Первая программа](./02_first-program.md) +Далее: [Основы и типы](./02_basics-and-types.md) Назад: [Вступление](./00_introduction.md) - diff --git a/docs/ru/book/02_basics-and-types.md b/docs/ru/book/02_basics-and-types.md new file mode 100644 index 0000000..d646f6c --- /dev/null +++ b/docs/ru/book/02_basics-and-types.md @@ -0,0 +1,53 @@ +# Основы и типы + +В этой главе разберём выражения, переменные и значения FZLang. +Исходный код хранится в файлах с расширением .fzs, а каждая инструкция обычно заканчивается точкой с запятой. + +## Литералы + +Числа записываются последовательностью десятичных цифр. +Строки заключаются в одинарные или двойные кавычки, булевы значения — `true` и `false`, пустое значение для объектов — `null`. + +``` +int answer = 42; +str greeting = "hello"; +bool enabled = true; +``` + +## Объявление и присваивание + +Тип указывается перед именем переменной. Инициализация необязательна: + +``` +uint work_it = 21 * 2 ^ 2; +int make_it = 10; +u64 do_it; +do_it = 15; +``` + +Поддерживаются машинные `int` и `uint`, знаковые `i8`, `i16`, `i32`, `i64`, беззнаковые `u8`, `u16`, `u32`, `u64`, а также `str`, `char` и `bool`. +Имена классов используются как типы объектов. + +## Арифметика и логика + +Доступны операции +, -, *, /, %, ^, сравнения ==, !=, <, <=, >, >= и логические операции &&, ||, !. +Порядок разбора: унарные операции, степень, умножение/деление/остаток, сложение/вычитание, сравнения, &&, затем ||. +Скобки меняют порядок вычисления. + +Строки поддерживают == и !=, объекты сравниваются по идентичности экземпляра. +Несовместимые типы отклоняются компилятором. + +## Комментарии + +Однострочный комментарий начинается с // и продолжается до конца строки. + +``` +// Этот текст игнорируется компилятором +printline("Комментарий пропущен"); +``` + +--- + +Далее: [Управление потоком](./03_control-flow.md) + +Назад: [Начало работы](./01_getting-started.md) diff --git a/docs/ru/book/03_control-flow.md b/docs/ru/book/03_control-flow.md new file mode 100644 index 0000000..74f82b6 --- /dev/null +++ b/docs/ru/book/03_control-flow.md @@ -0,0 +1,43 @@ +# Управление потоком + +FZLang поддерживает условные конструкции и отдельные блоки кода. +Условия записываются в круглых скобках, тело может быть одной инструкцией или блоком в фигурных скобках. + +## Условие if + +``` +if (2 + 2 >= 4) + printline("two plus two is four"); +else +{ + printline("unexpected result"); + exit(1); +} +``` + +Ветка `else if` является обычным `else`, за которым следует новый `if`. +Условие вычисляется, после чего ВМ переходит в одну из веток; обычно это булево значение или результат сравнения. + +## Блоки + +Фигурные скобки создают отдельное окружение: + +``` +{ + int local = 10; + printline(local); +} +``` + +После выхода из блока его окружение уничтожается. +Локальные имена не должны использоваться за пределами блока. + +## Ограничения + +В текущей реализации нет циклов while или for. Повторяющееся вычисление выражается рекурсивными функциями. + +--- + +Далее: [Функции и рекурсия](./04_functions-and-recursion.md) + +Назад: [Основы и типы](./02_basics-and-types.md) diff --git a/docs/ru/book/04_functions-and-recursion.md b/docs/ru/book/04_functions-and-recursion.md new file mode 100644 index 0000000..b530b38 --- /dev/null +++ b/docs/ru/book/04_functions-and-recursion.md @@ -0,0 +1,44 @@ +# Функции и рекурсия + +Функция объявляется ключевым словом `fn`, именем, списком типизированных аргументов и, если функция возвращает значение, типом результата. + +``` +fn sum(uint a, uint b) uint +{ + return a + b; +} +``` + +Если функция ничего не возвращает, тип после закрывающей скобки можно опустить. +Вызов записывается как `name(arg1, arg2)`, аргументы передаются в порядке объявления. + +## Возврат + +return завершает текущую функцию. +Возвращаемое выражение должно быть совместимо с объявленным типом. +Пустой return; используется в функции без результата. +Возврат вне функции — ошибка компиляции. + +## Рекурсия + +Функция может вызывать саму себя: + +``` +fn factorial(uint n) uint +{ + if (n <= 1) + return 1; + return n * factorial(n - 1); +} +``` + +Каждый вызов получает собственное окружение. +ВМ хранит адрес возврата в стеке вызовов, а локальные значения — в стеке окружений. + +При возврате объекта компилятор переносит его владение в родительское окружение. + +--- + +Далее: [Классы и объекты](./05_classes-and-objects.md) + +Назад: [Управление потоком](./03_control-flow.md) diff --git a/docs/ru/book/05_classes-and-objects.md b/docs/ru/book/05_classes-and-objects.md new file mode 100644 index 0000000..977d2c1 --- /dev/null +++ b/docs/ru/book/05_classes-and-objects.md @@ -0,0 +1,46 @@ +# Классы и объекты + +Класс описывается блоком с полями и методами: + +``` +class Point +{ + int x; + int y; + + fn move(int dx, int dy) + { + this.x = this.x + dx; + this.y = this.y + dy; + } +} +``` + +Методы обращаются к полям текущего экземпляра через обязательное имя `this`. + +## Создание экземпляра + +Экземпляр создаётся выражением `new ClassName`: + +``` +Point point = new Point; +point.x = 1; +point.y = 2; +point.move(9, 8); +``` + +Объект выделяется с количеством слотов, равным числу полей класса. +Поля читаются и изменяются через точку. +Поддерживаются цепочки вроде `list.next.sum()`. + +Имя класса выступает типом объекта. +Переменная может содержать `null`, а объекты одного класса совместимы между собой. +Сравнение == и != проверяет идентичность экземпляра, а не содержимое полей. + +Неизвестный класс или поле приводит к ошибке компиляции. + +--- + +Далее: [Модель памяти](./06_memory-model.md) + +Назад: [Функции и рекурсия](./04_functions-and-recursion.md) diff --git a/docs/ru/book/06_memory-model.md b/docs/ru/book/06_memory-model.md new file mode 100644 index 0000000..ad0236e --- /dev/null +++ b/docs/ru/book/06_memory-model.md @@ -0,0 +1,36 @@ +# Модель памяти + +FZLang использует scope-based RAII: объект принадлежит окружению, в котором создан, и освобождается при уничтожении этого окружения. +Отдельного сборщика мусора нет. + +## Окружения + +Глобальная программа, функция и каждый блок получают окружение. +В нём хранятся имена и значения переменных. +При поиске имени VM проверяет текущее окружение, затем внешние. + +После return локальное окружение функции закрывается. +Возвращаемый объект переносится в родительское окружение, чтобы пережить этот момент. + +## Владение объектом + +Передача объекта во вложенный вызов позволяет использовать его во внутреннем окружении. +Операция `ESCAPE_OBJECT` переносит возвращаемый объект и его дочерние объекты наружу. + +``` +fn make() Animal +{ + Animal result = new Animal; + return result; +} +``` + +Числа, булевы значения и строки хранятся как значения контейнера ВМ. +Объектное значение содержит указатель на структуру экземпляра, а поля занимают числовые слоты класса. + +Объект не следует использовать после завершения окружения, которому он принадлежал. +Возвращайте его из функции или храните в объекте/окружении с большим временем жизни. + +--- + +Назад: [Классы и объекты](./05_classes-and-objects.md) diff --git a/docs/ru/internals/object_layout.md b/docs/ru/internals/object_layout.md new file mode 100644 index 0000000..9257b19 --- /dev/null +++ b/docs/ru/internals/object_layout.md @@ -0,0 +1,21 @@ +# Размещение объектов + +Экземпляр класса во время исполнения представлен структурой объекта с массивом значений полей: + +``` +typedef struct +{ + fzl_value_t *values; + size_t values_count; +} fzl_vm_object_t; +``` + +Поля получают последовательные индексы в порядке объявления. +Таблица класса хранит имя поля, тип и `slot_index`. +Поэтому `object.field` компилируется в `GET_FIELD` или `SET_FIELD` с числовым индексом. + +Выражение `new ClassName` проверяет наличие класса и генерирует `ALLOC_OBJECT N`, где `N` — число полей. +Сравнение объектов проверяет указатели. +При уничтожении окружения освобождаются принадлежащие ему объекты и массивы их значений. + +При возврате объекта из вложенного окружения `ESCAPE_OBJECT` переносит владение в родительское окружение. diff --git a/docs/ru/internals/stacks.md b/docs/ru/internals/stacks.md new file mode 100644 index 0000000..9d95e41 --- /dev/null +++ b/docs/ru/internals/stacks.md @@ -0,0 +1,24 @@ +# Стеки виртуальной машины + +ВМ использует три фиксированных стека по 256 элементов. + +## Стек данных + +`dstack` хранит значения `fzl_value_t`: числа, строки, булевы значения, ссылки на объекты и null. +`PUSHNUM`, `PUSHBOOL` и `LOADCONST` помещают значения на стек. +Арифметические и логические операции снимают операнды и кладут результат обратно. + +## Стек вызовов + +`cstack` хранит адреса возврата. +`CALL` сохраняет текущий адрес и переходит к функции, +`RET` снимает последний адрес. +Рекурсивные вызовы используют отдельные записи. + +## Стек окружений + +`estack` хранит таблицы имён и владельцев объектов. +`MK_ENVTABLE` создаёт окружение, `RM_ENVTABLE` уничтожает его, `STORE` добавляет имя, `LOOKUP_ENV` ищет значение, `WRITE` изменяет переменную. +`ESCAPE_OBJECT` переносит возвращаемый объект перед закрытием окружения. + +Запуск `fz -d program.fzb` печатает декодированную последовательность опкодов и аргументов. diff --git a/docs/ru/philosopy.md b/docs/ru/philosopy.md new file mode 100644 index 0000000..de81ddc --- /dev/null +++ b/docs/ru/philosopy.md @@ -0,0 +1,31 @@ +# Философия языка + +Язык FZLang преследует две цели при разработке: "быть удобным, как инструмент, но всегда оставаться предсказуемым". + +Вот, какими путями язык пытается достичь этой философии: + +## В отношении к памяти и ресурсам + +В средах с GC программист точно не знает, в какой момент сборщик мусора решит произвести очистку: +объект может висеть секундами после завершения метода. +А в момент очистки рантайм может устроить микропаузу, что критично для аудио, игр, сети или встроенных систем. + +В модели scope-based RAII, которая используется в том числе в FZLang, память детерминирована. +Любой объект имеет область, которая им владеет, а как только область уничтожается - объект уничтожается вместе с ней. +Время отклика таком подходе равное и предсказуемое. + +Ещё один плюс, который предоставляет модель scope-based RAII - это работа с ресурсами (сокеты, файлы). +Проблема освобождения ресурсов решается чистой семантикой области видимости: умирает скоуп - очищается всё, что к нему привязано. + +И последним аргументом в сторону scope-based RAII стало отстутствие оверхеда на рантайм. +Полноценному GC для работы нужны карты памяти, фоновые потоки, барьеры чтения и записи. +В FZLang виртуальная машина весит очень мало, а вся память освобождается по ходу чтения инструкций. + +## В отношении синтаксиса + +Язык FZLang намеренно не упрощается некоторые детали синтаксиса. +Например, при обращении к экземпляру класса в его методах, использование `this` является обязательным, как и указание типов при декларациях, - это строгая часть. +Однако, объявление функции без возвращаемого типа позволяет опускать тип, так как писать на месте типа постоянно `void` было бы избыточно. + +Таким образом, FZLang старается балансировать между синтаксисом, позволяющим оставаться языку детерминированным и упрощениями, которые действительно уместны. + diff --git a/docs/ru/reference/compiler_cli.md b/docs/ru/reference/compiler_cli.md new file mode 100644 index 0000000..e1bed37 --- /dev/null +++ b/docs/ru/reference/compiler_cli.md @@ -0,0 +1,19 @@ +# Интерфейс компилятора + +Компилятор называется `fzc`. +Он принимает исходные файлы `.fzs` и создаёт бинарный файл `.fzb`. + +``` +fzc [flags] +``` + +| Флаг | Назначение | +| ------------- | ---------------------------------------------- | +| -h, --help | Показать справку | +| -v, --verbose | Вывести токены, AST, таблицу констант и опкоды | +| -V, --version | Показать версию | +| -o, --out | Задать имя выходного файла | + +Если `-o` не задан, результат записывается в `a.fzb`. Пример: `fzc -v -o hello.fzb exl/hw.fzs`. + +VM запускается командой `fz [flags] `. Флаг `-d` или `--debug` печатает опкоды, не выполняя программу. diff --git a/docs/ru/reference/grammar_ebnf.md b/docs/ru/reference/grammar_ebnf.md new file mode 100644 index 0000000..4a1d2ab --- /dev/null +++ b/docs/ru/reference/grammar_ebnf.md @@ -0,0 +1,33 @@ +# Грамматика (EBNF) + +Упрощённая грамматика текущего парсера: + +``` +program = { statement } ; +statement = class | function | if | block | return | expression ";" ; +block = "{" { statement } "}" ; +class = "class" name "{" { declaration | function } "}" ; +function = "fn" name "(" [ parameters ] ")" [ type-name ] statement ; +parameters = parameter { "," parameter } ; +parameter = type-name name ; +return = "return" [ expression ] ";" ; +if = "if" "(" expression ")" statement [ "else" statement ] ; +expression = assignment ; +assignment = new-expression [ "=" assignment ] ; +new-expression = logical-or | "new" name ; +logical-or = logical-and { "||" logical-and } ; +logical-and = comparison { "&&" comparison } ; +comparison = term { compare-op term } ; +term = factor { ( "+" | "-" ) factor } ; +factor = power { ( "*" | "/" | "%" ) power } ; +power = unary [ "^" unary ] ; +unary = ( "+" | "-" | "!" ) unary | postfix ; +postfix = primary { call | member } ; +call = "(" [ expression { "," expression } ] ")" ; +member = "." name ; +primary = literal | declaration | name | "(" expression ")" ; +declaration = type-name name ; +type-name = builtin-type | name ; +``` + +`literal` включает строковый, числовой, булев и `null` литералы. Комментарии `// ...` и пробельные символы между токенами игнорируются. diff --git a/docs/ru/reference/operators.md b/docs/ru/reference/operators.md new file mode 100644 index 0000000..220ce66 --- /dev/null +++ b/docs/ru/reference/operators.md @@ -0,0 +1,17 @@ +# Операторы + +| Оператор | Назначение | +| -------------------- | -------------------------------------- | +| +, - | Сложение/вычитание, унарные плюс/минус | +| *, /, % | Умножение, деление, остаток | +| ^ | Возведение в степень | +| ==, !=, <, <=, >, >= | Сравнение | +| ! | Логическое отрицание | +| &&, || | Логические И и ИЛИ | +| = | Присваивание | +| . | Доступ к полю и методу | + +Для строк и объектов доступны только `==` и `!=`. +Ключевое слово `new` создаёт экземпляр класса: `new Point`. + +Приоритет от большего к меньшему: унарные операции; ^; *, /, %; +, -; сравнения; &&; ||; =. Скобки имеют высший приоритет. diff --git a/docs/ru/reference/types_system.md b/docs/ru/reference/types_system.md new file mode 100644 index 0000000..65aceeb --- /dev/null +++ b/docs/ru/reference/types_system.md @@ -0,0 +1,22 @@ +# Система типов + +| Типы | Значение | +| ----------------- | ---------------------------------------- | +| int, uint | Целое машинного размера | +| i8, i16, i32, i64 | Знаковые целые фиксированного размера | +| u8, u16, u32, u64 | Беззнаковые целые фиксированного размера | +| str | Строка | +| char | Символ | +| bool | Булево значение | +| ClassName | Экземпляр пользовательского класса | + +Также существует `null`, применимое к объектным значениям. +Тип указывается при объявлении переменной, поля и аргумента функции. + +Объект совместим с объектом того же класса или с `null`. +Объекты разных классов несовместимы. +Строки поддерживают `==` и `!=`, объекты сравниваются по ссылке. +Поля класса имеют объявленные типы и последовательные слоты. + +Для функции тип результата указывается после списка параметров. +Для функции без результата его можно опустить. diff --git a/docs/ru/stdlib/builtins.md b/docs/ru/stdlib/builtins.md new file mode 100644 index 0000000..74d5417 --- /dev/null +++ b/docs/ru/stdlib/builtins.md @@ -0,0 +1,30 @@ +# Встроенные функции + +Встроенные функции распознаются компилятором по имени и исполняются ВМ напрямую. + +## printline + +Выводит аргумент в стандартный вывод и добавляет перевод строки: + +``` +printline("hello, world"); +printline(42); +``` + +Вызов без аргументов считается ошибкой компиляции. +Функция используется для строк, чисел, булевых значений и объектов. + +## exit + +Завершает программу с указанным кодом возврата: + +``` +if (failed) +{ + printline("Test failed"); + exit(1); +} +``` + +Код передаётся одним аргументом. +Ненулевой код обычно означает ошибку.