Bibliothèque debug
La bibliothèque debug donne accès à l'introspection interne du moteur : métatables, uservalues,
upvalues, variables locales, informations d'appel et hooks d'exécution. Elle est chargée
automatiquement par OpenLibs(). Réservée à l'outillage (débogueur, profileur, sérialisation) — un
script ordinaire n'en a généralement pas besoin.
Reprend la forme de la bibliothèque debug de Lua 5.4, avec quelques écarts assumés :
debug.debugn'est pas exposée par la bibliothèque cœur : la notion même destdin/stdoutinteractif est propre à l'hôte, pas au moteur (YScripts'utilise aussi bien embarqué sans aucune console).YScript.Console, qui a un vrai terminal, l'ajoute comme extension locale à la bibliothèque — voir L'interpréteur.debug.setcstacklimitn'est pas exposée : elle existe dans le manuel Lua 5.4 mais borne la profondeur de récursion des appels C non protégés (lua_callvslua_pcall), une notion liée à l'implémentation en pile C native de la référence Lua — sans équivalent direct ici, où l'interpréteur tourne sur la pile .NET/CLR normale. Pour mémoire, Lua lui-même l'a rendue quasiment no-op à partir de 5.4.2 (retourne toujoursLUAI_MAXCCALLSsans rien changer) — ce n'est donc pas une fonctionnalité activement utile à porter.debug.getinfone reconnaît pas la catégoriet(istailcall) danswhat: la VM n'implémente pas les appels en position terminale (tail calls), donc cette information n'existerait de toute façon qu'àfalseen permanence. Passertdanswhatn'est pas une erreur, mais n'ajoute aucun champ à la table résultat.
Vue d'ensemble
| Fonction | Description |
|---|---|
debug.getmetatable(value) |
Métatable de value, ou nil si elle n'en a pas |
debug.setmetatable(value, table) |
Fixe la métatable de value (nil pour la retirer) |
debug.getregistry() |
La table de registre interne du moteur |
debug.getuservalue(u [, n]) |
n-ième valeur utilisateur attachée à l'userdata u |
debug.setuservalue(u, value [, n]) |
Fixe la n-ième valeur utilisateur de u |
debug.getupvalue(f, up) |
Nom et valeur de la up-ième upvalue de la fonction f |
debug.setupvalue(f, up, value) |
Fixe la up-ième upvalue de f |
debug.upvalueid(f, n) |
Identifiant opaque de la n-ième upvalue de f |
debug.upvaluejoin(f1, n1, f2, n2) |
Fait partager la même upvalue à f1/f2 |
debug.getlocal([thread,] f\|level, index) |
Nom (et valeur) de la index-ième variable locale |
debug.setlocal([thread,] level, index, value) |
Fixe la index-ième variable locale de la pile d'appel au niveau level |
debug.sethook([thread,] [hook, mask [, count]]) |
Installe (ou retire) un hook d'exécution |
debug.gethook([thread]) |
Hook actuellement installé, son masque et son compteur |
debug.getinfo([thread,] f [, what]) |
Table d'informations sur une fonction ou un niveau de la pile d'appel |
debug.traceback([thread,] [message [, level]]) |
Chaîne de trace d'appel, avec message en préfixe optionnel |
Métatables et registre
debug.getmetatable(value)
Retourne la métatable de value, ou nil si elle n'en a pas (contrairement à getmetatable de la
bibliothèque de base, ignore le champ __metatable qui masquerait normalement l'accès).
debug.setmetatable(value, table)
Fixe la métatable de value à table (ou la retire si table est nil). Retourne value.
debug.getregistry()
Retourne la table de registre interne du moteur — l'espace de stockage utilisé par les bibliothèques
elles-mêmes (package.loaded, package.preload, hooks enregistrés, etc.). Réservé à un usage très
avancé.
Uservalues
debug.getuservalue(u [, n]) / debug.setuservalue(u, value [, n])
Lisent/écrivent la n-ième valeur utilisateur (par défaut 1) attachée à l'userdata u — un
emplacement de stockage annexe indépendant de l'objet .NET encapsulé. setuservalue retourne u en
cas de succès ; lever n hors des bornes disponibles est une erreur d'argument.
Upvalues
debug.getupvalue(f, up)
Retourne le nom et la valeur de la up-ième upvalue (variable capturée) de la fonction f
(1-based). Retourne nil seul si up est hors limites.
debug.setupvalue(f, up, value)
Fixe la valeur de la up-ième upvalue de f. Retourne le nom de l'upvalue en cas de succès, ou
nil si up est hors limites.
debug.upvalueid(f, n) / debug.upvaluejoin(f1, n1, f2, n2)
upvalueid retourne un identifiant opaque (light userdata) désignant la cellule d'upvalue
elle-même — deux fonctions dont l'upvalue n a le même id partagent la même variable capturée.
upvaluejoin force f1's upvalue n1 à partager la cellule de f2's upvalue n2. Un index
d'upvalue invalide dans l'un ou l'autre est une erreur d'argument.
Variables locales
debug.getlocal([thread,] f|level, index)
Deux formes selon le deuxième argument :
- avec un niveau de pile (
level, entier) : inspecte laindex-ième variable locale active au niveaulevelde la pile d'appel du thread (0 = la fonction en cours), retourne son nom et sa valeur. Unlevelhors limites est une erreur d'argument. - avec une fonction (
f) : retourne uniquement le nom duindex-ième paramètre déclaré def(sans valeur, la fonction n'étant pas nécessairement en cours d'exécution).
Retourne nil seul si index ne correspond à aucune variable/paramètre.
debug.setlocal([thread,] level, index, value)
Fixe la valeur de la index-ième variable locale active au niveau level de la pile d'appel.
Retourne le nom de la variable en cas de succès, nil sinon. Un level hors limites est une erreur
d'argument.
Hooks d'exécution
debug.sethook([thread,] [hook, mask [, count]])
Installe hook (une fonction) comme rappel exécuté selon les évènements listés dans mask, chaîne
combinant :
| Lettre | Évènement déclencheur |
|---|---|
c |
à chaque appel de fonction ("call") |
r |
à chaque retour de fonction ("return") |
l |
à chaque nouvelle ligne exécutée ("line") |
count (optionnel, > 0) ajoute un déclenchement périodique tous les count instructions
("count"). Le hook est appelé avec le nom de l'évènement, plus le numéro de ligne pour "line".
Appelé sans hook/mask (juste debug.sethook() ou debug.sethook(thread)), retire le hook
installé sur le thread visé.
debug.sethook(function(event, line)
print(event, line)
end, "l")
debug.gethook([thread])
Retourne trois valeurs : la fonction hook actuellement installée sur thread (par défaut le thread
courant) — ou nil si aucune, ou si le hook actif n'a pas été posé par debug.sethook —, le masque
d'évènements sous forme de chaîne ("crl"), et le compteur.
Informations d'appel
debug.getinfo([thread,] f [, what])
Retourne une table décrivant soit la fonction f, soit — si f est un entier — le niveau f de la
pile d'appel de thread. what (chaîne, défaut "nSlu") sélectionne les catégories d'informations
à remplir :
| Lettre | Champs ajoutés à la table résultat |
|---|---|
n |
name, namewhat |
S |
source, short_src, linedefined, lastlinedefined, what |
l |
currentline |
u |
nups, nparams, isvararg |
f |
func — la fonction elle-même |
L |
activelines — table des lignes actives |
Si f est un niveau de pile hors limites, retourne nil plutôt que la table.
Contrairement à Lua, la lettre t (qui ajoute istailcall) n'est pas reconnue : voir la note en
tête de cette page.
debug.traceback([thread,] [message [, level]])
Construit une chaîne de trace de la pile d'appel de thread (par défaut le thread courant),
préfixée par message si fourni. level (défaut 1 pour le thread courant, 0 sinon) indique à
partir de quel niveau commencer la trace. Si message n'est ni une chaîne ni un nombre, il est
retourné tel quel sans construire de trace (permet de laisser passer un objet d'erreur non-textuel
sans le convertir).