# Вывод ошибок Если во время работы программы происходит ошибка рантайма, то ВМ выводит своё состояние на момент остановки. Среди выводимой информации есть: 1. Указатель на адрес инструкции; 2. Стек данных; 3. Стек окружений; 4. Стек вызовов. ## Указатель на адрес инструкции (IP) Он может быть полезен для отладки, в паре с выводом опкодов программы. Если подать в ВМ флаг `--debug` (`-d`) вместе с путём к скомпилированной программой, то ВМ выведет список опкодов программы без её запуска. Выглядит вывод программы примерно так: ``` 0000: MK_ENVTABLE 0001: JMP IP: 53 0003: MK_ENVTABLE 0004: LOADCONST #0 ('a') 0006: STORE 0007: LOADCONST #0 ('a') 0009: WRITE 0010: MK_ENVTABLE 0011: LOADCONST #0 ('a') 0013: LOOKUP_ENV 0014: GET_FIELD #0 ... ``` Порядковый номер позволяет быстро найти инструкцию, на которой произошло исключение. Полный список опкодов и их описание можно найти в документе [списка опкодов](../internals/opcodes.md). ## Стек данных Стек данных выводится как список значений в стиле `[T] V`, где `T` - номер типа, `V` - значение. Если значение является строкой или объектом, то в начале дописывается `str: V` и `ref: V` соответственно. Вот, как выглядит пример вывода стека: ``` > Data stack: > [2] str: 'this' ``` Важно учесть, что значения выводятся сверху вниз. То есть, первыми будут выведены самые свежие значения. ## Стек окружения Стек окружения выводится как два списка: объекты во владении и локальные для окружения имена. Пример окружения: ``` > Environments: > [1] 0x55a9d8196a20: > Owned objects (0/2): > Local entries (3/4): > [14] b = 4 > [1] a = ref 0x55a9d81969e0 > [0] this = 0 > [0] 0x55a9d8196930: > Owned objects (1/2): > ref: 0x55a9d81969e0 (entries: 1) > Local entries (1/2): > [1] sum = ref 0x55a9d81969e0 ``` `> [N] A` - это сама таблица окружения. `N` - это уровень таблицы, который тем выше, чем глубже само окружение. `A` - это адрес таблицы в памяти. Внутри идёт первый список - "Owned objects", с указанием количества элементов и аллоцированным размером массива `(<кол-во>/<размер>)`. Перечисление объектов идёт форматом `ref: A (entries: N)`, где `A` - адрес объекта в памяти, `N` - количество хранимых полей. Далее идёт список локальных имён - "Local entries", с таким же указанием количества элементов к аллоцированному размеру. Формат элемента - `[T] N = V`, где `T` - номер типа, `N` - имя элемента, а `V` - его значение. ## Стек вызовов На стеке вызовов лежат точки возврата, которые попадают на стек при инструкции `CALL` и съедаются инструкцией `RET`. ``` > Call stack: > [0] 53 ``` Формат записи простой: `[L] IP`, где `L` - уровень вложенности (больше = глубже), а `IP` - указатель на номер инструкции, на которую нужно прыгнуть после возврата. ## Полный вывод Итого, полный вывод ошибки выглядит следующим образом: ``` ===== ERROR ===== > Caused on IP: 21 > Data stack: > [2] str: 'this' > Environments: > [1] 0x55a9d8196a20: > Owned objects (0/2): > Local entries (3/4): > [14] b = 4 > [1] a = ref 0x55a9d81969e0 > [0] this = 0 > [0] 0x55a9d8196930: > Owned objects (1/2): > ref: 0x55a9d81969e0 (entries: 1) > Local entries (1/2): > [1] sum = ref 0x55a9d81969e0 > Call stack: > [0] 53 Error: runtime error - expected 2 values in data stack ```