From d22b4009b011a822a9fa3a42dfa9dfb261f23cc1 Mon Sep 17 00:00:00 2001 From: samsonium Date: Mon, 19 Oct 2026 17:24:40 +0300 Subject: [PATCH] doc: add stacks doc --- docs/ru/internals/stacks.md | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/docs/ru/internals/stacks.md b/docs/ru/internals/stacks.md index e516108..260c350 100644 --- a/docs/ru/internals/stacks.md +++ b/docs/ru/internals/stacks.md @@ -1,2 +1,102 @@ # Стеки виртуальной машины +Во время работы, виртуальная машина FZLang полагается на три стека: данных, окружений и вызовов. +Каждый стек инициализируется как массив из 256 значений, а затем зануляется. +Основное свойство, присущее всем трём стекам - последнее значение является верхом стека и сниматься в первую очередь должно оно, декрементируя указатель на вершину стека. + +## Стек данных + +Стек данных представляет из себя массив из 256 элементов типа `fzl_value_t`. +Структура `fzl_value_t` - это контейнер для хранения значений, используемых во время работы программы. + +```c +typedef struct +{ + fzl_type_t type; + + union + { + void *obj; + + struct + { + const char *value; + size_t length; + } s; + + char c; + bool b; + + int8_t i8; + uint8_t u8; + + int16_t i16; + uint16_t u16; + + int32_t i32; + uint32_t u32; + + int64_t i64; + uint64_t u64; + + intptr_t i; + uintptr_t u; + } as; +} fzl_value_t; +``` + +Стек используется во время работы программы виртуальной машиной, чтобы писать и читать промежуточные вычисления. +К концу работы программы, стек должен быть пуст. + +## Стек окружений + +Чтобы определять лексическое окружение, в котором на данный момент производятся вычисления и выполняются команды, используется стек окружений. +Стек окружений - это массив из 256 элементов типа `fzl_vm_env_t`. + +```c +typedef struct +{ + size_t size; + size_t remainder; + + fzl_vm_env_entry_t *table; + + fzl_vm_object_t **owned_objects; + size_t owned_objects_remainder; + size_t owned_objects_count; +} fzl_vm_env_t; +``` + +Каждый элемент стека хранит таблицу локальных имён `fzl_vm_env_entry_t`, а также объекты, которые принадлежат текущему окружению. +Локальное имя - это контейнер, оборачивающий `fzl_value_t` и дающий ему имя: + +```c +typedef struct +{ + char *name; + fzl_value_t value; +} fzl_vm_env_entry_t; +``` + +Объект же представляет из себя массив полей, хранимых в этом объекте. +Количество элементов определется при аллокации объекта (опкод `FZL_OPCODE_ALLOC_OBJECT N`, подробнее - в [описании опкодов](./opcodes.md)). + +```c +typedef struct +{ + fzl_value_t *values; + size_t values_count; +} fzl_vm_object_t; +``` + +Создание окружения или выход из него происходит при опкодах `FZL_OPCODE_MK_ENVTABLE` и `FZL_OPCODE_RM_ENVTABLE` соответственно. +При этом, если компилятор видит возвращаемое из функции значение типа `FZL_TYPE_OBJECT`, то перед опкодами `FZL_OPCODE_RET` и `FZL_OPCODE_RM_ENVTABLE` он вставляет `FZL_OPCODE_ESCAPE_OBJECT`, +которое позволяет переместить владение объектом в родительское окружение. + +## Стек возврата + +Стек возврата хранит адреса инструкций при входе в функцию (через опкод `FZL_OPCODE_CALL`). +Опкод `FZL_OPCODE_RET` снимает адрес со стека вызовов и прыгает на снятый адрес. + +Сам по себе стек представляет из себя 256 элементов типа `size_t`. +