Précédent Index

Annexe: source de deug-eval

 

 
 
 
1 ;;;;   $Id: eval4fr.scm,v 1.12 2003/01/16 16:03:52 titou Exp $
2 ;;;;   Copyright (C) 2000 by <Titou.Durand@ufr-info-p6.jussieu.fr>
3 ;;;;                      and <Christian.Queinnec@lip6.fr>
4
5 ;;;;   {{{ Grammaire du langage
6 ;;;;   Le langage interprété est défini par la grammaire suivante:
7 ;;;;    deug-programme := expression
8 ;;;;        expression := variable
9 ;;;;                   |  constante  |  (QUOTE donnée)          ;  citation
10 ;;;;                   |  (COND clause*)                        ;  conditionnelle
11 ;;;;                   |  (IF condition conséquence [alternant]);  alternative
12 ;;;;                   |  (BEGIN expression*)                   ;  séquence
13 ;;;;                   |  (LET (liaison*) corps)                ;  bloc
14 ;;;;                   |  (fonction argument*)                  ;  application
15 ;;;;         condition := expression
16 ;;;;       conséquence := expression
17 ;;;;         alternant := expression
18 ;;;;            clause := (condition expression*)
19 ;;;;                   |  (ELSE expression*)
20 ;;;;          fonction := expression
21 ;;;;          argument := expression
22 ;;;;         constante := nombre | chaîne | booléen | caractère
23 ;;;;            donnée := constante 
24 ;;;;                   |  symbole 
25 ;;;;                   |  (donnée*)
26 ;;;;           liaison := (variable expression)
27 ;;;;             corps := definition* expression expression*
28 ;;;;        définition := (DEFINE (nom-fonction variable*) corps)
29 ;;;;      nom-fonction := variable
30 ;;;;          variable := tous les symboles de Scheme autres que les mots-clés
31 ;;;;           symbole := tous les symboles de Scheme
32 ;;;;   }}} Grammaire du langage
33
34 ;;;;   {{{ Utilitaires généraux 
35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36 ;;;;   Nécessaires pour l'auto-amorçage (on pourrait également les placer
37 ;;;;   dans l'environnement initial).
38
39 ;;;   Signaler une erreur et abandonner l'évaluation.
40 (define (deug-erreur fn message donnee) 
41   (erreur 'deug-eval fn message donnee) )
42
43 ;;;   cadr: LISTE[alpha]/au moins deux termes/ -> alpha
44 ;;;   (cadr L) rend le second terme de la liste «L».
45 (define (cadr L) 
46   (car (cdr L)) )
47
48 ;;;   cddr: LISTE[alpha]/au moins deux termes/ -> LISTE[alpha]
49 ;;;   (cddr L) rend la liste «L» privée de ses deux premiers termes.
50 (define (cddr L) 
51   (cdr (cdr L)) )
52
53 ;;;   caddr: LISTE[alpha]/au moins trois termes/ -> alpha
54 ;;;   (caddr L) rend le troisième terme de la liste «L».
55 (define (caddr L)
56   (car (cdr (cdr L))) )
57
58 ;;;   cdddr: LISTE[alpha]/au moins trois termes/ -> LISTE[alpha]
59 ;;;   (cdddr L) rend la liste «L» privée de ses trois premiers termes.
60 (define (cdddr L) 
61   (cdr (cdr (cdr L))) )
62
63 ;;;   cadddr: LISTE[alpha]/au moins quatre termes/ -> alpha
64 ;;;   (cadddr L) rend le quatrième terme de la liste «L».
65 (define (cadddr L)
66   (car (cdr (cdr (cdr L)))) )
67
68 ;;;   length: LISTE[alpha] -> nat
69 ;;;   (length L) rend la longueur de la liste «L».
70 (define (length L)
71   (if (pair? L)
72       (+ 1 (length (cdr L)))
73       0 ) )
74
75 ;;;   deug-map: (alpha -> beta) * LISTE[alpha] -> LISTE[beta]
76 ;;;   (deug-map f L) rend la liste des valeurs de «f» appliquée aux termes 
77 ;;;   de la liste «L».
78 (define (deug-map f L)
79   (if (pair? L)
80       (cons (f (car L)) (deug-map f (cdr L)))
81       '() ) )
82
83 ;;;   member: alpha * LISTE[alpha] -> LISTE[alpha] + #f
84 ;;;   (member e L) rend le suffixe de «L» débutant par la première 
85 ;;;   occurrence de «e» ou #f si «e» n'apparaît pas dans «L».
86 (define (member e L)
87   (if (pair? L)
88       (if (equal? e (car L))
89           L
90           (member e (cdr L)) )
91       #f ) )
92
93 ;;;   rang: alpha * LISTE[alpha] -> nat
94 ;;;   (rang e L) rend le rang de l'élément donné dans la liste «L» 
95 ;;;   (où on sait que l'élément apparaît). Le premier élément a pour rang un.
96 (define (rang e L)
97   (if (equal? e (car L))
98       1
99       (+ 1 (rang e (cdr L))) ) )
100 ;;;;   }}} Utilitaires généraux
101
102 ;;;;   {{{ Barrière-syntaxique
103 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
104 ;;;;   Ces fonctions permettent de manipuler les différentes expressions 
105 ;;;;   syntaxiques dont Scheme est formé. Pour chacune de ces différentes 
106 ;;;;   formes syntaxiques, on trouve le reconnaisseur et les accesseurs.
107
108 ;;;   variable?: Expression -> bool
109 (define (variable? exp)
110   (if (symbol? exp) 
111       (cond ((equal? exp 'cond)   #f)
112             ((equal? exp 'else)   #f)
113             ((equal? exp 'if)     #f)
114             ((equal? exp 'quote)  #f)
115             ((equal? exp 'begin)  #f)
116             ((equal? exp 'let)    #f)
117             ((equal? exp 'let*)   #f)
118             ((equal? exp 'define) #f)
119             ((equal? exp 'or)     #f)
120             ((equal? exp 'and)    #f)
121             (else                 #t) )
122       #f) )
123
124 ;;;   citation?: Expression -> bool
125 (define (citation? exp)
126   (cond ((number? exp)  #t)
127         ((string? exp)  #t)
128         ((char? exp)    #t)
129         ((boolean? exp) #t)
130         ((pair? exp)    (equal? (car exp) 'quote))
131         (else           #f) ) )
132
133 ;;;   conditionnelle?: Expression -> bool
134 (define (conditionnelle? exp)
135   (if (pair? exp) (equal? (car exp) 'cond) #f) )
136
137 ;;;   conditionnelle-clauses: Conditionnelle -> LISTE[Clause]
138 (define (conditionnelle-clauses conditionnelle)
139   (cdr conditionnelle) )
140
141 ;;;   alternative?: Expression -> bool
142 (define (alternative? exp)
143   (if (pair? exp) (equal? (car exp) 'if) #f) )
144
145 ;;;   alternative-condition: Alternative -> Expression
146 (define (alternative-condition alt)
147   (cadr alt) )
148
149 ;;;   alternative-consequence: Alternative -> Expression
150 (define (alternative-consequence alt)
151   (caddr alt) )
152
153 ;;;   alternative-alternant: Alternative -> Expression
154 (define (alternative-alternant alt)
155   (if (pair? (cdddr alt)) 
156       (cadddr alt)
157       #f ) )
158
159 ;;;   sequence?: Expression -> bool
160 (define (sequence? exp)
161   (if (pair? exp) (equal? (car exp) 'begin) #f) )
162
163 ;;;   sequence-exps: Sequence -> LISTE[Expression]
164 (define (sequence-exps seq)
165   (cdr seq) )
166
167 ;;;   bloc?: Expression -> bool
168 (define (bloc? exp)
169   (if (pair? exp) (equal? (car exp) 'let) #f) )
170
171 ;;;   bloc-liaisons: Bloc -> LISTE[Liaison]
172 (define (bloc-liaisons bloc)
173   (cadr bloc) )
174
175 ;;;   bloc-corps: Bloc -> Corps
176 (define (bloc-corps bloc)
177   (cddr bloc) )
178
179 ;;;   application?: Expression -> bool
180 (define (application? exp)
181   (pair? exp) )
182
183 ;;;   application-fonction: Application -> Expression
184 (define (application-fonction appl)
185   (car appl) )
186
187 ;;;   application-arguments: Application -> LISTE[Expression]
188 (define (application-arguments appl)
189   (cdr appl) )
190
191 ;;;   clause-condition: Clause -> Expression
192 (define (clause-condition clause)
193   (car clause) )
194
195 ;;;   clause-expressions: Clause -> LISTE[Expression]
196 (define (clause-expressions clause)
197   (cdr clause) )
198
199 ;;;   liaison-variable: Liaison -> Variable
200 (define (liaison-variable liaison)
201   (car liaison) )
202
203 ;;;   liaison-exp: Liaison -> Expression
204 (define (liaison-exp liaison)
205   (cadr liaison) )
206
207 ;;;   definition?: Corps -> bool
208 ;;;  (definition? corps) rend #t ssi le premier élément du corps 
209 ;;;  «corps» est une définition
210 (define (definition? corps)
211   (if (pair? corps) (equal? (car corps) 'define) #f) )
212
213 ;;;   definition-nom-fonction: Definition -> Variable
214 (define (definition-nom-fonction def)
215   (car (cadr def)) )
216
217 ;;;   definition-variables: Definition -> LISTE[Variable]
218 (define (definition-variables def)
219   (cdr (cadr def)) )
220
221 ;;;   definition-corps: Definition -> Corps
222 (define (definition-corps def)
223   (cddr def) )
224 ;;;;   }}} Barrière-syntaxique
225
226 ;;;;   {{{ Evaluateur
227 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
228
229 ;;;   deug-eval: Deug-Programme -> Valeur
230 ;;;   (deug-eval p) rend la valeur du programme (de Deug-Scheme) «p».
231 (define (deug-eval p)
232   (evaluation p (env-initial) ) )
233
234 ;;;   evaluation: Expression * Environnement -> Valeur
235 ;;;   (evaluation exp env) rend la valeur de l'expression «exp» dans 
236 ;;;   l'environnement «env».
237 (define (evaluation exp env)
238   ;;  (discrimine l'expression et invoque l'évaluateur spécialisé)
239   (cond 
240    ((variable? exp)       (variable-val exp env))
241    ((citation? exp)       (citation-val exp))
242    ((alternative? exp)    (alternative-eval 
243                            (alternative-condition exp)
244                            (alternative-consequence exp)
245                            (alternative-alternant exp) env))
246    ((conditionnelle? exp) (conditionnelle-eval 
247                            (conditionnelle-clauses exp) env))
248    ((sequence? exp)       (sequence-eval (sequence-exps exp) env))
249    ((bloc? exp)           (bloc-eval (bloc-liaisons exp)
250                                      (bloc-corps exp) env))
251    ((application? exp)    (application-eval 
252                            (application-fonction exp)
253                            (application-arguments exp) env))
254    (else (deug-erreur 'evaluation "pas un programme" exp))) )
255
256 ;;;   alternative-eval: Expression3 * Environnement -> Valeur
257 ;;;   (alternative-eval condition consequence alternant env) rend la valeur de 
258 ;;;   l'expression «(if condition consequence alternant)» dans l'environnement «env».
259 (define (alternative-eval condition consequence alternant env)
260   (if (evaluation condition env)
261       (evaluation consequence env)
262       (evaluation alternant env)) )
263
264 ;;;   LISTE[Clause] * Environnement -> Valeur
265 ;;;   (conditionnelle-eval clauses env) rend la valeur, dans l'environnement «env», 
266 ;;;   de l'expression «(cond c1 c2 ... cn)», «c1», «c2»... «cn» étant les éléments 
267 ;;;   de la liste «clauses».
268 (define (conditionnelle-eval clauses env)
269   (evaluation (conditionnelle-expansion clauses) env) )
270
271 ;;;   conditionnelle-expansion: LISTE[Clause] -> Expression
272 ;;;   (conditionnelle-expansion clauses) rend l'expression, écrite avec des
273 ;;;   alternatives, équivalente à l'expression «(cond c1 c2 ... cn)», 
274 ;;;   «c1», «c2»... «cn» étant les éléments de la liste «clauses».
275 (define (conditionnelle-expansion clauses)
276   (if (pair? clauses)
277       (let ((premiere-clause (car clauses)))
278         (if (equal? (clause-condition premiere-clause) 'else)
279             (cons 'begin (clause-expressions premiere-clause))
280             (cons 'if
281                   (cons (clause-condition premiere-clause)
282                         (cons (cons 'begin (clause-expressions premiere-clause))
283                               (let ((seq (conditionnelle-expansion (cdr clauses))))
284                                 (if (pair? seq)
285                                     (list seq)
286                                     seq ) ) ) ) ) ) )
287       '() ) )
288
289 ;;;   sequence-eval: LISTE[Expression] * Environnement -> Valeur
290 ;;;   (sequence-eval exps env) rend la valeur, dans l'environnement «env», de 
291 ;;;   l'expression «(begin e1 ... en)», «e1»... «en» étant les éléments de la liste
292 ;;;    «exps».
293 ;;;   (Il faut évaluer tour à tour les expressions et rendre la valeur de la
294 ;;;    dernière d'entre elles.)
295 (define (sequence-eval exps env)
296   ;;   sequence-eval+ :  LISTE[Expression]/non vide/ -> Valeur
297   ;;   même fonction, sachant que la liste «exps» n'est pas vide et en globalisant
298   ;;   la variable «env».
299   (define (sequence-eval+ exps)
300     (if (pair? (cdr exps))
301         (begin (evaluation (car exps) env)
302                (sequence-eval+ (cdr exps)) )
303         (evaluation (car exps) env)))   
304   ;;   expression de (sequence-eval exps env) :
305   (if (pair? exps)
306       (sequence-eval+ exps)
307       #f ) )
308
309 ;;;   application-eval: Expression * LISTE[Expression] * Environnement -> Valeur
310 ;;;   (application-eval exp-fn arguments env) rend la valeur de l'invocation de 
311 ;;;   l'expression «exp-fn» aux arguments «arguments» dans l'environnement «env».
312 (define (application-eval exp-fn arguments env)
313   ;;   eval-env : Expression -> Valeur
314   ;;  (eval-env exp) rend la valeur de «exp» dans l'environnement «env»
315   (define (eval-env exp) 
316     (evaluation exp env))
317   ;;  expression de (application-eval exp-fn arguments env) :
318   (let ((f (evaluation exp-fn env)))
319     (if (invocable? f)
320         (invocation f (deug-map eval-env arguments))
321         (deug-erreur 'application-eval 
322                      "pas une fonction" f ) ) ) )
323
324 ;;;   bloc-eval: LISTE[Liaison] * Corps * Environnement -> Valeur
325 ;;;   (bloc-eval liaisons corps env) rend la valeur, dans l'environnement «env»,
326 ;;;   de l'expression «(let liaisons corps)».
327 (define (bloc-eval liaisons corps env)
328   (corps-eval corps (env-add-liaisons liaisons env)) )
329
330 ;;;   corps-eval: Corps * Environnement -> Valeur
331 ;;;   (corps-eval corps env) rend la valeur de «corps» dans l'environnement «env»
332 (define (corps-eval corps env)
333   (let ((def-exp (corps-separation-defs-exps corps)))
334     (let ((defs (car def-exp))
335           (exp (cadr def-exp)))
336       (evaluation exp (env-enrichissement env defs)) ) ) )
337
338 ;;;   corps-separation-defs-exps: Corps -> (LISTE[Definition] * LISTE[Expression])
339 ;;;   (corps-separation-defs-exps corps) rend une liste dont le premier élément est
340 ;;;   la liste des definitions du corps «corps» et les autres éléments sont les 
341 ;;;   expressions de ce corps.
342 (define (corps-separation-defs-exps corps)
343   (if (definition? (car corps))
344       (let ((def-exp-cdr 
345               (corps-separation-defs-exps (cdr corps))))
346         (cons (cons (car corps)
347                     (car def-exp-cdr))
348               (cdr def-exp-cdr)))
349       (cons '() corps) ) )
350 ;;;;   }}} Evaluateur
351
352 ;;;;   {{{ Barrière-interpretation
353 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
354 ;;;;  Un programme Scheme décrit deux sortes d'objets: les valeurs non fonctionnelles
355 ;;;;  (les entiers, les booléens... les listes...) et les valeurs fonctionnelles
356
357 ;;;;       {{{ Valeurs-non-fonctionnelles
358 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
359
360 ;;;   citation-val: Citation -> Valeur/non fonctionelle/
361 ;;;   (citation-val cit) rend la valeur de la citation «cit».
362 (define (citation-val cit)
363   (if (pair? cit)
364       (cadr cit)
365       cit ) )
366 ;;;;       }}} Valeurs-non-fonctionnelles
367
368 ;;;;       {{{ Valeurs-fonctionnelles
369 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
370 ;;;;   Il y a deux types de fonctions, les fonctions prédéfinies (reconnues par
371 ;;;;   primitive?) et les fonctions du programme en cours d'évaluation (créées par 
372 ;;;;   fonction-creation).
373
374 ;;;   invocable?: Valeur -> bool
375 ;;;   (invocable? val) rend vrai ssi «val» est une fonction (primitive ou définie  
376 ;;;   par le programmeur)
377 (define (invocable? val)
378   (if (primitive? val)
379       #t 
380       (fonction? val) ) )
381
382 ;;;   invocation: Invocable * LISTE[Valeur] -> Valeur
383 ;;;   (invocation f vals) rend la valeur de l'application de «f» aux éléments de 
384 ;;;   «vals».
385 (define (invocation f vals)
386   (if (primitive? f)
387       (primitive-invocation f vals) 
388       (fonction-invocation f vals) ) )
389
390 ;;;;           {{{ Primitives 
391 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392 ;;;;   Une primitive est implantée par un 4-uplet:
393 ;;;;   - le premier élément est le symbole *primitive* (pour les reconnaître),
394 ;;;;   - le second élément est la fonction du Scheme sous-jacent qui implante 
395 ;;;;     la primitive,
396 ;;;;   - le troisième élément est un comparateur (= ou >=),
397 ;;;;   - le dernier élément est un entier naturel, ces deux derniers éléments
398 ;;;;     permettant de spécifier l'arité de la primitive.
399
400 ;;;   primitive?: Valeur -> bool
401 ;;;   (primitive? val) rend  vrai ssi «val» est une fonction primitive.
402 (define (primitive? val)
403   (if (pair? val) 
404       (equal? (car val) '*primitive*) 
405       #f) )
406
407 ;;;   primitive-creation: N-UPLET[(Valeur... -> Valeur) (num * num -> bool) num] 
408 ;;;                       -> Primitive
409 ;;;   (primitive-creation f-c-n) rend la primitive implantée par la fonction (du  
410 ;;;   Scheme sous-jacent) «f», le premier élément de «f-c-n», et dont l'arité est
411 ;;;   spécifiée par le comparateur «c», deuxième élément de «f-c-n» et l'entier «n»,
412 ;;;    troisième élément de «f-c-n».
413 (define (primitive-creation f-c-n)
414   (cons '*primitive* f-c-n) )
415
416 ;;;   primitive-invocation: Primitive * LISTE[Valeur] -> Valeur
417 ;;;   (primitive-invocation p vals) rend la valeur de l'application de la
418 ;;;   primitive «p» aux éléments de «vals».
419 (define (primitive-invocation primitive vals)
420   (let ((n       (length vals)) 
421         (f       (cadr primitive))
422         (compare (caddr primitive)) 
423         (arite   (cadddr primitive)))
424     (if (compare n arite)
425         (cond
426          ((= n 0) (f))
427          ((= n 1) (f (car vals)))
428          ((= n 2) (f (car vals) (cadr vals)))
429          ((= n 3) (f (car vals) (cadr vals) (caddr vals)))
430          ((= n 4) (f (car vals) (cadr vals) 
431                      (caddr vals) (cadddr vals) ))
432          (else 
433           (deug-erreur 'primitive-invocation 
434                        "limite implantation (arités quelconques < 5)" 
435                        vals)))
436         (deug-erreur 'primitive-invocation "arité incorrecte" vals) ) ) )
437 ;;;;           }}} Primitives
438
439 ;;;;           {{{ Fonctions-definies par le programmeur 
440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
441 ;;;;   Une fonction définie par le programmeur est implantée par un 4-uplet:
442 ;;;;   - le premier élément est le symbole *fonction* (pour les reconnaître),
443 ;;;;   - le second élément est la liste des variables de la définition de la
444 ;;;;     fonction,
445 ;;;;   - le troisième élément est le corps de la définition de la fonction,
446 ;;;;   - le quatrième élément est l'environnement où est définie la fonction.
447
448 ;;;   fonction?: Valeur -> bool
449 ;;;   (fonction? val) rend vrai ssi «val» est une fonction créée par le programmeur.
450 (define (fonction? val)
451   (if (pair? val)
452       (equal? (car val) '*fonction*)
453       #f ) )
454
455 ;;;   fonction-invocation: Fonction * LISTE[Valeur] -> Valeur
456 ;;;   (fonction-invocation f vals) rend la valeur de l'application de
457 ;;;   la fonction définie par le programmeur «f» aux éléments de «vals».
458 (define (fonction-invocation f vals)
459   (let ((variables (cadr f))
460         (corps     (caddr f))
461         (env       (cadddr f)) )
462     (corps-eval corps (env-extension env variables vals)) ) )
463
464 ;;;   fonction-creation: Definition * Environnement -> Fonction
465 ;;;   (fonction-creation definition env) rend la fonction définie par 
466 ;;;   «definition» dans l'environnement «env».
467 (define (fonction-creation definition env)
468   (list '*fonction*
469         (definition-variables definition)
470         (definition-corps definition)
471         env ) )
472
473 ;;;;           }}} Fonctions-definies par le programmeur
474 ;;;;       }}} Valeurs-fonctionnelles
475 ;;;;   }}} Barrière-interpretation
476
477 ;;;;   {{{ Environnements-H (barrière de haut niveau)
478 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
479
480 ;;;   variable-val: Variable * Environnement -> Valeur
481 ;;;   (variable-val var env) rend la valeur de la variable «var» dans 
482 ;;;   l'environnement «env».
483 (define (variable-val var env)
484   (if (env-non-vide? env)
485       (let ((bloc (env-1er-bloc env)))
486         (let ((variables (blocActivation-variables bloc)))
487           (if (member var variables)
488               (blocActivation-val bloc var)
489               (variable-val var (env-reste env)))))
490       (deug-erreur 'variable-val "variable inconnue" var) ) )
491
492 ;;;   env-extension: Environnement * LISTE[Variable] * LISTE[Valeur] -> Environnement
493 ;;;   (env-extension env vars vals) rend l'environnement «env» étendu avec    
494 ;;;   un bloc d'activation liant les variables «vars» aux valeurs «vals».
495 (define (env-extension env vars vals)
496   (if (= (length vars) (length vals))
497       (let ((bloc (blocActivation-creation vars)))
498         (begin
499           (blocActivation-mettre-valeurs! bloc vals)
500           (env-add bloc env) ) )
501       (deug-erreur 'env-extension "arité incorrecte" (list vars vals)) ) )
502
503 ;;;   env-add-liaisons: LISTE[Liaison] * Environnement -> Environnement
504 ;;;   (env-add-liaisons liaisons env) rend l'environnement obtenu en ajoutant,
505 ;;;   à l'environnement «env», les liaisons «liaisons».
506 (define (env-add-liaisons liaisons env)
507   ;;   eval-env : Expression -> Valeur
508   ;;  (eval-env exp) rend la valeur de «exp» dans l'environnement «env»
509   (define (eval-env exp) 
510     (evaluation exp env))
511   ;;  expression de (env-add-liaisons liaisons env) :
512   (env-extension env 
513                  (deug-map liaison-variable liaisons)
514                  (deug-map eval-env (deug-map liaison-exp liaisons)) ) )
515
516 ;;;   env-enrichissement: Environnement * LISTE[Definition] -> Environnement
517 ;;;   (env-enrichissement env defs) rend l'environnement «env» étendu avec un 
518 ;;;   bloc d'activation pour les définitions fonctionnelles «defs».
519 (define (env-enrichissement env defs)
520   (let ((noms (deug-map definition-nom-fonction defs)))
521     (let ((bloc (blocActivation-creation noms)))
522       (let ((env-plus (env-add bloc env)))
523         (define (fonction-creation-env-plus definition)
524           (fonction-creation definition env-plus))
525         (begin
526           (blocActivation-mettre-valeurs! 
527            bloc
528            (deug-map fonction-creation-env-plus defs))
529           env-plus ) ) ) ) )
530
531 ;;;;       {{{ Environnements-B (barrière de bas niveau)
532 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
533 ;;;;   Les environnements sont représentés par la structure de données
534 ;;;;   LISTE[BlocActivation]
535
536 ;;;   env-vide: -> Environnement
537 ;;;   (env-vide) rend l'environnement vide
538 (define (env-vide) '())
539
540 ;;;   env-non-vide?: Environnement -> bool
541 ;;;   (env-non-vide? env) rend #t ssi l'environnement «env» n'est pas vide
542 (define (env-non-vide? env)
543   (pair? env) )
544
545 ;;;   env-add: Environnement * BlocActivation -> Environnement
546 ;;;   (env-add bloc env) rend l'environnement obtenu en ajoutant devant 
547 ;;;   l'environnement «env» le bloc d'activation «bloc».
548 (define (env-add bloc env)
549   (cons bloc env) )
550
551 ;;;   env-1er-bloc: Environnement -> BlocActivation
552 ;;;   ERREUR lorsque l'environnement donné est vide
553 ;;;   (env-1er-bloc env) rend le premier (i.e. celui qui a été ajouté en  
554 ;;;   dernier) bloc d'activation de l'environnement «env».
555 (define (env-1er-bloc env)
556    (car env) )
557
558 ;;;   env-reste: Environnement -> Environnement
559 ;;;   ERREUR lorsque l'environnement donné est vide
560 ;;;   (env-reste env) rend l'environnement obtenu en supprimant le premier  
561 ;;;   bloc d'activation de l'environnement «env».
562 (define (env-reste env)
563   (cdr env) )
564
565 ;;;;            {{{ Blocs d'activation
566 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
567 ;;;;   Les blocs d'activation sont représentés par la structure de données:
568 ;;;;   VECTEUR[LISTE[Variable] Valeur...]
569
570 ;;;   blocActivation-variables: BlocActivation -> LISTE[Variable]
571 ;;;   (blocActivation-variables bloc) rend la liste des variables définies 
572 ;;;   dans le bloc d'activation «bloc»
573 (define (blocActivation-variables bloc)
574   (vector-ref bloc 0) )
575
576 ;;;   blocActivation-val: BlocActivation * Variable -> Valeur
577 ;;;   HYPOTHESE: «var» est une variable définie dans «bloc»
578 ;;;   (blocActivation-val bloc var) rend la valeur de la variable «var» 
579 ;;;   dans le bloc d'activation «bloc».
580 (define (blocActivation-val bloc var)
581   (let ((i (rang var (blocActivation-variables bloc))))
582     (vector-ref bloc i) ) )
583
584 ;;;   blocActivation-creation: LISTE[Variable] -> BlocActivation
585 ;;;   (blocActivation-creation vars) rend un bloc d'activation contenant 
586 ;;;   la liste des variables «vars», avec la place qu'il faut pour les valeurs
587 ;;;   de ces variables, cette place n'étant pas remplie.
588 (define (blocActivation-creation vars)
589   (let ((bloc (make-vector (+ 1 (length vars)))))
590     (begin
591       (vector-set! bloc 0 vars)
592       bloc ) ) )
593
594 ;;;   blocActivation-mettre-valeurs!: BlocActivation * LISTE[Valeur] -> Rien
595 ;;;   (blocActivation-mettre-valeurs! bloc vals)  affecte les valeurs «vals» (données
596 ;;;   sous forme de liste) dans le bloc d'activation «bloc» (qui est un vecteur)
597 (define (blocActivation-mettre-valeurs! bloc vals)
598   ;;   remplir!: nat * LISTE[Valeur] -> Rien
599   ;;   (remplir! i vals) remplit les cases du vecteur «bloc», à partir de  
600   ;;   l'indice «i», avec les valeurs de la liste «vals» (et dans le même ordre).
601   (define (remplir! i vals)
602     (if (pair? vals)
603         (begin
604           (vector-set! bloc i (car vals))
605           (remplir! (+ i 1) (cdr vals)) ) ) )
606   (remplir! 1 vals) )
607 ;;;;            }}} Blocs d'activation
608 ;;;;       }}} Environnements-B (barrière de bas niveau)
609
610 ;;;;       {{{ Environnement-initial
611 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
612 ;;;;   L'environnement initial est composé des primitives.
613 ;;;;   Pour faciliter la description, dans ce logiciel, des différentes 
614 ;;;;   primitives, nous les écrirons sous la forme d'une liste de 
615 ;;;;   descriptions de primitive.
616 ;;;;   Un élément du type DescriptionPrimitive est une description (presque 
617 ;;;;   textuelle) d'une primitive. C'est une liste dont 
618 ;;;;   - le premier élément est la variable représentant, dans Deug-Scheme, la 
619 ;;;;     primitive considérée,
620 ;;;;   - les trois autres éléments sont les trois éléments qui décrivent
621 ;;;;     l'implantation de la primitive (la fonction du Scheme sous-jacent,
622 ;;;;     le comparateur et l'arité).
623
624 ;;;   env-initial: -> Environnement  
625 ;;;   (env-initial) rend l'environnement initial, i.e. l'environnement qui
626 ;;;   contient toutes les primitives.
627 (define (env-initial)
628   (env-extension (env-vide)
629                  (deug-map car (descriptions-primitives))
630                  (deug-map primitive-creation 
631                            (deug-map cdr (descriptions-primitives)) ) ) )
632
633 ;;;   description-primitive: Variable * (Valeur ... -> Valeur)
634 ;;;       * (num * num -> bool) * num  -> DescriptionPrimitive
635 ;;;   (description-primitive var f comparator arite) rend la description de la  
636 ;;;   primitive désignée par «var», implantée dans le Scheme sous-jacent par «f» et
637 ;;;   dont l'arité est définie par «comparator» «arite».
638 (define (description-primitive var f comparator arite)
639   (list var f comparator arite))
640
641 ;;;   descriptions-primitives: -> LISTE[DescriptionPrimitive]
642 ;;;   (descriptions-primitives) rend la liste des descriptions de toutes les 
643 ;;;   primitives
644 (define (descriptions-primitives)        
645   (list
646    (description-primitive 'car           car           =  1)
647    (description-primitive 'cdr           cdr           =  1)
648    (description-primitive 'cons          cons          =  2)
649    (description-primitive 'list          list          >= 0)
650    (description-primitive 'vector-length vector-length =  1)
651    (description-primitive 'vector-ref    vector-ref    =  2)
652    (description-primitive 'vector-set!   vector-set!   =  3)
653    (description-primitive 'make-vector   make-vector   =  1) ;   ou 2 
654    (description-primitive 'pair?         pair?         =  1)
655    (description-primitive 'symbol?       symbol?       =  1)
656    (description-primitive 'number?       number?       =  1)
657    (description-primitive 'string?       string?       =  1)
658    (description-primitive 'boolean?      boolean?      =  1)
659    (description-primitive 'vector?       vector?       =  1)
660    (description-primitive 'char?         char?         =  1)
661    (description-primitive 'equal?        equal?        =  2)
662    (description-primitive '+             +             >= 0)
663    (description-primitive '*             *             >= 0)
664    (description-primitive '-             -             =  2)
665    (description-primitive '=             =             =  2)
666    (description-primitive '<             <             =  2)
667    (description-primitive '>             >             =  2)
668    (description-primitive '<=            <=            =  2)
669    (description-primitive '>=            >=            =  2)
670    (description-primitive 'remainder     remainder     =  2)
671    (description-primitive 'display       display       =  1) ;   ou 2
672    (description-primitive 'newline       newline       =  0) ;   ou 1
673    (description-primitive 'read          read          =  0)
674    (description-primitive 'erreur        deug-erreur   =  3) ))
675
676 ;;;;       }}} Environnement-initial
677 ;;;;   }}} Environnements-H (barrière de haut niveau)
678
679 ;;;;   {{{ Mode d'emploi
680 ;;;;  NOTA: sous DrScheme, on doit faire tourner ce code dans un environnement où est
681 ;;;;  définie la fonction «erreur», pour faire tourner ce code sous d'autres systèmes
682 ;;;;  Scheme, il faut définir une fonction «erreur» d'arité supérieure ou égale à 2.
683
684 ;   Mise en oeuvre sous DrScheme:
685 ;   ouvrir fichier eval4fr.scm puis évaluer (deug-eval '(+ 2 3))
686 ;   puis évaluer
687 ;   (deug-eval '(let ((a 5)) (define (f n) (if (= n 0) 1 (* n (f (- n 1))))) 
688 ;                            (f a)))
689 ;   Pour auto-interpréter l'évaluateur, il suffit d'écrire (en supposant
690 ;   que <DEUGEVAL> est le programme définissant deug-eval:
691 ;   (deug-eval '(let () <DEUGEVAL> (deug-eval '(+ 2 3))))
692 ;   puis 
693 ;   (deug-eval '(let () 
694 ;      <DEUGEVAL> 
695 ;      (deug-eval '(let ((a 5)) (define (f n) (if (= n 0) 1 (* n (f (- n 1))))) 
696 ;                                 (f a)))))
697 ;;;;   }}} Mode d'emploi
698 ;;;;   end of eval4fr.scm


Auteur(s): titou@ufr-info-p6.jussieu.fr.Mainteneur de la page: titou@ufr-info-p6.jussieu.fr.

Précédent Index