Files
fz-lang/docs/ru/reference/errors_print.md
T

5.1 KiB
Raw Blame History

Вывод ошибок

Если во время работы программы происходит ошибка рантайма, то ВМ выводит своё состояние на момент остановки. Среди выводимой информации есть:

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

Порядковый номер позволяет быстро найти инструкцию, на которой произошло исключение. Полный список опкодов и их описание можно найти в документе списка опкодов.

Стек данных

Стек данных выводится как список значений в стиле [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