3.8 – Интерфейсы отладки
Lua не имеет встроенных удобных средств отладки. Вместо этого существует специальный
интерфейс посредством функции и hook -функций.
С его помощью можно создавать различные отладчики, профайлеры и другие инструменты,
требующие «внутренней информации», предоставляемой интерпретатором.
typedef struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) */
const char *what; /* (S) */
const char *source; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
other fields
} lua_Debug;
Эта структура используется для предоставления информации об активной функции.
lua_getstack
используется для заполнения только private-части этой структуры. Для того, чтобы заполнить остальные
поля lua_Debug
используйте lua_getinfo.
Поля структуры lua_Debug имеют следующее значение:
- source:
Если функция была определена в строке, то source будет содержать эту строку. Если же функция была определена
в файле, тогда source начинается с символа '@' за которым следует имя файла.
- short_src:
«пригодная для печати» версия source, используемая в
сообщениях об ошибках.
- linedefined:
номер строки, в которой начинается описание функции.
- lastlinedefined:
номер строки, в которой заканчивается описание функции.
- what:
Строка "Lua", если функция является функцией
LUA>, строка "C" если «Си-шная», "main" если это основная часть chunk и
"tail" если это функция, которая
совершает завершающий вызов (if it was a function that did a tail call). В
последнем случае, Lua не имеет более никакой информации об этой функции.
- currentline:
Текущая строка, где данная функция выполняется. Когда информация о текущей
строке недоступна, currentline устанавливается
равной -1.
- name:
Подходящее имя (a reasonable)
для данной функции name.
Поскольку функции в Lua являются first class объектами, они не имеют фиксированного имени: одни
функции могут быть значениями множества глобальный переменных, в то время
как другие могут храниться только в полях таблицы. Функция lua_getinfo проверяет как
функция была вызвана для того, чтобы найти подходящее имя. Если имя найти не
удалось, то значение поля name устанавливается
в NULL.
- namewhat:
Объясняет поле name. Может принимать значения "global", "local", "method", "field", "upvalue", или "" (пустая строка), в соответствии
с тем, как функция была вызвана. (Lua использует пустую строку, когда никакие
другие значения не подходят)
- nups:
число внешних локальных переменных функции.
lua_Hook lua_gethook (lua_State *L);
Возвращает текущую hook-функцию.
int lua_gethookcount (lua_State *L);
Возвращает текущее количество инструкций, после которых происходит вызов hook-функций.
int lua_gethookmask (lua_State *L);
Возвращает текущую маску hook’а.
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
Возвращает информацию об определенной функции или вызовах функции.
Для получения информации о вызовах функции параметр ar должен быть активирующей записью, которая была заполнена
предыдущим вызовом lua_getstack или
передана в качестве аргумента hook’у
(см. lua_Hook).
Для того, чтобы получить информацию о функции, вы должны ее поместить в стек
и в начало строки what добавить символ '>'. (В этом случае, lua_getinfo помещает функцию на вершину стека). Например, для того чтобы
узнать, на какой строке определена функция f, можно
использовать следующий код:
lua_Debug ar;
lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* get global 'f' */
lua_getinfo(L, ">S", &ar);
printf("%d\n", ar.linedefined);
Каждый символ строки what определяет,
какие поля структуры ar должны быть заполнены, или какое
значение должно быть помещено в стек:
- 'n':
заполнять поля name и namewhat;
- 'S': заполнять поля source, short_src, linedefined, lastlinedefined, и what;
- 'l': заполнить поле currentline;
- 'u': заполнить поле nups;
- 'f': поместить в стек функцию, которая выполняется на заданном уровне;
- 'L': поместить в стек таблицу, индексы которой являются номерами функциональных строк функции. (Функциональная строка – это такая строка, которая содержит некоторый код, и на которой можно поставить точку останова. Не функциональными строками являются пустые строчки и комментарии)
Функция возвращает 0 при ошибке. (Например, при неправильной опции в строке what).
const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
Получает информацию о локальной переменной данной структуры активации. Параметр
ar должен быть структурой активации, которая была заполнена
предыдущим вызовом lua_getstack или
передана в качестве аргумента hook’у
(см. lua_Hook).
Параметр n определяет какую локальную переменную необходимо рассматривать.
(1 означает первый параметр или активную локальную переменную и так далее до последней
активной локальной переменной). lua_getlocal помещает
значение переменной в стек и возвращает ее имя.
Переменные, имена которых начинаются с '('
(открывающаяся круглая скобка) представляют собой внутренние переменные (счетчики
циклов, временные переменные, и локальные переменные функций на C).
Возвращает NULL (и ничего не помещает в стек) когда значение индекса
больше чем количество активных локальных переменных.
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
Получает информацию о стеке времени выполнения.
Функция заполняет часть структуры lua_Debug с идентификацией
структуры активации функции,
выполняемой на заданном уровне. Уровень 0 – это выполняемая в данный момент функция,
тогда как уровень n+1
это функция, которая была вызвана с уровня n.. Когда не было обнаружено ошибок, lua_getstack возвращает
1; когда значение уровня больше чем высота стека – будет возвращен 0.
const char *lua_getupvalue (lua_State *L, int funcindex, int n);
Получает информацию о внешней локальной переменной (upvalue) экземпляра (closure) функции. (Функции Lua используют такие переменные и, следовательно, включают их в экземпляр). Функция lua_getupvalue
получает индекс n внешней локальной переменной,
извлекает ее значение в стек и возвращает ее имя. Значение funcindex указывает на положение экземпляра в стеке. (Внешние локальные переменные не имеют своего порядка, так как они активны в течение всего времени
выполнения функции. Поэтому, они имеют случайный порядок.)
Возвращает NULL (и ничего
не помещает в стек) когда индекс больше чем число внешних локальных переменных. Для функций, написанных на C, используется пустая строка “”в качестве имени всех внешних локальных переменных
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
Тип данных для отладки hook-функций.
Каждый раз, когда вызывается hook,
у аргумента ar поле event принимает значение события, которое инициировало запуск. Lua определяет
эти события при помощи следующих констант: LUA_HOOKCALL, LUA_HOOKRET,
LUA_HOOKTAILRET,
LUA_HOOKLINE,
и LUA_HOOKCOUNT>.
Кроме того, если произошло событие LUA_HOOKLINE, заполняется еще и поле currentline.
Для получения значение любого другого поля в структуре ar, hook должен
вызвать lua_getinfo.
Для возвращения событий, event может быть LUA_HOOKRET, обычное
значение или LUA_HOOKTAILRET.
В последнем случае, Lua имитирует возвращение из функции, которая совершает завершающий
вызов, при этом вызывать функцию lua_getinfo бесполезно.
Пока Lua выполняет hook,
другие обращения к нему блокируются. Поэтому, если hook обращается обратно
к Lua для
выполнения функции или chunk,
это выполнение произойдет без каких-либо обращений к hook-ам.
int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
Устанавливает отладочную hook функцию.
Аргумент f – это hook-функция.
Параметр mask определяет, при каких события эта функция будет вызвана: Он
формируется из констант LUA_MASKCALL,
LUA_MASKRET,
LUA_MASKLINE и LUA_MASKCOUNT побитовым «или». Аргумент count имеет смысл только если маска содержит константу LUA_MASKCOUNT. Для каждого
другого события, hook вызывается согласно тому, как это объяснено ниже:
- Hook вызова: выполняется, когда интерпретатор вызывает функцию сразу после того как Lua входит в новую функцию, но перед тем, как функция получит свои аргументы.
- Hook возвращения: выполняется когда интерпретатор выходит из функции.Hook вызывается сразу после того, как Lua покидает функцию, при этом нет никакого доступа к значение, которые функция возвратила.
- Hook строки: выполняется, когда интерпретатор собирается начать выполнение новой строки кода или когда переходит назад в коде (даже на ту же строчку). (Это событие происходит только, когда Lua выполняет функции Lua)
- Hook подсчета: выполняется после того, как интерпретатор выполнит каждую count–ую инструкцию. (Это событие происходит только, когда Lua выполняет функции Lua)
Для того, чтобы запретить hook, необходимо установить mask в ноль.
const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
Устанавливает значение локальной переменной данной активационной структуры. Параметры
ar и n are такие же как
и в lua _getlocal
(см. lua_getlocal).
lua_setlocal
назначает значение, находящееся на вершине стека переменной и возвращает ее имя,
при этом значение из стека извлекается.
Возвращает NULL (и ничего не выталкивает из стека) когда индекс больше
чем количество активных локальных переменных.
const char *lua_setupvalue (lua_State *L, int funcindex, int n);
Устанавливает значение внешней локальной переменной экземпляра функции.Назначает
значение, находящееся на вершине стека внешней локальной переменной и
возвращает ее имя. Назначенное значение из стека выталкивается.. Параметры funcindex и n are такие же как
и в lua_getupvalue
(см. lua_getupvalue).
Возвращает NULL (и ничего из стека не выталкивает) когда значение индекса
больше чем количество внешних локальных переменных.
|