Files
fz-lang/docs/en/internals/stacks.md

93 lines
2.6 KiB
Markdown

# Virtual machine stacks
While running, the FZLang virtual machine relies on three stacks: the data stack, the environment stack, and the call stack. Each stack is initialized as an array of 256 values and then zeroed. All three share the same basic property: the most recently added value is at the top and is the first one removed, decrementing the stack-top pointer.
## Data stack
The data stack is an array of 256 `fzl_value_t` elements. The `fzl_value_t` structure is a container for values used while a program runs.
```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;
```
The VM uses this stack to store and retrieve intermediate values while the program runs. The stack should be empty when execution finishes.
## Environment stack
The environment stack tracks the lexical environment in which evaluation and instructions are currently taking place. It is an array of 256 `fzl_vm_env_t` elements.
```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;
```
Each stack element stores a table of local names (`fzl_vm_env_entry_t`) and the objects owned by the current environment. A local name is a container that wraps an `fzl_value_t` and gives it a name:
```c
typedef struct
{
char *name;
fzl_value_t value;
} fzl_vm_env_entry_t;
```
An object is an array of its fields. The number of fields is set when the object is allocated by the `FZL_OPCODE_ALLOC_OBJECT N` opcode (see the [opcode reference](./opcodes.md) for details).
```c
typedef struct
{
fzl_value_t *values;
size_t values_count;
} fzl_vm_object_t;
```
An environment is created or removed by the `FZL_OPCODE_MK_ENVTABLE` and `FZL_OPCODE_RM_ENVTABLE` opcodes, respectively. If the compiler sees a value of type `FZL_TYPE_OBJECT` being returned from a function, it inserts `FZL_OPCODE_ESCAPE_OBJECT` before `FZL_OPCODE_RET` and `FZL_OPCODE_RM_ENVTABLE`. This moves ownership of the object to the parent environment.
## Call stack
The call stack stores instruction addresses when entering a function through the `FZL_OPCODE_CALL` opcode. `FZL_OPCODE_RET` pops an address from the call stack and jumps to it.
The stack itself is an array of 256 `size_t` elements.