1 Mercredi 3 Octobre 1984 INRIA Domaine de Voluceau Rocquencourt 78153 Le Chesnay Cedex Vprint Le Composeur Ceyx Ge'rard Berry, Jean-Marie Hullot Ete' 1984 Re'sume': ←N←o←u←s ←d←e'←f←i←n←i←s←s←o←n←s ←u←n←e ←m←a←c←h←i←n←e ←v←i←r←t←u←e←l←l←e ←p←e←r←m←e←t←t←a←n←t ←d←e ←p←r←o←d←u←i←r←e ←d←e←s ←r←e←p←r←e'←s←e←n←t←a←t←i←o←n←s ←t←e←x←t←u←e←l←l←e←s ←d←e ←s←t←r←u←c←t←u←r←e←s ←L←i←s←p ←o←u ←C←e←y←x ←a←r←b←i←t←r←a←i←r←e←s. 2 Mercredi 3 Octobre 1984 3 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx ←G←e'←r←a←r←d ←B←e←r←r←y, ←J←e←a←n-←M←a←r←i←e ←H←u←l←l←o←t Nous de'finissons une machine pour composer Ceyx. Cette documentation donne les fonctions de base de la machine et un programme standard de paragraphage (pretty-print) utilisant cette machine. La lecture de ce document suppose une connaissance pre'alable de Ceyx et Le←Lisp. Nous renvoyons pour cela aux rapports INRIA suivants: o+ Le←Lisp de l'INRIA, Le Manuel de Re'fe'rence (J. Chailloux), o+ Ceyx: Une Initiation (J.-M. Hullot), o+ Programmer en Ceyx (J.-M. Hullot). 1 La Machine de Composition 1.1 Impression des Atomes (with-vprint-output <expr>1 ... <expr>n) Les <expr>i sont des expressions Lisp quelconques qui sont e'value'es en se'quence. Toutes les fonctions d'impression et de composition de'crites ci-dessous ne fonctionnent que si elles sont utilise'es dans le corps d'un with-vprint-output. 4 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx (vpatom <atom>) Permet d'imprimer un atome Lisp quelconque. (vprincn <charn>) <charn> est un code ascii, cette fonction imprime le caracte`re correspondant. (vprinch <char>) <char> est un symbole monocaracte`re qui est imprime'. Exemples: ? (with-vprint-output (vprinch 'a)) a = t ? (with-vprint-output (vprincn #/a)) a = t ? (with-vprint-output (vpatom 'Celui) (vprinch '| |) ? (vpatom "qui") (vprinch '| |) ? (vpatom "sait") (vprinch '| |) (vpatom "ne") (vprinch '| |) (vpatom "parle") (vprinch '| |) (vpatom "pas") (vprincn #/.) (vprinch '| |)) Celui qui sait ne parle pas. = t 1.2 Les Blocs de Composition Les fonctions de la section pre'ce'dente permettent de construire des ←b←l←o←c←s ←d←e ←t←e←x←t←e monolignes. Pour l'exemple pre'ce'dent, nous avons le bloc de texte: *----------------------------* 5 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx |Celui qui sait ne parle pas.| *----------------------------* Dans le cas ou` ce bloc tient dans une ligne physique (i.e. sa longueur est infe'rieure a` (rmargin)), il est imprime' tel que. S'il ne tient pas dans une ligne, aucune indication n'est donne'e sur la fac,on dont on doit le couper en plusieurs lignes lors de l'impression. Nous dirons que les blocs de texte sont ←i←n←s←e'←c←a←b←l←e←s. Nous donnons maintenant des constructions permettant de structurer des blocs de manie`re a` autoriser l'impression sur plusieurs lignes. Pour cela, nous introduisons les notions de ←p←o←i←n←t ←d←e ←c←o←u←p←u←r←e et de ←b←l←o←c ←d←e ←c←o←m←p←o←s←i←t←i←o←n. (vcutpoint <atom>) (vcutpoint) Cette fonction introduit un point de coupure optionnel qui est interpre'te' de manie`re diffe'rente dans le contexte d'un bloc horizontal, vertical ou mixte (voir ci-dessous). 1.2.1 Les Blocs Horizontaux (hblock <indent> <expr>1 ... <expr>n) <indent> doit avoir pour valeur un entier. Les <expr>i sont des expressions Lisp quelconques qui sont e'value'es en se'quence. Cette fonction place la machine de composition en mode horizontal. (hblock 3 (vpatom "Celui") (vcutpoint) (vpatom "qui") (vcutpoint) (vpatom "sait") *----------------------------------------* (vcutpoint) |*-----* *---* *----* *--* *-----* *----*| (vpatom "ne") ||Celui|↑|qui|↑|sait|↑|ne|↑|parle|↑|pas.|| (vcutpoint) |*-----* *---* *----* *--* *-----* *----*| 6 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx (vpatom "parle") *----------------------------------------* (vcutpoint) (vpatom "pas") (vprincn #/.)) En mode horizontal, les points de coupure sont interpre'te's comme des espaces tant que la marge droite n'est pas atteinte, si aucun argument n'est donne' a` vcutpoint. Si un argument <atom> est donne', on imprime cet atome a` la place de l'espace. Ainsi si toute l'expression tient sur la ligne, le re'sultat de l'impression est: Celui qui sait ne parle pas. |<-- rmargin Dans le cas contraire, un saut de ligne est produit a` la place du dernier point de coupure sur la ligne, et l'impression reprend a` la ligne suivante avec le renfoncement <indent>: Celui qui sait |<-- rmargin ne parle pas.| ou, avec une marge droite plus petite, Celui qui |<-- rmargin sait ne | parle pas.| Noter que dans ce cas le blanc ou la chai↑ne argument de vcutpoint n'est pas imprime'. {Vprint}:indent [variable] La variable {Vprint}:indent contient la valeur par de'faut du renfoncement. A l'initialisation du syste`me, elle vaut 3 et elle peut bien sur e↑tre modifie'e par l'utilisateur. 7 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx 1.2.2 Les Blocs Verticaux (vblock <indent> <expr>1 ... <expr>n) <indent> doit avoir pour valeur un entier. Les <expr>i sont des expressions Lisp quelconques qui sont e'value'es en se'quence. Cette fonction place la machine de composition en mode vertical. Avec l'exemple pre'ce'dent, dans lequel hblock est change' en vblock, (vblock 3 (vpatom "Celui") (vcutpoint) ...) nous avons syste'matiquement la composition verticale suivante: Celui qui sait ne parle pas. c'est a` dire que tous les points de coupure sont interpre'te's comme des sauts de ligne. 1.2.3 Les Blocs Mixtes (xblock <indent> <expr>1 ... <expr>n) <indent> doit avoir pour valeur un entier. Les <expr>i sont des expressions Lisp quelconques qui sont e'value'es en se'quence. Cette fonction place la machine de composition en mode mixte. 8 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx Reprenons l'exemple pre'ce'dent dans le cas d'un bloc mixte: (xblock 3 (vpatom "Celui") (vcutpoint) ...) Ici la composition se fait en mode horizontal si tout tient sur une seule ligne et en mode vertical dans le cas contraire: Celui qui sait ne parle pas |<-- rmargin ou: Celui |<-- rmargin qui | sait | ne | parle | pas. | Comme pre'ce'demment, (vcutpoint <atom>) imprime l'atome a` la place du blanc en mode horizontal, et provoque un retour chariot sans impression de l'atome en mode vertical. De plus un appel de vcutpoint ne provoque pas de retour chariot si rien n'a e'te' e'crit dans la ligne courante, afin d'e'viter la ligne blanche qui en re'sulterait. 1.2.4 Exemples Etant donne'e une liste d'atomes L, nous de'finissons la fonction qui permet d'imprimer cette liste en inse'rant un point de coupure entre chacun des e'le'ments de la liste: Nous construisons deux listes que nous allons utiliser pour visualiser le re'sultat de la composition. La premie`re liste L1 tient toujours sur une seule ligne, la liste L2 demande plusieurs lignes pour s'imprimer: 9 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx ? (setq L1 '(<item>1 <item>2 <item>3)) = (<item>1 <item>2 <item>3) ? (setq L2 '(<item>1 <item>2 <item>3 <item>4 <item>5 <item>6 <item>7 <item>8 ? <item>9 <item>10 <item>11 <item>12 <item>13 <item>14 <item>15)) = (<item>1 <item>2 <item>3 <item>4 <item>5 <item>6 <item>7 <item>8 <item>9 <item>10 <item>11 <item>12 <item>13 <item>14 <item>15) Nous nous plac,ons d'abord dans un mode de composition horizontale: ? (with-vprint-output (hblock 0 (print-list-atoms L1))) <item>1 <item>2 <item>3 = t Les diffe'rents atomes apparaissent se'pare's par des espaces qui sont l'interpre'tation des points de coupure dans ce cas. Toujours en mode horizontal, mais dans le cas ou` une ligne ne suffit pas pour l'impression, nous avons: ? (with-vprint-output (hblock 0 (print-list-atoms L2))) <item>1 <item>2 <item>3 <item>4 <item>5 <item>6 <item>7 <item>8 <item>9 <item>10 <item>11 <item>12 <item>13 <item>14 <item>15 = t L'atome <item>10 ne peut dans ce cas tenir sur la ligne; le point de coupure entre <item>9 et <item>10 est alors interpre'te' comme un saut de ligne, les autres continuant a` e↑tre interpre'te' comme des espaces. Le renfoncement associe' au bloc horizontal vaut 0, <item>10 commence en de'but de ligne. Nous donnons ci-dessous un exemple avec un renfoncement non nul: ? (with-vprint-output (hblock 8 (print-list-atoms L2))) <item>1 <item>2 <item>3 <item>4 <item>5 <item>6 <item>7 <item>8 <item>9 <item>10 <item>11 <item>12 <item>13 <item>14 <item>15 = t 10 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx Nous reprenons maintenant les me↑mes exemples dans un mode de composition verticale: ? (with-vprint-output (vblock 0 (print-list-atoms L1))) <item>1 <item>2 <item>3 = t Dans ce cas, tous les points de coupure sont interpre'te's comme des sauts de lignes. Avec un renfoncement non nul, nous avons: ? (with-vprint-output (vblock 3 (print-list-atoms L1))) <item>1 <item>2 <item>3 = t Enfin, dans le cas d'un mode de composition mixte, le mode de composition horizontale est choisi si l'impression peut se faire sur une seule ligne et le mode de composition verticale si une ligne n'est pas suffisante: ? (with-vprint-output (xblock 0 (print-list-atoms L1))) <item>1 <item>2 <item>3 = t ? (with-vprint-output (xblock 0 (print-list-atoms L2))) <item>1 <item>2 <item>3 <item>4 <item>5 <item>6 <item>7 <item>8 <item>9 <item>10 <item>11 11 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx <item>12 <item>13 <item>14 <item>15 = t Pour les initie's, remarquons que dans ce dernier mode il est pre'fe'rable d'introduire un point de coupure de`s le de'but pour e'viter les interfe'rences avec les blocs pre'ce'dents. La bonne fac,on d'imprimer une liste en xblock est ainsi : ? (de print-list-atoms-xblock (l) ? (xblock 0 ? (vcutpoint "") ? (vpatom (nextl l)) ? (while l ? (vcutpoint) ? (vpatom (nextl l))))) = print-list-atoms-xblock 1.3 Autres Commandes (vterpri) Cette fonction de'clenche un saut de ligne inconditionnel. (vindent <indent>) <indent> est un entier, cette fonction augmente le renfoncement du bloc de composition courant de la valeur <indent>. (begin-hblock) Cette fonction de'clenche l'ouverture d'un bloc horizontal qui devra e↑tre ferme' ulte'rieurement par (end-block). La construction hblock est de'finie a` l'aide de cette fonction par: (defmacro hblock (indent . body) 12 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx `(progn (begin-hblock) (vindent ,indent) ,@body (end-block))) (begin-vblock) Identique a` la pre'ce'dente pour les blocs verticaux. (begin-xblock) Identique a` la pre'ce'dente pour les blocs mixtes. (end-block) Ferme un bloc de quelque nature qu'il soit. 2 Le Programme Standard d'Impression En plus de la machine de composition pre'sente'e dans la section pre'ce'dente, nous donnons un programme standard d'impression pour les expressions Lisp et Ceyx. Au moment de l'e'criture de cette documentation (Septembre 1984), le nombre de formats de composition de'finis en standard n'est pas suffisant pour obtenir un paragraphage ide'al de toutes les expressions Lisp. Ceci sera comple'te' avec le temps. 2.1 Fonctions Ge'ne'rales (vprint <expr> [profondeur]) Cette fonction re'alise un paragraphage (pretty-print) de l'expression <expr>, jusqu'a` la profondeur donne'e en second argument ou jusqu'a` la profondeur standard contenue dans la variable {Vprint}:level (valant par de'faut (printlevel)). Ceci signifie que l'impression s'arre↑te a` la profondeur dite, le 13 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx symbole # e'tant alors imprime' a` la place de la sous-expression correspondante. ? (vprint '(a b c)) (a b c) = t ? (vprint '((a b)(c d))) ((a b) (c d)) = t ? (vprint '((a b)(c d)) 1) (# #) = t (vpretty <function-name> [profondeur]) Cette fonction re'alise le paragraphage (pretty-print) de la fonction de nom <function-name>. ? (vpretty print-list-atoms) (de print-list-atoms (l) (vpatom (nextl l)) (while l (vcutpoint) (vpatom (nextl l)))) = t 2.2 Contro↑le du format d'impression par l'utilisateur La fonction vprint peut e↑tre de'finie en Lisp par: (de vprint (x) (let ((x (car args)) ({Vprint}:level (if (cadr args) (cadr args) {Vprint}:level))) (with-vprint-output (vprin x)))) et c'est la fonction vprin qui se charge de la composition suivant les cas. 14 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx (vprin <expr>) Cette fonction se charge d'aiguiller la composition de l'expression <expr>. Elle peut e↑tre de'finie en Lisp par: (de vprin (x) (let (({Vprint}:curlevel (1+ {Vprint}:curlevel))) (if (> {Vprint}:curlevel {Vprint}:level) (vprincn #/#) (cond ((tconsp x) (sendq vprin x)) ((null x) (vpatom "()")) ((stringp x) (vprincn #/") (vpatom x) (vprincn #/")) ((atom x) (vpatom x)) ((consp x) (if (symbolp (car x)) (selectq (ptype (car x)) (1 ({Vformat}:progn x)) (2 ({Vformat}:if x)) (3 ({Vformat}:defun x)) (4 ({Vformat}:cond x)) (5 ({Vformat}:selectq x)) (6 ({Vformat}:setq x)) (t (let ((vformat (getprop (car x) 'vformat))) (ifn vformat ({Vformat}:data x) (funcall vformat x))))) ({Vformat}:data x))) (t (syserror 'vprin "Type Lisp Inconnu")))))) Pour les objets atomiques, le comportement de cette fonction est clair, nous nous attachons dans la suite au cas des objets qui sont des tcons ou des cons. 2.2.1 Composition des Objets Tagge's (tcons) Dans le cas ou` elle rencontre un objet tagge', la fonction vprin envoie le message vprin a` l'objet en question. 15 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx De'finissons par exemple le Trecord toto par: ? (deftrecord toto a b c) = toto ? (setq x (omakeq toto a 1 b 2 c 3)))) = #(toto 1 2 . 3) Si nous ne de'finissons pas de se'mantique vprin pour toto, la se'mantique vprin du mode`le * est re'cupe're'e, on obtient ainsi une composition identique a` celle fournie par Le←Lisp: ? (vprint x) #(toto 1 2 . 3) = t puisque {*}:vprin est de'fini par: ? (de {*}:vprin (x) (prin x)) = #:*:vprin L'utilisateur peut changer ce format en rede'finissant la se'mantique vprin pour le mode`le toto: ? (de {toto}:vprin (x) ? (vblock 3 ? (vpatom 'toto) ? (vcutpoint) ? (vpatom "a: ") ? (vprin ({toto}:a x)) ? (vcutpoint) ? (vpatom "b: ") ? (vprin ({toto}:b x)) ? (vcutpoint) ? (vpatom "c: ") ? (vprin ({toto}:c x)))) = #:Model:Tmodel:toto:vprin ? (vprint x) toto 16 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx a: 1 b: 2 c: 3 = t 2.2.2 Composition des Objets de Type Cons Conforme'ment a` l'usage dans les pretty-printer Lisp, les objets de type cons sont compose's suivant la valuer de leur car. Dans le cas ou` ce car n'est pas un atome on appliquera le format par de'faut (i.e. {Vformat}:data), sinon on regarde si un format n'a pas e'te' attache' a` cet atome. Pour ce faire nous regardons tout d'abord leur ptype a` la Le←Lisp et sinon nous regardons sur la pliste de cet atome si une fonction de composition leur a e'te' attache' sous la proprie'te' vformat. Pour associer une fonction de composition a` un atome, nous de'finissons la fonction deformat: (deformat <symbol> (<arg>) . <body>)) Cette construction de'finit la fonction {Vformat}:<symbol>, et attache le symbole {Vformat}:symbol sur la pliste de <symbol> sous l'indicateur vformat de manie`re a` ce qu'il puisse e↑tre re'cupe're' par vprin: (de {Vformat}:symbol (<arg>) ,@<body>) Dans le cas ou` l'appel a` la forme (deformat <symbol>1 <symbol>2) {Vformat}:<symbol>2 est attache' a` <symbol>1 sous l'indicateur vformat. Exemples: Le format standard est de'fini par: (deformat data (l) 17 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx (hblock 1 (vprincn #/() (vplist l) (vprincn #/)))) Le format 'progn' est de'fini par (nous rappelons que la variable {Vprint}:indent contient un entier qui est le renfoncement par de'faut): (deformat progn (l) (xblock {Vprint}:indent (vprincn #/() (vplist l) (vprincn #/)))) ou` vplist est de'finie par: (vplist <lexpr>) (de vplist (l) (vprin (nextl l)) (while (consp l) (vcutpoint) (vprin (nextl l))) (when l (vcutpoint) (vprincn #/.) (vcutpoint) (vprin l))) Le format 'setq' est de'fini par: (deformat setq (l) (xblock {Vprint}:indent (vprincn #/() (vprin (nextl l)) (while l (vcutpoint) (xblock 2 (vprin (nextl l)) (vcutpoint) (vprin (nextl l)))) (vprincn #/)))) 18 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx Nous aurons ainsi: ? (rmargin 79) = 79 ? (vprint '(a b c d e f g h i j)) (a b c d e f g h i j) = t ? (vprint '(progn a b c d e f g h i j)) (progn a b c d e f g h i j) = t ? (vprint '(setq a 1 b 2 c 3 d 4 e 5)) (setq a 1 b 2 c 3 d 4 e 5) = t ? (rmargin 10) = 10 ? (vprint '(a b c d e f g h i j)) (a b c d e f g h i j) = t ? (vprint '(progn a b c d e f g h i j)) (progn a b c d e f g h i j) = t ? (vprint '(setq a 1 b 2 c 3 d 4 e 5)) (setq a 1 b 2 c 3 d 4 e 5) = t 19 Mercredi 3 Octobre 1984 Vprint Le Composeur Ceyx 20 Mercredi 3 Octobre 1984 Table des matie`res 1 Mercredi 3 Octobre 1984 Table des matie`res Table des matie`res 1 La Machine de Composition..............................4 1.1 Impression des Atomes................................4 1.2 Les Blocs de Composition.............................5 1.2.1 Les Blocs Horizontaux..............................6 1.2.2 Les Blocs Verticaux................................8 1.2.3 Les Blocs Mixtes...................................8 1.2.4 Exemples...........................................9 1.3 Autres Commandes....................................12 2 Le Programme Standard d'Impression....................13 2.1 Fonctions Ge'ne'rales.................................13 2.2 Contro↑le du format d'impression par l'utilisateur...14 2.2.1 Composition des Objets Tagge's (tcons).............15 2.2.2 Composition des Objets de Type Cons...............17 2 Mercredi 3 Octobre 1984 Index des fonctions Lisp 1 Mercredi 3 Octobre 1984 Index des fonctions Lisp Index des fonctions Lisp (begin-hblock) .........................................12 (begin-vblock) .........................................13 (begin-xblock) .........................................13 (deformat <symbol> (<arg>) . <body>)) ..................17 (end-block) ............................................13 (hblock <indent> <expr>1 ... <expr>n) ...................6 (vblock <indent> <expr>1 ... <expr>n) ...................8 (vcutpoint <atom>) ......................................6 (vcutpoint) .............................................6 (vindent <indent>) .....................................12 (vpatom <atom>) .........................................5 (vplist <lexpr>) .......................................18 (vpretty <function-name> [profondeur]) .................14 (vprin <expr>) .........................................15 (vprinch <char>) ........................................5 (vprincn <charn>) .......................................5 (vprint <expr> [profondeur]) ...........................13 (vterpri) ..............................................12 (with-vprint-output <expr>1 ... <expr>n) ................4 (xblock <indent> <expr>1 ... <expr>n) ...................8 {Vprint}:indent [variable] ..............................7 2 Mercredi 3 Octobre 1984