# 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.