doc: add stacks doc
This commit is contained in:
@@ -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`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user