• Aucun résultat trouvé

Masquer l’évaluation des macros dans l’interprète

6.4 Filtrage avancé : masquer l’interprète Bigloo

6.4.4 Masquer l’évaluation des macros dans l’interprète

Le langage Scheme propose un mécanisme de macro-expansion pour remplacer une forme syntaxique dans le source par un ensemble d’expressions calculées au moment de l’expansion. Les expressions macros-expansées à la compilation ne présentent pas de pro- blème en ce qui concerne le débogage. Toutefois, la macro-expansion peut aussi se produire à l’exécution lorsque l’interprète Bigloo évalue des expressions. Il est donc nécessaire de masquer l’implantation de la macro-expansion.

Le système de macro de Bigloo est une mise en œuvre de la technique appelée Expansion Passing Style ou EPS [DFH86]. Dans ce schéma, les extensions syntaxiques sont manipulées par des fonctions appelées expanders. Un expander reçoit deux arguments : la forme syn- taxique à expanser et un expander devant être appliqué au résultat de la macro-expansion du premier argument. Par récurrence, la macro-expansion retourne une s-expression com- posée uniquement de formes primitives du langage. Ce style d’expansion est similaire dans l’esprit au style de programmation CPS [GLS78].

1 (define-macro (add1 el)

2 ‘(+ ,el 1)

(a) macro utilisateur

1 (add-expander! ’add1

2 (lambda (x.%% e.%%)

3 (e.%% (let ((el (cadr x.%%))

4 (.%% (cddr x.%%)))

5 (if (pair? .%%)

6 (error "bad args")

7 ‘(+ ,el 1)) )

8 e.%%))

(b) transformation en un expander équivalent

Fig. 6.5: L’implantation de la forme define-macro avec un expander

Dans sa quatrième révision, le langage Scheme fournit un système de macro différent à travers la forme define-macro. Dans Bigloo, ce système de macros est implanté en in-

terne à l’aide d’expanders. À titre d’exemple, la figure 6.5 présente une macro utilisateur

add1 (6.5(a)) et l’expander équivalent (6.5(b)) construit par Bigloo pour implanter cette

macro.

Contrairement aux implantations présentées précédemment dans ce chapitre, l’implan- tation de macro est singulière car le code produit par la macro-expansion est du code-octet Bigloo. Or, ce dernier a déja été pris en charge pour la construction de la vue virtuelle.

Pour illustrer notre propos, considérons le listing de la figure 6.6. Supposons qu’un point

d’arrêt interprété soit présent dans le fichier file6.scm à la ligne 2 (6.6(b)). Au moment où le programme compilé (6.6(b)) charge ce fichier, l’exécution se suspend dans la macro expansion de la fonction foo4.

La figure 6.7(a) présente la vue virtuelle de la pile au moment de la suspension. La

6.4. FILTRAGE AVANCÉ : MASQUER L’INTERPRÈTE BIGLOO 1 (module example7 2 (main go)) 3 4 (define (go args) 5 (load "file6.scm"))

(a) Le programme compilé

1 (define-macro (add1 el)

2 ‘(+ ,el 1))

3

4 (define (foo4 x)

5 (add1 (* x x)))

(b) Le code chargé dynamiquement

Fig. 6.6: Macro-expansion durant l’évaluation d’un programme interprété

macro-expansion commence dans la bloc 8. Chaque appel à la fonction initial-expander est responsable de l’expansion d’une sous partie de la fonction foo4, jusqu’à l’appel de l’expander add1. On peut voir que l’émulation de cette macro entraîne l’apparition dans la pile de la signature de l’expander. De plus, les variables locales synthétiques produites par la compilation apparaissent dans le bloc d’activation.

Pour construire correctement la vue virtuelle de la pile d’exécution, il faut tout d’abord masquer les expanders de la bibliothèque d’exécution de Bigloo, car ils ne représentent pas d’intérêt particulier pour localiser la progression de la macro-expansion. Les règles de remplacement suivantes s’occupent du masquage :

(50

[(+ (any any any ["^bigloo\\.runtime\\.Eval\\.(expd.*|expanders)$"]))] mask)

(50

[(["BgL_zc3anonymousza3.*"] any any "bigloo.runtime.Eval.eval") (["funcall"] any any "bigloo.runtime.Eval.eval")]

mask)

Ces deux règles masquent les fonctions provenant des fichiers nommés expand.scm et expd*.scm, ainsi que les fonctions anonymes du fichier eval.scm. Ce masquage est toutefois purement « cosmétique » et peut être débrayé si l’on souhaite déboguer la progression exacte de la macro expansion.

Pour construire un bloc d’activation virtuel correct à partir du bloc d’activation 0 qui représente la macro utilisateur, il faut modifier légèrement l’évaluateur Bigloo : lors de la

création de fonctions anonymes utilisées comme macros (figure 6.5(b)), nous plaçons une

marque dans le code-octet produit pour indiquer que la fonction est une macro, ainsi que le nombre d’argument que contient réellement cette macro utilisateur. Il suffit ensuite de modifier légèrement les fonctions sf-bigloo-evmeaning et rrp-evmeaning-prep-call pour créer un bloc d’activation virtuel représentant une macro ou une simple fonction interprétée selon le cas.

La figure 6.7(b) présente l’état de la vue virtuelle lorsqu’on applique les règles de rem-

placement et que l’on construit un bloc d’activation virtuel spécial. On voit que la signature originale de la macro utilisateur (bloc 0) est restaurée. De plus, les variables locales syn- thétiques produites générées par l’implantation de la forme define-macro (celles terminant par .%%) sont correctement masquées. Enfin, les blocs d’activation initial-expander sont conservés dans la vue virtuelle car ils peuvent être consultables pour localiser la partie exacte du code en cours de macro-expansion.

CHAPITRE 6. FILTRAGE DE LA PILE POUR LE LANGAGE BIGLOO

(bugloo) (info stack filter)

#0 (add1 ::obj :obj) in file file6.scm:2

#1 (<anonymous:1618> ::obj ::obj) in file Eval/eval.scm

#2 (initial-expander ::obj ::obj) in file Eval/expand.scm:76

#3 (<anonymous:1084> ::obj ::obj) in file Eval/expddefine.scm:82

#4 (expand-eval-external-define ::obj ::obj) in file Eval/expddefine.scm

#5 (expand-eval-define ::obj ::obj) in file Eval/expddefine.scm:117

#6 (<anonymous:2106> ::obj ::obj) in file Eval/expanders.scm:382

#7 (initial-expander ::obj ::obj) in file Eval/expand.scm:76

#8 (expand ::obj) in file Eval/expand.scm:51

#9 (eval ::obj ::obj) in file Eval/eval.scm:125

#10 (loadv ::obj ::obj) in file Eval/eval.scm:402 #11 (load ::obj) in file Eval/eval.scm:364

#12 (go ::pair) in file exemple6.scm:5

(bugloo) (info args filter)

el (::extended_pair) = (* x x) .%% (::nil) = ()

x.%% (::extended_pair) = (add1 (* x x))

e.%% (::bigloo.runtime.Eval.expddefine) = procedure in expddefine.scm:80

(a) vue virtuelle sans filtrage de la forme define-macro (bugloo) (info stack filter)

#0 (add1 ::obj) in file file6.scm:2

#1 (initial-expander ::obj ::obj) in file Eval/expand.scm

#2 (initial-expander ::obj ::obj) in file Eval/expand.scm:76

#3 (expand ::obj) in file Eval/expand.scm:51

#4 (eval ::obj ::obj) in file Eval/eval.scm:125

#5 (loadv ::obj ::obj) in file Eval/eval.scm:402

#6 (load ::obj) in file Eval/eval.scm:364

#7 (go ::pair) in file exemple6.scm:5

(bugloo) (info args filter)

el (::extended_pair) = (* x x)

(b) vue virtuelle tenant compte de la forme define-macro

Fig. 6.7: Macro-expansion durant l’évaluation d’un programme interprété

6.5 Rapport d’expérience sur l’implantation