home *** CD-ROM | disk | FTP | other *** search
/ messroms.de / 2007-01-13_www.messroms.de.zip / ORIC1 / IMAGES / ORICLISP.ZIP / manuel.txt < prev    next >
Text File  |  1995-11-20  |  60KB  |  1,680 lines

  1.  
  2.  
  3.  
  4.             Manuel de rΘfΘrence ORICLISP
  5.  
  6.                (C) F.FrancΦs 1986,1995
  7.  
  8.  
  9.  
  10.  
  11.  
  12.                  Table des matiΦres
  13.  
  14. I. Une introduction au langage LISP................................  2
  15.   I.1 Syntaxe......................................................  3
  16.   I.2 L'interprΦte.................................................  3
  17.   I.3 Les fonctions prΘdΘfinies....................................  4
  18.         a) QUOTE...................................................  4
  19.         b) Les sΘlecteurs CAR et CDR...............................  4
  20.         c) Les constructeurs.......................................  5
  21.         d) Les prΘdicats...........................................  5
  22.         e) La conditionnelle et les structures de contr⌠le.........  6
  23.         f) L'arithmΘtique..........................................  6
  24.         g) L'affectation...........................................  6
  25.         h) La dΘfinition de fonctions..............................  7
  26.  
  27. II. PrΘsentation d'OricLisp........................................  8
  28.   II.1 Principales caractΘristiques................................  8
  29.   II.2 Premier contact.............................................  8
  30.         a) L'Θcran et le clavier...................................  9
  31.         b) L'Θdition de lignes.....................................  9
  32.   II.3 Les primitives OricLisp..................................... 10
  33.         a) QUOTE................................................... 10
  34.         b) Les sΘlecteurs.......................................... 10
  35.         c) Les constructeurs....................................... 11
  36.         d) Les prΘdicats........................................... 12
  37.         e) La conditionnelle et les structures de contr⌠le......... 13
  38.         f) L'arithmΘtique.......................................... 14
  39.         g) Les modifications physiques
  40.          et les fonctions α effet de bord...................... 15
  41.         h) La dΘfinition de fonction............................... 17
  42.   II.4 Concepts avancΘs............................................ 18
  43.         a) Fonctions sans Θvaluation............................... 18
  44.         b) Macro-caractΦres........................................ 19
  45.         c) Macro-fonctions......................................... 19
  46.         d) Fonctions d'ordre supΘrieur............................. 21
  47.  
  48. A. Annexe A: Copyright............................................. 21
  49. B. Annexe B: DΘfinitions formelles................................. 22
  50. C. Annexe C: Portage de programmes MuLisp.......................... 24
  51. D. Annexe D: DΘtails d'implΘmentation.............................. 26
  52.         a) Carte mΘmoire........................................... 26
  53.         b) Structures de donnΘes................................... 26
  54.         c) La pile virtuelle....................................... 27
  55.         d) Le ramasse-miettes...................................... 27
  56. E. Annexe E: Exemple............................................... 28
  57.  
  58.  
  59.                                 - 1 -
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68. I. Une introduction au langage LISP
  69. -----------------------------------
  70.  
  71.     LISP est un langage crΘΘ en 1964 par John MacCarthy pour traiter des
  72. informations organisΘes en arbres binaires (formules mathΘmatiques, phrases de
  73. la langue naturelle, connaissances...). Ces arbres sont reprΘsentΘs par des
  74. listes en LISP (qui est une abrΘviation de LISt-Processing).
  75.     La capacitΘ de LISP α traiter des informations symboliques en a fait
  76. un des "langages machine" de domaines de l'informatique tels que l'Intelligence
  77. Artificielle, la Robotique, le Calcul Formel, la ThΘorie de la Programmation
  78. (les preuves de programme par exemple), la thΘorie des jeux, les Θditeurs 
  79. syntaxiques (type Emacs) et plus gΘnΘralement les environnements de programma-
  80. -tion, etc.
  81.     Pour le situer par rapport aux autres langages, on a l'habitude de
  82. considΘrer trois familles de langages (certains langages sont bien s√r α
  83. l'intersection de ces familles): les langages impΘratifs comme Fortran, Pascal,
  84. Cobol, Basic, Ada, C... o∙ une suite d'ordres permet de converger vers la
  85. solution; les langages dΘclaratifs comme Prolog o∙ l'on se contente de dΘcrire
  86. le problΦme (c'est une logique dΘductive qui permet d'aller vers la solution);
  87. les langages fonctionnels et applicatifs comme LISP, ML, FP o∙ l'on applique
  88. des fonctions au sens mathΘmatique du terme (il n'y a plus de "variables" dans
  89. le programme). On peut considΘrer que les premiers langages α objets comme
  90. SmallTalk descendent de LISP, et on trouve aussi son influence dans le langage
  91. LOGO.
  92.     Hormis cette classification, les principales caractΘristiques des 
  93. langages fonctionnels de la famille LISP sont les suivantes (il n'y a en effet
  94. pas un mais des dialectes LISP: InterLisp, MacLisp, VLisp, LeLisp, MuLisp,
  95. FranzLisp...):
  96.     - ils procΦdent par composition de fonctions rΘcursives alors que les
  97. langages classiques (impΘratifs) procΦdent par rΘpΘtition de sΘquences
  98. d'affectation.
  99.     - ils manipulent des arborescences et un programme est un arbre de mΩme
  100. nature qu'un arbre de donnΘes (un programme peut donc Ωtre traitΘ par un autre
  101. programme !)
  102.     - ils sont structurΘs et modulaires (par composition de fonctions)
  103.     - ils sont interactifs (le dialogue avec l'interprΦte permet de
  104. construire les programmes de maniΦre incrΘmentale)
  105.     - la gestion de la mΘmoire est dynamique et automatique (grΓce α un
  106. "ramasse-miettes" qui rΘcupΦre les donnΘes qui ne sont plus utilisΘes)
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.                                 - 2 -
  120.  
  121.  
  122. I.1 Syntaxe
  123. -----------
  124.     Un programme LISP est un arbre binaire, soit, comment donc le
  125. reprΘsenter avec une suite de caractΦres ASCII ? Bien s√r, il n'est pas question
  126. de faire un dessin, alors il a ΘtΘ choisi d'utiliser les parenthΦses, l'espace
  127. et le point pour reprΘsenter ces arborescences. DΦs que l'on aura remarquΘ que 
  128. les deux branches d'un arbre binaire sont elles-mΩmes des arbres, on acceptera
  129. sans peine la reprΘsentation suivante dite "paire pointΘe":  ( S1 . S2 )
  130. o∙ S1 et S2 sont aussi soit des paires pointΘes soit des feuilles de l'arbre,
  131. que l'on appelle des "atomes".
  132.     Les atomes, comme en physique, sont donc les ΘlΘments constitutifs et
  133. deux sortes sont distinguΘes : les nombres entiers (parfois aussi des rΘels) et
  134. les "symboles" qui sont des identificateurs et jouent le r⌠le de donnΘes
  135. abstraites. Par exemple, deux symboles sont utilisΘs pour reprΘsenter les
  136. boolΘens classiques : NIL pour "Faux" et T pour "Vrai" (bien que tout ce qui
  137. n'est pas NIL est aussi "Vrai"). De plus, NIL sert aussi pour dΘnoter le "Vide",
  138. la liste vide plus prΘcisΘment...
  139.     Puisque nous Θvoquons le terme de "liste", prΘcisons que les listes sont
  140. des arbres particuliers (les arbres sont appelΘs "S-expressions" en LISP) : il a
  141. ΘtΘ choisi de faire porter le premier ΘlΘment d'une liste par la partie gauche
  142. de la paire pointΘe et la suite de la liste par la partie droite, ce qui fait
  143. qu'une liste de fruits s'Θcrirait, α l'aide de paires pointΘes :
  144. ( pomme . ( poire . ( abricot . nil ) ) )
  145.     Les listes sont tellement courantes que la notation ci-dessus est peu
  146. pratique et l'on a bien s√r une premiΦre Θcriture abrΘgΘe :
  147.     ( pomme poire abricot . nil )
  148. C'est une simplification d'Θcriture qui donne une signification spΘciale
  149. α la sΘparation par des espaces α l'intΘrieur de parenthΦses. On abrΦge encore
  150. cette Θcriture en donnant la signification de fin de liste au symbole NIL avec :
  151.     ( pomme poire abricot )
  152. Voilα qui est bien plus simple ! Mais pour compliquer un peu, rappelons
  153. qu'une liste est une S-expression; rien n'empΩche donc un ou des ΘlΘments d'une
  154. liste d'Ωtre eux-mΩmes des listes... Par exemple,
  155.     ( marcel (age 20) (enfants (lucie (age 2)) (alain (age 1)) ) )
  156. est une liste de 3 ΘlΘments ! Le premier est un atome, le second une liste de
  157. deux atomes, le troisiΦme une liste d'un atome et de deux listes... on commence
  158. α comprendre que savoir compter les parenthΦses va Ωtre important !
  159.  
  160. I.2 L'interprΦte
  161. ----------------
  162.     Comment ? On change de paragraphe sans donner la syntaxe des programmes
  163. LISP ? Eh oui, si vous savez construire des listes, vous savez programmer !
  164. Un programme LISP, c'est une S-expression, disons plut⌠t un atome ou une liste,
  165. que l'interprΦte va "Θvaluer". Par exemple, si vous donnez un nombre α Θvaluer
  166. α l'interprΦte, il vous renverra ce mΩme nombre (facile...). Si vous donnez un
  167. symbole α Θvaluer, l'interprΦte retournera la "valeur" de ce symbole s'il en a
  168. une, par exemple : MON_DOCTEUR pourrait s'Θvaluer en 
  169.     (Dugenou Leon (23 chemin du cubitus))
  170. Enfin, si vous donnez une liste α Θvaluer, l'interprΦte considΦrera que le
  171. premier ΘlΘment de la liste est une fonction et que les autres ΘlΘments sont les
  172. arguments donnΘs α la fonction. Par exemple : 
  173.     (+ 2 2) renverra 4
  174.     (CAR MON_DOCTEUR) renverra Dugenou, on verra en effet plus loin que CAR
  175. est une fonction qui renvoie le premier ΘlΘment d'une liste.
  176.  
  177.  
  178.  
  179.                                 - 3 -
  180.  
  181.  
  182.     L'interprΦte LISP peut donc Ωtre dΘcrit par l'application successive des
  183. trois fonctions suivantes :
  184. - READ qui lit une S-expression (nous dirons par la suite une expression pour 
  185. simplifier) au clavier ou depuis un fichier.
  186. - EVAL qui Θvalue la valeur d'une expression.
  187. - PRINT qui affiche une expression sur l'Θcran ou dans un fichier.
  188. Selon le dialecte LISP utilisΘ, cet interprΦte peut Ωtre une fonction standard
  189. (TOPLEVEL ou DRIVER ou autre), dont la dΘfinition contient une composition des
  190. trois fonctions prΘcΘdentes : (PRINT (EVAL (READ)))
  191. On remarque que les arguments Θtant ΘvaluΘs avant d'Ωtre passΘs aux fonctions,
  192. c'est la fonction READ qui est invoquΘe d'abord, son rΘsultat est passΘ α la
  193. fonction EVAL, et le rΘsultat d'EVAL est envoyΘ α PRINT ! (on verra que la
  194. plupart des fonctions Θvaluent leurs arguments, c'est l'appel par valeur, seules
  195. quelques fonctions ne les Θvaluent pas, comme les structures de controles, on
  196. parle alors d'appel par nom).
  197.     C'est donc la fonction EVAL qui est au coeur du langage LISP: lorsque
  198. vous demandez (+ 2 2), c'est elle qui invoquera le code de la fonction addition.
  199.  
  200.  
  201. I.3 Les fonctions prΘdΘfinies
  202. -------------------------
  203.     Tous les dialectes LISP partagent un mΩme noyau minimal de fonctions qui
  204. est suffisant pour Θcrire n'importe quel programme. Les dialectes se diffΘren-
  205. -cient par des jeux de fonctions Θtendus, plus ou moins riches, qui permettent
  206. d'Θcrire les programmes de maniΦre plus concise. Nous dΘcrivons ici un noyau
  207. minimal:
  208.  
  209. a) QUOTE
  210. --------
  211.     QUOTE est une fonction qui permet de protΘger son argument de l'Θvalua-
  212. -tion. Elle n'Θvalue donc pas son argument et le renvoie tel quel en rΘsultat.
  213. Exemple:
  214.     (QUOTE (+ 2 2))    -->    (+ 2 2)
  215. Son usage trΦs courant fait qu'une abrΘviation a ΘtΘ dΘfinie :
  216.     'A     -->   A
  217.     '(CAR MON_DOCTEUR)    -->   (CAR MON_DOCTEUR)
  218.  
  219. Pour les curieux, le caractΦre ' est un "macro-caractΦre", c.a.d que c'est en
  220. fait une fonction qui s'Θvalue dΦs qu'elle est rencontrΘe dans le flot de
  221. caractΦres venant du clavier (l'action du macro-caractΦre ' est d'invoquer la
  222. fonction READ pour lire l'expression suivante, puis de construire une liste avec
  223. QUOTE en premier ΘlΘment et cette expression en second ΘlΘment, et enfin de
  224. renvoyer cette liste !)
  225.  
  226.  
  227. b) Les sΘlecteurs CAR et CDR
  228. ----------------------------
  229.     Ces fonctions Θvaluent leur argument, CAR prend la partie gauche de la
  230. paire pointΘe donnΘe en argument et CDR la partie droite (les noms de ces
  231. fonctions viennent hΘlas de l'appellation A et D de registres de la premiΦre
  232. machine ayant implΘmentΘ LISP...)
  233. Exemple:
  234.     (CAR '(+ 2 3))    -->  +
  235.     (CAR '((A B) C))  -->  (A B)
  236.     (CDR '(+ 2 3))    -->  (2 3)
  237.     (CDR '((A B) C))  -->  (C)
  238.  
  239.                                 - 4 -
  240.  
  241.  
  242. Suivant les dialectes LISP, appliquer la fonction CAR α un atome peut renvoyer
  243. une erreur ou la valeur de cet atome. De mΩme, la fonction CDR appliquΘe α un
  244. atome peut retourner une erreur ou une liste de propriΘtΘs associΘes α l'atome
  245. (ces deuxiΦmes possibilitΘs permettent d'appliquer CAR et CDR α n'importe quelle
  246. expression LISP, mais il vaut mieux rΘserver ces fonctions aux paires pointΘes 
  247. (listes ou arbres) par souci de portabilitΘ).
  248.  
  249.  
  250.  
  251. c) Les constructeurs
  252. --------------------
  253.     CONS est la fonction constructeur de base : elle construit une paire
  254. pointΘe α partir de deux expressions.
  255. Exemple:
  256.     (CONS 'A 'B)       -->  (A.B)
  257.     (CONS 'A '(B C))   -->  (A B C)
  258.     (CONS '(A B) '(C)) -->  ((A B) C)
  259.     (CONS 'A NIL)      -->  (A)
  260.     (CONS NIL '(A))    -->  (NIL A)
  261.  
  262. LIST existe toujours pour simplifier la construction de listes de longueur
  263. quelconque. La fonction LIST accepte un nombre quelconque d'arguments.
  264. Exemple:
  265.     (LIST 'a 'b 'c 'd)    -->  (a b c d)
  266.     (LIST 'a '(b c) 'd)   -->  (a (b c) d)
  267.  
  268.  
  269. d) Les prΘdicats
  270. ----------------
  271.     Ce sont des fonctions renvoyant une valeur boolΘenne (NIL reprΘsente la
  272. valeur "Faux", tout autre rΘsultat est "Vrai"), elles Θvaluent leurs arguments.
  273. ATOM     renvoie T si son argument est un atome,    sinon NIL.
  274. NUMBERP    renvoie T si son argument est un nombre,   sinon NIL.
  275. CONSP    renvoie T si son argument est une liste,   sinon NIL.
  276. NULL    renvoie T si son argument est NIL,         sinon NIL.
  277. EQUAL    renvoie T si ses arguments sont Θgaux,     sinon NIL.
  278. EQ    renvoie T si ses arguments sont les mΩmes, sinon NIL.
  279.  
  280. Ces deux derniers mΘritent une petite explication: EQ teste si les deux objets
  281. donnΘs en argument ne font qu'un en mΘmoire (ΘgalitΘ physique) tandis que EQUAL
  282. compare toutes les branches des objets pour vΘrifier qu'ils ont mΩme reprΘsenta-
  283. -tion externe.
  284. Exemple:
  285.     (ATOM 'A)       -->  T
  286.     (ATOM '(A))     -->  NIL
  287.     (ATOM '())      -->  T  en effet, () est la liste vide reprΘsentΘe par
  288.                 l'atome NIL !
  289.     (NULL 'A)    -->  NIL
  290.     (NULL '(A))    -->  NIL
  291.     (NULL NIL)    -->  T
  292.     (EQUAL '(A (B C) D)  '(A (B C) D))    -->  T
  293.     (EQ    '(A (B C) D)  '(A (B C) D))    -->  NIL
  294.     (EQUAL 'A 'A)    -->  T
  295.     (EQ    'A 'A)    -->  T    car les atomes sont prΘsents de maniΦre unique
  296.                 en mΘmoire...
  297.  
  298.  
  299.                                 - 5 -
  300.  
  301.  
  302. e) La CONDitionnelle
  303. --------------------
  304.     COND accepte en paramΦtre un nombre quelconque de clauses (non ΘvaluΘes)
  305. de la forme "(prΘdicat expression)". COND n'Θvalue pas ses arguments α priori,
  306. mais Θvalue sΘquentiellement les prΘdicats dans les clauses jusqu'α en trouver
  307. un "Vrai" (non NIL), dans ce cas il Θvalue l'expression associΘe dans la clause 
  308. et la renvoie en rΘsultat. Sinon (tous les prΘdicats ont ΘtΘ ΘvaluΘs α NIL), 
  309. COND renvoie NIL.
  310. Exemple:
  311.     (COND ((EQ 'A 'A) 'OUI))  -->  OUI
  312.     (COND ((EQ 'A 'B) 'OUI))  -->  NON
  313.     (COND    ((EQ 'A 'B) 'OUI)
  314.         (T        'NON))       -->  NON
  315.             ce qui montre l'utilisation de T comme dernier prΘdicat,
  316.             mais on peut s'en passer comme suit :
  317.     (COND    ((EQ X 1) 'PREMIER)
  318.         ((EQ X 2) 'DEUXIEME)
  319.         ((EQ X 3) 'TROISIEME)
  320.         (         'AUTRE))    --> PREMIER, DEUXIEME, TROISIEME ou AUTRE
  321.                     suivant la valeur de X...
  322.  
  323.  
  324.  
  325. f) L'arithmΘtique
  326. -----------------
  327.     Les noms de fonction varient d'un dialecte α un autre, mais on trouvera
  328. toujours les 4 opΘrations et des prΘdicats d'ordre.
  329. Exemple:
  330.     (- 239 (* 7 (/ 239 7)))    -->  1
  331.     (< 3 7)               -->  T
  332.  
  333.  
  334.  
  335. g) L'affectation
  336. ----------------
  337.     Pour les puristes, c'est une horreur comme un GOTO dans un langage
  338. structurΘ. En pratique, on rΘserve souvent son usage au niveau le plus haut d'un
  339. programme pour associer un nom α une valeur, comme on peut le faire en mathΘma-
  340. -tique, mais on se garde de modifier cette association (les symboles ne sont
  341. pas des variables !) pour Θviter les effets de bord.
  342. Exemple:
  343.     (SETQ A '(1 2 3))       -->  (1 2 3)
  344.     A            -->  (1 2 3)
  345. SETQ n'Θvalue pas son premier argument (symbole), et renvoie son second argument
  346. aprΦs l'avoir associΘ au symbole. SET est encore plus dangereux car il Θvalue
  347. aussi le premier argument:
  348.     (SETQ B 'A)    -->  A
  349.     B        -->  A
  350.     (SET B '(A B))    -->  (A B)
  351.     B        -->  A
  352.     A        -->  (A B)
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.                                 - 6 -
  360.  
  361.  
  362. h) La dΘfinition de fonctions
  363. -----------------------------
  364.     Une fonction LISP est une expression de la forme
  365.         (LAMBDA (param1 param2 ... paramN) expr)
  366. o∙ param1, param2 ... paramN sont les noms des paramΦtres formels et expr le
  367. corps de la fonction.
  368. Exemple:
  369.     (LAMBDA (X) X)    est la fonction identitΘ (elle renvoie son argument)
  370.     (LAMBDA (X Y)
  371.       (COND    ((ATOM X) (CONS X Y))
  372.         (T      (CONS (CAR X) Y))))
  373.             est une fonction qui rajoute X en tΩte de la liste Y si
  374.             X est un atome, sinon rajoute le CAR de X en tΩte de la
  375.             liste Y.
  376.  
  377. La maniΦre d'associer une dΘfinition de fonction α un nom n'est pas standard,
  378. LeLisp utilise la fonction DE (par exemple: "(DE IDENTITE(X) X)" ), VLisp range
  379. la dΘfinition dans la liste de propriΘtΘ d'un atome, d'autres associent la
  380. dΘfinition α la valeur d'un atome. Pour la suite, nous utiliserons la fonction
  381. MuLisp PUTD.
  382. Exemple:
  383.     (PUTD 'IDENTITE '(LAMBDA(X) X))
  384. En MuLisp, les atomes ont par dΘfaut pour valeur eux-mΩmes, ce qui permet de
  385. supprimer l'apostrophe (quote) devant le nom de fonction lorsque aucune valeur
  386. ne lui est associΘe. Allez, quelques classiques :
  387.  
  388.     (PUTD LENGTH
  389.       '(LAMBDA (X)
  390.          (COND ((NULL X) 0)
  391.            (T         (+ 1 (LENGTH (CDR X))))
  392.     )  ) )
  393.         calcule la longueur d'une liste: (LENGTH '(A B C)) --> 3
  394.     (PUTD MEMBER
  395.       '(LAMBDA (X L)
  396.          (COND ((NULL L)          NIL)
  397.            ((EQUAL X (CAR L)) T)
  398.            (T              (MEMBER X (CDR L)))
  399.     )  ) )
  400.         cherche si une expression est prΘsente dans une liste :
  401.             (MEMBER '(A B) '(A B (A (A B)) (B A) (A B))  --> T
  402.         car on trouve (A B) en quatrieme position.
  403.     (PUTD FACT
  404.       '(LAMBDA (N)
  405.          (COND ((EQ N 0) 1)
  406.            (T        (* N (FACT (- N 1))))
  407.     )  ) )
  408.         calcule la factorielle d'un nombre...
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.                                 - 7 -
  420.  
  421.  
  422. II. PrΘsentation d'OricLisp
  423. ---------------------------
  424.     OricLisp est un dialecte LISP inspirΘ de LeLisp (JΘr⌠me Chailloux) pour
  425. les fonctions dΘfinies par l'utilisateur (LAMBDA, FLAMBDA, MLAMBDA, cf plus bas)
  426. et de MuLisp (Albert D.Rich, David R.Stoutemyer, Roy Feldman) pour tout le reste
  427. mΩme si l'implΘmentation est trΦs diffΘrente (MuLisp a ΘtΘ implΘmentΘ sur les
  428. processeurs Intel 8080 et 8086).
  429. Un nombre relativement faible de fonctions sont prΘdΘfinies (plus de 60 tout de
  430. mΩme !) afin de laisser le maximum d'espace disponible α l'utilisateur, mais
  431. ses caractΘristiques puissantes permettent de dΘvelopper des applications trΦs
  432. consΘquentes.
  433.     OricLisp a ΘtΘ Θcrit en 1986 (mais ce manuel ne l'a suivi qu'en 1995 !).
  434.  
  435.  
  436.  
  437. II.1 Principales caractΘristiques:
  438. ----------------------------------
  439. * sauvegarde d'images mΘmoire permettant de reprendre une session au point
  440. exact o∙ elle a ΘtΘ sauvΘe, ou d'enrichir le langage par des dΘfinitions
  441. personnalisΘes, ou de produire des applications Lisp dΘmarrant automatiquement.
  442. * arithmΘtique entiΦre sur 32 bits, exprimΘe dans une base arbitraire (de la
  443. base 2 α la base 36)
  444. * symboles de taille arbitraire (jusqu'α 256 caractΦres) et pouvant comporter
  445. n'importe quel caractΦre ascii (mΩme l'espace). Les symboles peuvent ainsi
  446. jouer le r⌠le de chaεnes de caractΦres.
  447. * pile virtuelle segmentΘe permettant au processeur d'utiliser une pile de prΦs
  448. de 3 Ko avec la rapiditΘ de la pile habituelle de 256 octets.
  449. * espace utilisateur important avec en standard 16 Ko pour les paires pointΘes
  450. et les chaεnes de caractΦres (soit plus de 4000 paires pointΘes), et prΦs de 
  451. 12 Ko pour les atomes. Cette rΘpartition peut Ωtre changΘe.
  452. * ramasse-miettes transparent pour l'utilisateur, compactant tous les espaces
  453. utilisateurs (chaεnes, paires, nombres, symboles).
  454. * fonctions Θvaluant ou n'Θvaluant pas leurs arguments, plus macro-fonctions
  455. et macro-caractΦres !
  456. * espace clos de pointeurs et donnΘes typΘes par leur adresse pour une plus
  457. grande efficacitΘ.
  458.  
  459.  
  460.  
  461. II.2 Premier contact :
  462. ----------------------
  463.     Taper CLOAD"ORICLISP" depuis le Basic 1.1 de l'Oric pour charger et
  464. exΘcuter le systΦme (ou LOAD"ORICLISP" pour un systΦme α disquettes, mais
  465. attention, les images mΘmoires ne sont sauvΘes que sur cassette). La ligne
  466. supΘrieure de l'Oric affiche le copyright, et le prompt "point d'interrogation"
  467. signale que le systΦme attend des caractΦres tapΘs au clavier. Entrer des 
  468. expressions montre que l'interprΦte est actif:
  469. Exemple:
  470.     ? 'HELLO
  471.     =HELLO
  472.     ? (+ 2 2)
  473.     =4
  474.  
  475.  
  476.  
  477.  
  478.  
  479.                                 - 8 -
  480.  
  481.  
  482. a) L'Θcran et le clavier
  483. ------------------------
  484.     Pour plus de rapiditΘ, les routines d'Θcrans ont ΘtΘ redΘfinies, elles
  485. permettent de travailler avec 38 ou 40 colonnes et affichent sur la totalitΘ des
  486. 28 lignes en mode rouleau avec une routine de dΘfilement rapide.
  487.     La scrutation du clavier s'adapte au travail de l'utilisateur: lorsqu'il
  488. est en phase d'entrΘe de caractΦres, elle est effectuΘe tous les 3/100e de
  489. seconde, alors qu'elle n'est effectuΘe qu'une fois par seconde lorsque le
  490. systΦme calcule, et une fois tous les 1/10e de seconde lorsque le systΦme
  491. affiche. Ceci permet d'allier performance et confort d'utilisation, un programme
  492. peut toujours Ωtre stoppΘ en cours de calcul par un Ctrl-C (appuyΘ 1 seconde)
  493. et gagne ainsi environ 15% en vitesse d'exΘcution.
  494.  
  495.  
  496.  
  497. b) L'Θdition de lignes
  498. ----------------------
  499.     Elle est trΦs diffΘrente de celle du Basic et gΦre un buffer de 128
  500. caractΦres (plus de 3 lignes Θcran). La derniΦre entrΘe (terminΘe par la touche
  501. RETURN) est conservΘe dans le buffer pour permettre une correction aisΘe de 
  502. celle-ci.
  503.     Deux modes sont gΘrΘs: insertion et suppression, par dΘfaut le mode
  504. suppression est actif et Ctrl-I permet de basculer du mode suppression au mode
  505. insertion et vice-versa.
  506.     En mode suppression, tout caractΦre ASCII tapΘ vient remplacer le
  507. caractΦre qui occupe la mΩme position dans le buffer (donc remplace un caractΦre
  508. de l'entrΘe prΘcΘdente).
  509.     En mode insertion, tout caractΦre ASCII tapΘ vient s'insΘrer α la
  510. position courante du buffer, dΘcalant ainsi vers la droite le reste du buffer.
  511.     Le dernier caractΦre ASCII (127) a une signification spΘciale puisqu'il 
  512. s'agit de DEL qui dΘtruit le dernier caractΦre tapΘ (et revient donc une 
  513. position plus α gauche dans le buffer). Deux caractΦres de contr⌠le sont dΘfinis
  514. en plus de la bascule insertion/suppression pour utiliser l'entrΘe prΘcedente
  515. conservΘe dans le buffer :
  516.     - Ctrl-A rΘcupΦre en effet le caractΦre courant de l'entrΘe prΘcΘdente,
  517. laisser un Ctrl-A appuyΘ permet de recopier une entrΘe jusqu'au dernier
  518. caractΦre dΘsirΘ.
  519.     - Ctrl-D dΘtruit le prochain caractΦre du buffer. Le rΘsultat de cette
  520. action est malheureusement invisible pour l'utilisateur (tant qu'il n'entre pas
  521. un Ctrl-A).
  522.  
  523. Exemple: supposons que l'utilisateur ait tapΘ la ligne suivante:
  524.     ? (PUTD FACT '(LAMBDA(N) COND ((EQ N 0) 1)) (T (* N (FACT (- N 1))))))
  525.     =(LAMBDA(N) COND ((EQ N 0) 1))
  526. Il s'aperτoit alors sans peine qu'il a oubliΘ une parenthΦse ouvrante avant le
  527. COND et tapΘ une parenthΦse de trop aprΦs la premiΦre clause. Pour corriger son
  528. entrΘe, il suffit qu'il appuie sur Ctrl-A jusqu'α ce que
  529.     ? (PUTD FACT '(LAMBDA(N)
  530. soit affichΘ, puis passer en mode insertion avec Ctrl-I, taper une parenthΦse
  531. ouvrante, de nouveau enfoncer Ctrl-A jusqu'α ce que
  532.     ? (PUTD FACT '(LAMBDA(N) (COND ((EQ N 0) 1)
  533. soit affichΘ, puis dΘtruire la parenthΦse fermante superflue de l'entrΘe
  534. prΘcΘdente par Ctrl-D, et terminer en laissant Ctrl-A enfoncΘ...
  535.  
  536.  
  537.  
  538.  
  539.                                 - 9 -
  540.  
  541.  
  542. II.3 Les primitives OricLisp
  543. ----------------------------
  544.  
  545. a) QUOTE
  546. --------
  547. la fonction QUOTE classique, protΦge son argument de l'Θvaluation.
  548.         ? (QUOTE (+ 2 2))
  549.         =(+ 2 2)
  550. Remarque : le macro-caractΦre ' a le mΩme effet
  551.         ? '(+ 2 2)
  552.         =(+ 2 2)
  553.  
  554.  
  555. b) Les sΘlecteurs
  556. -----------------
  557. * les sΘlecteurs CAR et CDR sont prΘsents, ainsi que les compositions de 2 ou 3
  558. CAR ou CDR (par exemple, "(CADR X)" est l'Θquivalent de "(CAR (CDR X))" ).
  559. OricLisp possΦde un espace clos de pointeurs, on peut toujours appliquer un CAR
  560. ou un CDR sans erreur; dans le cas d'un atome, CAR renvoie la valeur associΘe α
  561. l'atome et CDR la liste de propriΘtΘs associΘe α l'atome. La valeur d'un symbole
  562. est par dΘfaut lui-mΩme (tant qu'aucune valeur ne lui a ΘtΘ liΘe), celle d'un
  563. nombre est toujours le mΩme nombre. La liste de propriΘtΘs d'un symbole est vide
  564. par dΘfaut (elle vaut NIL), celle d'un nombre reflΦte son signe : T pour un
  565. nombre positif ou nul, NIL pour un nombre nΘgatif.
  566. Exemple:
  567.     ? (CAR '(A.B))
  568.     =A
  569.     ? (CADR '(A B C))
  570.     =B
  571.     ? (CDDR '(A B C D))
  572.     =(C D)
  573.  
  574. * LAST renvoie la derniΦre paire pointΘe de premier niveau de son argument (et
  575. non le dernier ΘlΘment) ou NIL si l'argument est un atome. Renvoyer la derniΦre
  576. paire pointΘe plut⌠t que le dernier ΘlΘment permet de modifier cette paire
  577. pointΘe (pour ajouter en fin de liste avec RPLACD par exemple, mais attention
  578. aux effets de ces modifications physiques), et le dernier ΘlΘment peut Ωtre
  579. facilement obtenu avec un CAR supplΘmentaire.
  580. Exemple:
  581.     ? (LAST '(A B C D))
  582.     =(D)
  583.     ? (LAST '(A B.C))
  584.     =(B.C)
  585.     ? (CAR (LAST '(A B C D)))
  586.     =D
  587.  
  588.  
  589. * ASSOC cherche le premier argument (la clef) dans la A-liste fournie par le
  590. deuxiΦme argument. Une A-liste (liste associative) est une liste de la forme
  591.     ((clef1.val1) (clef2.val2) ... (clefN.valN))
  592. ASSOC compare (avec EQUAL) le premier argument avec chacune des clefs (les
  593. ΘlΘments atomiques de la A-liste sont sautΘs) et renvoie l'ΘlΘment complet de
  594. la premiΦre comparaison avec succΦs, sinon NIL. Certains Lisp ne renvoient que
  595. la partie valeur de la paire pointΘe, il suffit de rajouter un CDR pour obtenir
  596. le mΩme rΘsultat (tandis que renvoyer l'ensemble permet de modifier la valeur
  597. associΘe α la clef).
  598.  
  599.                                 - 10 -
  600.  
  601.  
  602. Exemple:
  603.     ? (ASSOC 'MARTIN '((DUPONT JEAN 61586273) (MARTIN JACQUES 61483922)
  604.                 (DUPONT ALAIN 61289019)))
  605.     =(MARTIN JACQUES 61483922)
  606.  
  607. * MEMBER cherche (avec EQUAL) le premier argument dans la liste fournie par le
  608. second argument et renvoie la fin de liste commenτant α l'ΘlΘment trouvΘ, ou
  609. NIL s'il n'est pas trouvΘ. Certains Lisp ne renvoient qu'une valeur boolΘenne T
  610. ou NIL, ici le rΘsultat peut servir (pour dΘtruire l'ΘlΘment de la liste, par
  611. exemple).
  612. Exemple:
  613.     ? (MEMBER '(MARTIN JACQUES 61483922)
  614.           '((DUPONT JEAN 61586273) (MARTIN JACQUES 61483922)
  615.                 (DUPONT ALAIN 61289019)))
  616.     =((MARTIN JACQUES 61483922) (DUPONT ALAIN 61289019)))
  617.  
  618.  
  619. c) Les constructeurs
  620. --------------------
  621. * CONS construit une paire pointΘe avec les deux arguments fournis.
  622. Exemple:
  623.     ? (CONS 'A 'B)
  624.     =(A.B)
  625.     ? (CONS 'A '(B C))
  626.     =(A B C)
  627.  
  628. * LIST construit une liste avec tous les arguments fournis.
  629.     ? (LIST 'a '(b c) 'd)
  630.     =(a (b c) d)
  631.  
  632. * OBLIST construit une liste de tous les symboles
  633.     ? (OBLIST)
  634.     =(LAST OBLIST DIV MOD ................... LAMBDA T NIL)
  635.  
  636. * APPEND construit une liste qui est la concatΘnation des deux listes passΘes
  637. en argument. De nouvelles paires pointΘes sont crΘes pour le dΘbut de cette
  638. liste, contrairement α NCONC. Remarque : APPEND avec un seul argument peut Ωtre
  639. utilisΘ pour copier une liste.
  640.     ? (APPEND '(A (B C) D) '(E F (G H)))
  641.     =(A (B C) D E F (G H))
  642.  
  643. * REVERSE construit une nouvelle liste qui est une liste renversΘe de son
  644. premier argument (l'implΘmentation utilise un deuxiΦme paramΦtre pour cumuler
  645. le rΘsultat partiel. De ce fait, si un deuxiΦme argument est fourni, il sera
  646. concatΘnΘ α la liste renversΘe)
  647.     ? (REVERSE '(A (B C) D))
  648.     =(D (B C) A)
  649.     ? (REVERSE '(A (B C) D) '(E F))
  650.     =(D (B C) A E F)
  651.  
  652. * GC n'est pas un constructeur comme CONS, LIST, OBLIST, APPEND ou REVERSE. Mais
  653. il intervient lui aussi dans la gestion de l'espace mΘmoire. Tous les construc-
  654. -teurs font appel α CONS pour allouer une paire pointΘe. Lorsque plus aucune
  655. paire ne peut Ωtre allouΘe, le ramasse-miettes (Garbage Collector) est invoquΘ
  656. automatiquement. Il peut aussi Ωtre appelΘ explicitement avec la fonction GC.
  657.  
  658.  
  659.                                 - 11 -
  660.  
  661.  
  662. d) Les prΘdicats
  663. ----------------
  664. * EQUAL renvoie T si ses deux arguments sont Θgaux. Toutes les branches sont
  665. comparΘes.
  666.     ? (EQUAL '(A (B C) D) '(A (B C) D))
  667.     =T
  668.  
  669. * EQ renvoie T si ses deux arguments ne sont qu'un mΩme objet en mΘmoire. Il ne
  670. peut exister deux symboles de mΩme nom. Il peut exister plusieurs nombres de
  671. mΩme valeur mais EQ considΦre que ce sont les mΩmes. Lorsque l'on partage des
  672. paires pointΘes, EQ est un test intΘressant, parce qu'il est trΦs rapide (il ne
  673. regarde pas les branches)
  674.     ? (EQ '(A (B C) D) '(A (B C) D))
  675.     =NIL
  676.  
  677. * ATOM renvoie T si son argument est un atome (donc pas une paire pointΘe)
  678.     ? (ATOM 'A)
  679.     =T
  680.     ? (ATOM '(A B))
  681.     =NIL
  682.     ? (ATOM '())
  683.     =T
  684.  
  685. * NULL renvoie T si son argument est NIL (la liste vide)
  686.     ? (NULL 'A)
  687.     =NIL
  688.     ? (NULL '(A B))
  689.     =NIL
  690.     ? (NULL '())
  691.     =T
  692.  
  693. * PLUSP renvoie T si son argument est un nombre positif ou nul.
  694.     ? (PLUSP 0)
  695.     =T
  696.     ? (PLUSP 'A)
  697.     =NIL
  698.  
  699. * MINUSP renvoie T si son argument est un nombre nΘgatif
  700.     ? (MINUSP -3)
  701.     =T
  702.     ? (MINUSP '(A B))
  703.     =NIL
  704.  
  705. * ZEROP renvoie T si son argument est le nombre 0
  706.     ? (ZEROP NIL)
  707.     =NIL
  708.     ? (ZEROP 0)
  709.     =T
  710.  
  711. Remarque : n'importe quelle expression peut servir de prΘdicat puisque toute
  712. valeur non NIL est considΘrΘe comme "Vrai". Par exemple, T est le prΘdicat
  713. toujours vrai, utile pour la derniΦre clause d'une conditionnelle.
  714.  
  715.  
  716.  
  717.  
  718.  
  719.                                 - 12 -
  720.  
  721.  
  722. e) La conditionnelle et les structures de contr⌠le
  723. --------------------------------------------------
  724. * COND est la conditionnelle classique de la forme suivante :
  725.     (COND (pred1 exp11 exp12 ... exp1N)
  726.           (pred2 exp21 exp22 ... exp2M)
  727.         ....
  728.     )
  729. Chaque prΘdicat pred1, pred2 ... est ΘvaluΘ sΘquentiellement jusqu'α trouver
  730. une valeur non NIL pour un prΘdicat predI, alors les expressions associΘes
  731. expI1, expI2... sont ΘvaluΘes en sΘquence, la derniΦre donnant la valeur de
  732. retour du COND (si aucune expression n'est associΘe au prΘdicat, c'est la valeur
  733. du prΘdicat qui est renvoyΘe). Avoir plusieurs expressions au lieu d'une α la
  734. suite du prΘdicat n'est utile que si les expressions ont des effets de bord.
  735. Exemple:
  736.     ? (COND ((< A B) A) (B)) renvoie le minimum des nombres A et B
  737.  
  738. * PROGN Θvalue sΘquentiellement tous ses arguments et renvoie la valeur du
  739. dernier. PROGN n'a d'intΘrΩt que si les expressions font des effets de bord et
  740. peut Ωtre gΘnΘralement omis du fait du PROGN implicite dans les dΘfinitions de
  741. fonction et dans la conditionnelle COND.
  742. Exemple:
  743.     ? (PROGN (PRIN '(FACT 5)) (FACT 5))
  744.     (FACT 5)=120
  745.  
  746. * PROG1 Θvalue sΘquentiellement tous ses arguments et renvoie la valeur du
  747. premier. Son usage est de mΩme liΘ aux effets de bord.
  748. Exemple:
  749.     ? (SETQ A (PROG1 B (SETQ B A))) Θchange les valeurs associΘes α A et B
  750.  
  751. * AND est α la fois le "et" logique classique et une structure de contr⌠le
  752. (Θquivalente α des "si...alors..." imbriquΘs). Les arguments sont ΘvaluΘs en
  753. sΘquence jusqu'α ce qu'une valeur NIL soit trouvΘe, auquel cas le rΘsultat est
  754. NIL et les arguments suivants sont "court-circuitΘs". Si tous les arguments
  755. s'Θvaluent α une valeur non NIL, la valeur du dernier est renvoyΘe, le rΘsultat
  756. est donc "Vrai".
  757. Exemple:
  758.     ? (AND (ZEROP 1) (PRINT 'ARGH))
  759.     =NIL    et on remarque que le deuxiΦme argument n'est pas ΘvaluΘ
  760.     ? (AND A B C) est Θquivalent α (COND (A (COND (B (COND (C))))))
  761.  
  762. * OR est α la fois le "ou" logique classique et une structure de contr⌠le (une
  763. suite de "si...alors...sinon si"). Les arguments sont ΘvaluΘs en sΘquence
  764. jusqu'α ce qu'une valeur non NIL soit trouvΘe (cette valeur est alors retournΘe
  765. et l'Θvaluation des arguments restants est court-circuitΘe). Si tous les
  766. arguments sont NIL, NIL est renvoyΘ.
  767. Exemple:
  768.     ? (OR NIL '() 'A (PRINT 'ARGH))
  769.     =A
  770.     ? (OR A B C) est Θquivalent α (COND (A) (B) (C))
  771.  
  772. * NOT est le "non" logique (ce n'est pas une structure de contr⌠le mais il
  773. permet d'inverser la signification de prΘdicats) et renvoie T si son argument
  774. est NIL, sinon NIL. NOT est donc identique au prΘdicat NULL.
  775. Exemple:
  776.     ? (NOT NIL)
  777.     =T
  778.  
  779.                                 - 13 -
  780.  
  781.  
  782. * WHILE est une structure de contr⌠le de style impΘratif de la forme
  783.     (WHILE pred exp1 exp2 ... expN)
  784. Tant que pred s'Θvalue α "Vrai" (non NIL), WHILE itΦre sur l'Θvaluation de exp1,
  785. exp2 ... expN (il faut donc nΘcessairement un effet de bord pour que la valeur
  786. de pred devienne NIL). WHILE est implΘmentΘ sans rΘcursivitΘ et permet donc des
  787. boucles importantes (ou infinies) sans saturation de la pile.
  788. Exemple:
  789.     ? (WHILE T (PRINT (EVAL (READ)))
  790.         une boucle infinie pour un nouvel interprΦte !
  791.     ? (WHILE (NOT (ZEROP N)) (SETQ N (- N 1)))
  792.     =NIL
  793.         dΘcrΘmente N jusqu'α 0
  794.  
  795.  
  796.  
  797. f) L'arithmΘtique
  798. -----------------
  799. * RADIX change la base pour la reprΘsentation des nombres entrΘs au clavier et
  800. affichΘs α l'Θcran. La nouvelle base est donnΘe en argument et doit Ωtre
  801. comprise entre 2 et 36 (au delα de la base 10, jusqu'α 26 lettres peuvent Ωtre
  802. employΘes). RADIX renvoie la nouvelle base en rΘsultat (mais on peut remarquer
  803. que l'affichage d'une base est toujours "10"). Si un argument non numΘrique est
  804. fourni, la base n'est pas changΘe et est renvoyΘe en rΘsultat.
  805. Exemple:
  806.     ? (RADIX 8)
  807.     =10
  808.     ? (+ 6 7)
  809.     =15
  810.     ? (RADIX 12)
  811.     =10
  812.     ? (+ 6 7)
  813.     =13
  814.  
  815.  
  816. * les 4 opΘrations entiΦres sont +,-,*,/. Elles prennent deux nombres en
  817. argument et renvoient le rΘsultat. Une erreur NONNUMERIC est levΘe si un
  818. opΘrande n'est pas un nombre et l'erreur DIVBYZERO est levΘe en cas de division
  819. par 0. / renvoie le quotient de la division entiΦre tandis que MOD renvoie le
  820. reste. Souvent, quotient et reste sont tous deux utiles, DIV permet de ne faire
  821. qu'une fois la division et renvoie un paire pointΘe (quotient.reste)
  822. Exemple:
  823.     ? (DIV 10 3)
  824.     =(3.1)
  825.  
  826.  
  827. * les prΘdicats d'ordre sont < et >. Ils renvoient T si l'ordre est vΘrifiΘ
  828. entre les deux arguments et NIL sinon. Les comparaisons au sens large (ΘgalitΘ
  829. incluse) ne sont pas des primitives, il faut inverser le test.
  830. Exemple:
  831.     ? (NOT (< A B))
  832.         renvoie T si A>=B, et NIL sinon.
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.                                 - 14 -
  840.  
  841.  
  842. g) Les modifications physiques et les fonctions α effet de bord
  843. ---------------------------------------------------------------
  844.  
  845. * SETQ lie la valeur fournie par le second argument au symbole spΘcifiΘ par
  846. le premier (le premier argument n'est pas ΘvaluΘ). Si le symbole Θtait local
  847. α une fonction, la liaison est perdue α la sortie de la fonction.
  848. Exemple:    
  849.     ? (SETQ A '(1 2))
  850.     =(1 2)
  851.     ? A
  852.     =(1 2)
  853.     ? (SETQ A 'B)
  854.     =B
  855.     ? A
  856.     =B
  857.  
  858.  
  859. * SET lie la valeur fournie par le second argument au symbole spΘcifiΘ par le
  860. premier (les deux arguments sont ΘvaluΘs).
  861. Exemple:
  862.     ? (SETQ A 'B)
  863.     =B
  864.     ? (SET A 3)
  865.     =3
  866.     ? B
  867.     =3
  868.     ? A
  869.     =B
  870.  
  871.  
  872. * RPLACA et RPLACD remplacent respectivement le CAR et le CDR de la paire 
  873. pointΘe donnΘe en premier argument par le deuxiΦme argument, et renvoient la 
  874. paire modifiΘe.
  875. Exemple:
  876.     ? (SETQ A '(1 2))
  877.     =(1 2)
  878.     ? (RPLACA A 0)
  879.     =(0 2)
  880.     ? A
  881.     (0 2)
  882.     ? (RPLACD A '(3 4))
  883.     =(0 3 4)
  884.     ? A
  885.     (0 3 4)
  886.  
  887.  
  888. * NCONC est la concatΘnation de liste, comme APPEND mais sans consommation de
  889. paire pointΘe. NCONC modifie la fin de la liste donnΘe par son premier argument
  890. pour lui faire suivre la deuxiΦme liste.
  891. Exemple:
  892.     ? (SETQ A '(1 2))
  893.     =(1 2)
  894.     ? (NCONC A '(3 4 5))
  895.     =(1 2 3 4 5)
  896.     ? A
  897.     =(1 2 3 4 5)
  898.  
  899.                                 - 15 -
  900.  
  901.  
  902. * MEMORY permet de lire ou d'Θcrire un octet en mΘmoire. Si un seul argument est
  903. donnΘ, c'est une adresse dont MEMORY renverra le contenu. Si deux arguments
  904. numΘriques sont donnΘs, MEMORY change l'adresse mΘmoire avec l'octet donnΘ en
  905. second argument, et renvoie l'ancienne valeur.
  906. Exemple:
  907.     ? (RADIX 16)
  908.     =10
  909.     ? (MEMORY 26B 1)
  910.     =7    change la couleur de papier...
  911.  
  912. * TIME renvoie la valeur d'une horloge en 1/100e de secondes et peut donc servir
  913. α mesurer le temps d'exΘcution d'un programme.
  914. Exemple:
  915.     ? (SETQ T1 (TIME)) (GC) (- (TIME) T1)
  916.     =5
  917.  
  918. * PRINT affiche l'expression donnΘe en paramΦtre, et retourne cette expression
  919. en rΘsultat. PRIN fait la mΩme chose mais sans terminer par un retour charriot.
  920. Exemple:
  921.     ? (PRINT 'HELLO)
  922.     HELLO
  923.     =HELLO
  924.     ? (PRINT '(A (B C) D))
  925.     (A (B C) D)
  926.     =(A (B C) D)
  927.     ? (PRIN 0)
  928.     0=0
  929.  
  930. * READ lit une expression au clavier et la renvoie en rΘsultat. Si plus d'une
  931. expression est donnΘe, les autres restent dans le buffer clavier α la disposi-
  932. -tion d'un READ ultΘrieur.
  933. Exemple:
  934.     ? (PRIN '(+ 2 2)) (+ 2 2)
  935.     (+ 2 2)=(+ 2 2)
  936.     =4
  937.     ? (SETQ A (READ)) (+ 2 2)
  938.     =(+ 2 2)
  939.         On remarque que (+ 2 2) n'a pas ΘtΘ lu par l'interprΦte mais
  940.         bien par le READ.
  941.  
  942. * SAVE produit sur cassette une image mΘmoire du nom de l'argument donnΘ en
  943. paramΦtre. Il n'y a pas de fonction LOAD, une image mΘmoire contient le noyau
  944. OricLisp et dΘmarre automatiquement au point exact du SAVE en tapant la commande
  945. CLOAD du Basic de l'Oric.
  946. Exemple:
  947.     ? (PROGN (SAVE 'IMAGE1) 'HELLO)
  948.     =HELLO    et un fichier IMAGE1 est Θcrit sur cassette que l'on lancera
  949.         depuis le Basic :
  950.     CLOAD"IMAGE1"
  951.     =HELLO
  952.     ?
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.                                 - 16 -
  960.  
  961.  
  962. h) La dΘfinition de fonction
  963. ----------------------------
  964. * Une fonction OricLisp Θvaluant ses arguments est une expression de la forme
  965.     (LAMBDA (param1 ... paramN) exp1 exp2 ... expM)
  966. o∙ param1 ... paramN sont les noms des paramΦtres formels et exp1, exp2 ... expM
  967. le corps de la fonction (l'Θvaluation d'une LAMBDA comporte donc un PROGN
  968. implicite).
  969. Exemple:
  970.     (LAMBDA () (/ (TIME) 100))
  971.         une fonction sans paramΦtres qui renvoie l'horloge en secondes
  972.     (LAMBDA (N) (+ N 1))
  973.         une fonction qui renvoie le nombre successeur de son argument
  974.  
  975. Attention ! le deuxiΦme ΘlΘment de la liste de la fonction (les paramΦtres
  976. formels) doit impΘrativement Ωtre une liste (Θventuellement vide).
  977.  
  978. Les LAMBDA sont des fonctions "sans nom" qui peuvent Ωtre utilisΘes de la mΩme
  979. faτon que les primitives du langage.
  980. Exemple:
  981.     ? ( (LAMBDA(N)(+ N 1)) 3)
  982.     =4
  983. Pour associer un nom α une LAMBDA, on utilise la primitive PUTD.
  984.     ? (PUTD 'INCR '(LAMBDA(N)(+ N 1)))
  985.     =(LAMBDA (N) (+ N 1))
  986.     ? (INCR 3)
  987.     =4
  988. Remarque : un symbole peut simultanΘment avoir une valeur, une liste de
  989. propriΘtΘs et une dΘfinition de fonction associΘes.
  990. Exemple:    
  991.     ? (SETQ INCR '(1 2))
  992.     =(1 2)
  993.     ? (INCR 3)
  994.     =4
  995.     ? INCR
  996.     =(1 2)
  997.  
  998. * GETD permet de lire la dΘfinition de fonction d'un symbole. GETD renvoie la
  999. LAMBDA d'une fonction dΘfinie en LISP, T pour une fonction en langage machine
  1000. et NIL si la fonction n'est pas dΘfinie.
  1001. Exemple:
  1002.     ? (GETD 'T)
  1003.     =NIL
  1004.     ? (GETD 'EVAL)
  1005.     =T
  1006.     ? (GETD 'INCR)
  1007.     =(LAMBDA (N) (+ N 1))
  1008.  
  1009. * MOVD permet de copier la dΘfinition de fonction d'un symbole dans un autre
  1010. symbole, dΘfinissant un synonyme pour une fonction sans consommer d'espace
  1011. mΘmoire supplΘmentaire (en dehors du symbole).
  1012. Exemple:
  1013.     ? (MOVD 'APPEND 'COPY)
  1014.     =T
  1015.     ? (COPY '(A B (C D) E))
  1016.     =(A B (C D) E)
  1017.  
  1018.  
  1019.                                 - 17 -
  1020.  
  1021.  
  1022. II.4 Concepts avancΘs
  1023. ---------------------
  1024.  
  1025.  
  1026. a) Fonctions sans Θvaluation
  1027. ----------------------------
  1028.  
  1029.     OricLisp permet de dΘfinir des fonctions n'Θvaluant pas leurs
  1030. arguments, une telle fonction est de la forme
  1031.     (FLAMBDA param exp1 exp2 ... expM)
  1032. Un seul symbole est fourni en paramΦtre formel, il sera liΘ α la liste de tous
  1033. les paramΦtres non-ΘvaluΘs.
  1034. Les fonctions n'Θvaluant pas leurs arguments permettent de dΘfinir de
  1035. nouvelles structures de contr⌠le (elles sont parfois aussi utilisΘes
  1036. pour dΘfinir des fonctions dont le nombre de paramΦtres est indΘterminΘ)
  1037. Exemple:
  1038.     (FLAMBDA L
  1039.       (COND ((EVAL (CAR L)) (EVAL (CADR L))) 
  1040.         (T              (EVAL (CADDR L)))
  1041.     ) )                dΘfinit un IF X THEN Y ELSE Z !!
  1042. que l'on liera bien s√r de la faτon suivante:
  1043.     ? (PUTD 'IF '(FLAMBDA L
  1044.     ?              (COND ((EVAL (CAR L)) (EVAL (CADR L)))
  1045.     ?                    (T              (EVAL (CADDR L))) )))
  1046.     =(FLAMBDA L (COND ((EVAL (CAR L))(EVAL (CADR L))) (T (EVAL (CADDR L)))))
  1047.     ? (IF NIL (PRINT 'ARGH) (PRINT 'OK))
  1048.     OK
  1049.     =OK    et on constate qu'effectivement, le "alors" n'est pas ΘvaluΘ,
  1050.         contrairement α ce qui serait arrivΘ si on avait dΘfini le IF
  1051.         par (LAMBDA (X Y Z) (COND (X Y) (Z)))
  1052.  
  1053. Exemple:
  1054.     (PUTD 'PLUS '(FLAMBDA L
  1055.       (COND ((NULL L) 0)
  1056.         ((+ (EVAL (CAR L)) (PLUS (CDR L))))
  1057.     )))
  1058.         dΘfinit une opΘration PLUS qui somme tous ses arguments
  1059.     ? (PLUS 1 2 3 4 5 6 7)
  1060.     =28
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.                                 - 18 -
  1080.  
  1081.  
  1082. b) Macro-caractΦres
  1083. -------------------
  1084.  
  1085.     Les macro-caractΦres sont des caractΦres qui ont une fonction associΘe
  1086. appelΘe lorsqu'ils sont rencontrΘs durant une lecture clavier. Le caractΦre
  1087. apostrophe (quote) est le seul macro-caractΦre dΘfini par dΘfaut. READ consulte
  1088. une table (α l'adresse $8000) pour savoir si un caractΦre est un macro-
  1089. caractΦre. Pour dΘfinir un macro-caractΦre, il suffit de positionner un octet
  1090. dans cette table et d'associer une fonction au caractΦre choisi.
  1091.  
  1092. Exemple:
  1093.     ? (PUTD '"#" '(LAMBDA () (EVAL (READ))))
  1094.     =(LAMBDA NIL (EVAL (READ)))
  1095.     ? (RADIX 16) (MEMORY (+ 8000 3) FF)
  1096.     =10
  1097.     =0    # a pour code ASCII 23h, la table commence au caractΦre 20h...
  1098.     ? (SETQ N 8) (PUTD 'TEST '(LAMBDA (X) (/ X #(* N N))))
  1099.     =8
  1100.     =(LAMBDA (X) (/ X 64))
  1101.         et on constate que l'expression prΘcΘdΘe de # a ΘtΘ ΘvaluΘe...
  1102.     ? (QUOTE # (+ 2 2))
  1103.     =4    ... mΩme α l'intΘrieur d'une expression protΘgΘe
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109. c) Macro-fonctions
  1110. ------------------
  1111.  
  1112.     Les macro-fonctions sont des fonctions α double Θvaluation dΘfinies
  1113. ainsi :
  1114.         (MLAMBDA param exp1 exp2 ... expN)
  1115.  
  1116. Un seul symbole est fourni en paramΦtre formel; α l'exΘcution il est liΘ α
  1117. l'ensemble de la liste invoquant la macro (sans Θvaluation), y compris la
  1118. fonction qui apparaεt en tΩte de liste. Le corps de la macro est exΘcutΘ (les
  1119. expressions exp1 ... expN) et le rΘsultat est de nouveau fourni α l'Θvaluation !
  1120. Le but d'une macro est donc le suivant : remplacer l'appel α la macro par une
  1121. autre expression.
  1122.  
  1123. Exemple:
  1124.     (PUTD 'IF '(MLAMBDA L
  1125.       (LIST 'COND
  1126.         (LIST (CADR L) (CADDR L))
  1127.         (LIST (CAR (CDDDR L)))
  1128.     )))
  1129.         dΘfinit une macro "IF" qui va construire une expression COND
  1130.         contenant les arguments du IF.
  1131.  
  1132. Ainsi,
  1133.     (IF (PLUSP N) N (- 0 N))
  1134. va construire la liste
  1135.     (COND ((PLUSP N) N) ((- 0 N)))
  1136. puis celle-ci sera ΘvaluΘe, donnant la valeur absolue de N.
  1137.  
  1138.  
  1139.                                 - 19 -
  1140.  
  1141.  
  1142. Ce mΘcanisme puissant qui peut paraεtre bien inefficace pour dΘfinir une
  1143. fonction IF (appel de la macro, parcours des arguments et allocation de paires
  1144. pointΘes pour construire une expression COND, avant d'enfin Θvaluer cette
  1145. derniΦre), surtout lorsque l'on compare α la version du IF avec FLAMBDA, rΘvΦle
  1146. tout son intΘrΩt dans le cadre des macro-fonctions "Θcrasantes". Modifions
  1147. lΘgΦrement la dΘfinition du IF ainsi :
  1148.     (PUTD 'IF '(MLAMBDA L
  1149.       (RPLACA L 'COND)
  1150.       (RPLACD L (LIST (LIST (CADR L) (CADDR L))
  1151.               (LIST (CAR (CDDDR L)))))
  1152.     ))
  1153.         et maintenant le IF va se remplacer une fois pour toute par un
  1154.         COND α la premiΦre exΘcution.
  1155. Exemple:
  1156.     ? (PUTD 'FACT '(LAMBDA (N)
  1157.     ?    (IF (ZEROP N) 1 (* N (FACT (- N 1))))))
  1158.     =(LAMBDA (N) (IF (ZEROP N) 1 (* N (FACT (- N 1)))))
  1159.     ? (FACT 3)
  1160.     =6
  1161.     ? (GETD 'FACT)
  1162.     =(LAMBDA (N) (COND ((ZEROP N) 1) ((* N (FACT (- N 1))))))
  1163. α la premiΦre exΘcution du IF, le code de FACT s'est modifiΘ ! Le code est
  1164. maintenant plus efficace que si on utilisait un IF implΘmentΘ avec une FLAMBDA !
  1165.  
  1166. Ce genre de manipulation est intΘressant dans le cadre de portage de programmes
  1167. LISP d'une machine α une autre (par exemple, ici, lorsque le IF n'existe pas)
  1168. ou pour dΘfinir efficacement des fonctions. Les macros ne sont jamais trΦs
  1169. lisibles, et plus dΘlicates α Θcrire que des LAMBDA normales, mais utiliser des
  1170. macros rend souvent un programme plus lisible sans perdre en efficacitΘ.
  1171. Exemple:
  1172.     la construction LET existe dans de nombreux LISP pour dΘfinir des
  1173. symboles locaux α un bloc. Ainsi, le IF prΘcΘdent s'Θcrirait plus lisiblement :
  1174.     (PUTD 'IF '(MLAMBDA L
  1175.       (LET (
  1176.         (X (CADR L))
  1177.         (Y (CADDR L))
  1178.         (Z (CAR (CDDDR L)))
  1179.            )
  1180.          (RPLACA L 'COND)
  1181.          (RPLACD L (LIST (LIST X Y) (LIST Z)))
  1182.     )))
  1183.  
  1184. le LET peut Ωtre dΘfini efficacement par une macro le remplaτant en LAMBDA :
  1185.     (PUTD 'LET '(MLAMBDA L
  1186.       (RPLACA L (CONS 'LAMBDA
  1187.               (CONS (ALLCAR (CADR L))
  1188.                 (CDDR L))))
  1189.       (RPLACD L (ALLCADR (CADR L)))
  1190.     ))
  1191. o∙ ALLCAR et ALLCADR permettent de rΘcupΘrer respectivement les paramΦtres
  1192. formels et les arguments effectifs :
  1193.     (PUTD 'ALLCAR '(LAMBDA (L)
  1194.      (COND ((NULL L) NIL)
  1195.            ((CONS (CAAR L) (ALLCAR (CDR L)))))))
  1196.     (PUTD 'ALLCADR '(LAMBDA (L)
  1197.      (COND ((NULL L) NIL)
  1198.            ((CONS (CADAR L) (ALLCADR (CDR L)))))))
  1199.                                 - 20 -
  1200.  
  1201.  
  1202. d) Fonctions d'ordre supΘrieur
  1203. ------------------------------
  1204. OricLisp permet de passer une fonction en paramΦtre d'une autre fonction.
  1205. Toutefois, le premier ΘlΘment d'une liste (la fonction) n'est jamais ΘvaluΘ par
  1206. la fonction EVAL, on ne peut donc invoquer directement une fonction obtenue en
  1207. argument. Par exemple, la fonctionnelle classique MAP (qui applique une fonction
  1208. α tous les ΘlΘments d'une liste et renvoie la liste des rΘsultats) ne peut
  1209. s'Θcrire ainsi avec OricLisp :
  1210.     (PUTD 'MAP '(LAMBDA (F L)
  1211.       (COND ((NULL L) NIL)
  1212.         ((CONS (F (CAR L))
  1213.                (MAP F (CDR L)))))))
  1214. parce que le symbole F en position de fonction ne sera pas ΘvaluΘ (Remarque :
  1215. dans beaucoup de dialectes LISP, cette dΘfinition de MAP ne marche que si F n'a
  1216. pas de dΘfinition associΘe).
  1217. De plus, OricLisp n'a pas de fonction APPLY mais les constructions de type
  1218. (APPLY F ARGS) peuvent Ωtre facilement remplacΘes par (EVAL (CONS F ARGS)).
  1219. Ainsi, le MAP peut s'Θcrire :
  1220.     (PUTD 'MAP '(LAMBDA (F L)
  1221.       (COND ((NULL L) NIL)
  1222.         ((CONS (APPLY F (LIST (CAR L)))
  1223.                (MAP F (CDR L)))))))
  1224. et cette dΘfinition marche sans restriction. APPLY peut Ωtre dΘfini par une
  1225. simple (LAMBDA (F L) (EVAL (CONS F L)))
  1226. ou par une macro :
  1227.     (MLAMBDA L
  1228.       (RPLACA L 'EVAL)
  1229.       (RPLACD L (LIST (LIST 'CONS (EVAL (CADR L)) (EVAL (CADDR L)))))).
  1230. Exemple:
  1231.     ? (MAP '(LAMBDA(X)(* X X)) '(1 2 3 4 5))
  1232.     =(1 4 9 16 25)
  1233.     ? (MAP 'PLUSP '(1 8 -2 6 -3))
  1234.     =(T T NIL T NIL)
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245. A. Annexe A: Copyright
  1246. ----------------------
  1247. Le programme OricLisp et le prΘsent manuel sont Copyright Fabrice FrancΦs.
  1248. Ils sont distribuΘs gratuitement et vous ne devez avoir payΘ que le prix
  1249. du support pour les avoir: il y a de meilleurs moyens de dΘpenser votre
  1250. argent, par exemple en me l'envoyant ! J'accepte les donations envoyΘes
  1251. α l'adresse suivante :
  1252.  
  1253.     Fabrice FrancΦs
  1254.     16, allΘe du Vaucluse
  1255.     31770 COLOMIERS
  1256.     FRANCE
  1257.  
  1258.  
  1259.                                 - 21 -
  1260.  
  1261.  
  1262. B. Annexe B: DΘfinitions formelles
  1263. ----------------------------------
  1264.     Pour le "LISPien", une fonction LISP vaut mieux qu'un long discours,
  1265. comment mieux dΘcrire le comportement d'une primitive sinon avec son code Θcrit
  1266. en LISP ? Bon nombre des fonctions implΘmentΘes en langage machine dans OricLisp
  1267. peuvent Ωtre Θcrites en LISP, mais elle seraient alors moins efficaces et
  1268. souvent trΦs consommatrices d'espace de pile (α cause des rΘcursivitΘs).
  1269.     Le noyau vraiment minimal est composΘ des dΘfinitions LAMBDA, FLAMBDA,
  1270. MLAMBDA et des primitives READ, EVAL, PRIN, COND, CAR, CDR, CONS, PUTD, GETD,
  1271. NULL, ATOM, RPLACA, RPLACD, EQ, TIME, MEMORY, RADIX, <, >, +, -, *, /, MOD.
  1272. Les autres peuvent s'Θcrire en fonction de ces primitives de base. Les dΘfini-
  1273. -tions qui suivent ont exactement le mΩme comportement que les routines en
  1274. langage machine (elles renvoient les mΩmes rΘsultats en toutes circonstances),
  1275. mΩme si l'implΘmentation effective est diffΘrente pour des raisons de
  1276. performance. Les seules primitives implΘmentΘes de faτon rΘcursive sont LIST et
  1277. APPEND (elles ne le devraient pas...). Enfin, APPLY n'est pas un symbole dΘfini
  1278. dans OricLisp, mais il existe en interne; il peut Ωtre dΘfini par
  1279. (PUTD 'APPLY '(LAMBDA (F ARGS) (EVAL (CONS F ARGS))))
  1280. mΩme si l'implΘmentation rΘelle ne consomme pas de paire pointΘe.
  1281.  
  1282. (PUTD 'AND
  1283.   '(FLAMBDA L
  1284.     (COND ((ATOM L) T)
  1285.           ((ATOM (CDR L)) (EVAL (CAR L)))
  1286.           ((EVAL (CAR L)) (APPLY 'AND (CDR L))))))
  1287.  
  1288. (PUTD 'APPEND
  1289.   '(LAMBDA (X Y)
  1290.       (COND ((ATOM X) Y)
  1291.         ((CONS (CAR X) (APPEND (CDR X) Y))))))
  1292.  
  1293. (PUTD 'ASSOC '(LAMBDA (X L)
  1294.         (COND    ((ATOM L) NIL)
  1295.                   ((ATOM (CAR L)) (ASSOC X (CDR L))
  1296.                   ((EQUAL X (CAAR L)) (CAR L))
  1297.                   ((ASSOC X (CDR L))))))
  1298.  
  1299. (PUTD 'CAAAR '(LAMBDA (X) (CAAR (CAR X))))
  1300. (PUTD 'CAADR '(LAMBDA (X) (CAAR (CDR X))))
  1301. (PUTD 'CADAR '(LAMBDA (X) (CADR (CAR X))))
  1302. (PUTD 'CADDR '(LAMBDA (X) (CADR (CDR X))))
  1303. (PUTD 'CDAAR '(LAMBDA (X) (CDAR (CAR X))))
  1304. (PUTD 'CDADR '(LAMBDA (X) (CDAR (CDR X))))
  1305. (PUTD 'CDDAR '(LAMBDA (X) (CDDR (CAR X))))
  1306. (PUTD 'CDDDR '(LAMBDA (X) (CDDR (CDR X))))
  1307. (PUTD 'CAAR '(LAMBDA (X) (CAR (CAR X))))
  1308. (PUTD 'CADR '(LAMBDA (X) (CAR (CDR X))))
  1309. (PUTD 'CDAR '(LAMBDA (X) (CDR (CAR X))))
  1310. (PUTD 'CDDR '(LAMBDA (X) (CDR (CDR X))))
  1311.  
  1312. (PUTD 'DIV '(LAMBDA (X Y) (CONS (/ X Y) (MOD X Y))))
  1313.  
  1314. (PUTD 'EQUAL
  1315.   '(LAMBDA (X Y)
  1316.        (COND ((ATOM X) (EQ X Y))
  1317.          ((ATOM Y) NIL)
  1318.          ((EQUAL (CAR X) (CAR Y)) (EQUAL (CDR X) (CDR Y))))))
  1319.                                 - 22 -
  1320.  
  1321.  
  1322. (PUTD 'LAST '(LAMBDA (L)
  1323.         (COND    ((ATOM L) NIL)
  1324.                   ((ATOM (CDR L)) L)
  1325.                   ((LAST (CDR L))))))
  1326.  
  1327. (PUTD 'LENGTH '(LAMBDA (L)
  1328.          (COND    ((ATOM L) 0)
  1329.                   ((+ 1 (LENGTH (CDR L)))))))
  1330.  
  1331. (PUTD 'LIST 
  1332.   '(FLAMBDA L 
  1333.       (COND ((ATOM L) NIL)
  1334.         ((CONS (EVAL (CAR L)) (APPLY 'LIST (CDR L)))))))
  1335.     
  1336. (PUTD 'MEMBER 
  1337.   '(LAMBDA (X L)
  1338.     (COND ((ATOM L) NIL)
  1339.           ((EQUAL X (CAR L)) L)
  1340.           ((MEMBER X (CDR L))))))
  1341.  
  1342. (PUTD 'NCONC '(LAMBDA (X Y)
  1343.                (COND ((ATOM X) Y)
  1344.               (T (RPLACD (LAST X) Y) X))))
  1345.  
  1346. (PUTD 'OR '(FLAMBDA L
  1347.         (COND    ((ATOM L) NIL)
  1348.                   ((EVAL (CAR L)))
  1349.                   ((APPLY 'OR (CDR L))))))
  1350.  
  1351. (PUTD 'PROG1
  1352.   '(FLAMBDA L
  1353.     (COND ((ATOM L) NIL)
  1354.           (T ((LAMBDA (X) (APPLY 'PROGN (CDR L)) X) (EVAL (CAR L)))))))
  1355.  
  1356. (PUTD 'PROGN 
  1357.   '(FLAMBDA L
  1358.     (COND ((ATOM L) NIL)
  1359.           ((ATOM (CDR L)) (EVAL (CAR L)))
  1360.           (T (EVAL (CAR L)) (APPLY 'PROGN (CDR L))))))
  1361.  
  1362. (PUTD 'QUOTE '(FLAMBDA L (CAR L)))
  1363.  
  1364. (PUTD 'REVERSE
  1365.   '(LAMBDA (X Y)
  1366.     (COND ((ATOM X) NIL)
  1367.           ((ATOM (CDR X)) (CONS (CAR X) Y))
  1368.           ((REVERSE (CDR X) (CONS (CAR X) Y))))))
  1369.  
  1370. (PUTD 'SET '(LAMBDA (X Y) (RPLACA X Y) Y)))
  1371.  
  1372. (PUTD 'SETQ '(FLAMBDA L (COND ((NAME (CAR L)) (SET (CAR L) (EVAL (CADR L)))))))
  1373.  
  1374. (PUTD 'WHILE 
  1375.   '(FLAMBDA L
  1376.       (COND ((EVAL (CAR L)) 
  1377.         (APPLY 'PROGN (CDR L)) 
  1378.         (APPLY 'WHILE L)))))
  1379.                                 - 23 -
  1380.  
  1381.  
  1382. C. Annexe C: portage de programmes MuLisp
  1383. -----------------------------------------
  1384.  
  1385. En dehors de l'Θvaluation des fonctions utilisateurs (LAMBDA, FLAMBDA, MLAMBDA),
  1386. OricLisp possΦde des primitives trΦs proches de celles de MuLisp, il est donc
  1387. aisΘ de porter des programmes de MuLisp vers OricLisp (et vice-versa). Pour
  1388. laisser plus de place α l'utilisateur, OricLisp ne dΘfinit pas toutes les
  1389. fonctions qui existent dans MuLisp. 
  1390. On pourra utiliser les dΘfinitions suivantes qui fournissent un Θquivalent
  1391. exact :
  1392.  
  1393.  
  1394. (PUTD 'NTH '(LAMBDA (N L)
  1395.     (COND    ((ZEROP N) (CAR L))
  1396.         ((ATOM L) NIL)
  1397.         ((NTH (- N 1) (CDR L)))))) pour une version α la MacLisp
  1398.  
  1399. (PUTD 'NTH '(LAMBDA (L N)
  1400.     (COND    ((EQ N 1) L)
  1401.         ((ATOM L) NIL)
  1402.         ((NTH (CDR L) (- N 1)))))) pour une version α la InterLisp
  1403.  
  1404. (PUTD 'TCONC '(LAMBDA (PTR OBJ)
  1405.     (SETQ OBJ (LIST OBJ))
  1406.     (COND    ((ATOM PTR) (CONS OBJ OBJ))
  1407.         ((ATOM (CDR PTR)) (RPLACA PTR OBJ) (RPLACD PTR OBJ))
  1408.         (T (RPLACD (CDR PTR) OBJ) (RPLACD PTR OBJ)))))
  1409.  
  1410. (PUTD 'LCONC '(LAMBDA (PTR L)
  1411.     (COND    ((ATOM L) PTR)
  1412.         ((ATOM PTR) (CONS L (LAST L)))
  1413.         ((ATOM (CDR PTR)) (RPLACA PTR L) (RPLACD PTR (LAST L)))
  1414.         (T (RPLACD (CDR PTR) L) (RPLACD PTR (LAST L))))))
  1415.  
  1416. (PUTD 'EVENP '(LAMBDA (N) (COND ((NUMBERP N) (ZEROP (MOD N 2))))))
  1417.  
  1418. (PUTD 'POP '(FLAMBDA P
  1419.     (COND    ((NOT (NAME (CAR P))) NIL)
  1420.         ((ATOM (CAAR P)) NIL)
  1421.         ((PROG1 (CAAAR P) (SET (CAR P) (CDAAR P)))))))
  1422.  
  1423. (PUTD 'PUSH '(FLAMBDA P
  1424.     (COND    ((NULL (CADR P)) NIL)
  1425.         ((NAME (CADR P)) (SET (CADR P) (CONS (EVAL (CAR P)) 
  1426.                              (CADR P)))))))
  1427.  
  1428. (PUTD 'PUT '(LAMBDA (NAM KEY OBJ)
  1429.   ((LAMBDA(ELEM) 
  1430.     (COND ((NULL ELEM) (RPLACD NAM (CONS (CONS KEY OBJ) (CDR NAM))) OBJ)
  1431.           (T (RPLACD ELEM OBJ) OBJ)))  (ASSOC KEY (CDR NAM)))))
  1432.  
  1433. (PUTD 'GET '(LAMBDA (NAM KEY) (CDR (ASSOC KEY (CDR NAM)))))
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.                                 - 24 -
  1440.  
  1441.  
  1442. (PUTD 'REMPROP '(LAMBDA (NAM KEY)
  1443.     (COND ((ATOM (CDR NAM)) NIL)
  1444.           ((EQUAL (CAADR NAM) KEY)
  1445.             (SETQ KEY (CDADR NAM))
  1446.             (RPLACD NAM (CDDR NAM))
  1447.             KEY)
  1448.           ((REMPROP (CDR NAM) KEY)))))
  1449.  
  1450. (PUTD 'FLAGP '(LAMBDA (NAM ATT) (MEMBER ATT (CDR NAM))))
  1451.  
  1452. (PUTD 'FLAG '(LAMBDA (NAM ATT)
  1453.     (COND ((FLAGP NAM ATT) ATT)
  1454.           (T (RPLACD NAM (CONS ATT (CDR NAM))) ATT))))
  1455.  
  1456. (PUTD 'REMFLAG '(LAMBDA (NAM ATT)
  1457.     (COND ((ATOM (CDR NAM)) NIL)
  1458.           ((EQUAL ATT (CADR NAM)) (RPLACD NAM (CDDR NAM)) T)
  1459.           ((REMFLAG (CDR NAM) ATT)))))
  1460.  
  1461. (PUTD 'GCD '(LAMBDA (X Y)
  1462.     (COND    ((NOT (ZEROP Y)) (GCD Y (MOD X Y)))
  1463.         ((PLUSP X) X)
  1464.         ((- 0 X)))))
  1465.  
  1466. (PUTD 'COMMENT '(FLAMBDA L NIL))
  1467.  
  1468. Les diffΘrences suivantes peuvent apparaεtre lors d'un portage :
  1469.  
  1470. * le corps d'une fonction MuLisp et d'une fonction OricLisp sont ΘvaluΘs
  1471. diffΘremment. MuLisp implΘmente un COND/PROGN implicite au lieu d'un PROGN
  1472. implicite dans les corps de fonction (et les clauses de COND), ce qui permet
  1473. de rΘduire la taille du code mais introduit une ambigu∩tΘ dans le cas de 
  1474. LAMBDAs qui sont alors prises pour des prΘdicats. Le COND est obligatoire dans
  1475. les corps de fonction OricLisp.
  1476.  
  1477. * PLUSP renvoie NIL pour 0 dans MuLisp et T dans OricLisp. De plus, le CDR
  1478. d'un nombre (la liste de propriΘtΘs) α une signification inversΘe : il vaut T
  1479. pour un nombre positif ou nul dans OricLisp, tandis qu'il vaut T pour un nombre
  1480. nΘgatif dans MuLisp.
  1481. GREATERP et LESSP acceptent plus de deux arguments dans MuLisp, de telles
  1482. expressions doivent Ωtre Θcrites avec plusieurs > et < dans OricLisp. De mΩme,
  1483. PLUS, DIFFERENCE, TIMES admettent plus de deux arguments dans MuLisp, il est
  1484. facile de rΘΘcrire ces expressions avec plusieurs +, - ou *.
  1485.  
  1486. * les fonctions sur les chaεnes de caractΦres de MuLisp (SUBSTRING, FINDSTRING,
  1487. PACK, UNPACK, LENGTH, ASCII) ne sont pas implΘmentables avec OricLisp.
  1488.  
  1489. * les Θchappements de MuLisp (CATCH, THROW) ne sont pas implΘmentables avec 
  1490. OricLisp, le traitement d'erreur non plus.
  1491.  
  1492. * les fonctions de lecture/Θcriture sur fichier ne sont pas disponibles avec
  1493. OricLisp.
  1494.  
  1495. * les puissantes macro-fonctions d'OricLisp n'existent pas avec MuLisp, si un
  1496. programme OricLisp les utilise intensivement, on prΘfΦrera alors porter vers
  1497. un autre dialecte comme LeLisp.
  1498.  
  1499.                                 - 25 -
  1500.  
  1501.  
  1502. D. Annexe D: DΘtails d'implΘmentation
  1503. -------------------------------------
  1504.  
  1505. a) Carte mΘmoire
  1506. ----------------
  1507. 0000 ------------+----------------------------+
  1508.                  |    variables systΦmes      |
  1509. 0100 ------------+----------------------------+
  1510.                  | quatre segments de pile    |
  1511. 0200 ------------+----------------------------+
  1512.                  |    variables systΦmes      |
  1513. 0300 ------------+----------------------------+
  1514.                  |      entrΘes-sorties       |
  1515. 0400 ------------+----------------------------+
  1516.                  |  buffer d'entrΘe clavier   |
  1517.                  |   + zone de conversion     |
  1518. 0500 ------------+----------------------------+-------- BOTTOM
  1519.                  |    pile des liaisons       |
  1520.                  |\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
  1521.                  |                            |
  1522.                  |/\/\/\/\/\/\/\/\/\/\/\/\/\/\|
  1523.                  | segments de pile virtuelle |
  1524. 1000 ------------+----------------------------+-------- SYSTEM
  1525.                  |   chaεnes de caractΦres    |
  1526.                  |\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
  1527.                  |                            |
  1528.                  |/\/\/\/\/\/\/\/\/\/\/\/\/\/\|
  1529.                  |      paires pointΘes       |
  1530. 5000 ------------+----------------------------+-------- ATOMS
  1531.                  |        nombres             |
  1532.                  |\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
  1533.                  |                            |
  1534.                  |/\/\/\/\/\/\/\/\/\/\/\/\/\/\|
  1535.                  |        symboles            |
  1536. 8000 ------------+----------------------------+-------- TOPATOM
  1537.                  |          noyau             |
  1538.                  +----------------------------+
  1539.  
  1540. Les adresses BOTTOM, SYSTEM et ATOMS peuvent Ωtre modifiΘes pour s'adapter aux
  1541. consommations diffΘrentes en nombres et symboles, paires pointΘes ou rΘcursivitΘ
  1542. d'une application. Malheureusement, cette transformation doit se faire en
  1543. modifiant des adresses du noyau AVANT qu'il ne s'exΘcute...
  1544. La page de BOTTOM peut Ωtre changΘe en modifiant l'adresse 9AA6, la page de
  1545. SYSTEM α l'adresse 9AAA et la page d'ATOMS α l'adresse 9AB0.
  1546.  
  1547. b) Structures de donnΘes
  1548. ------------------------
  1549.  
  1550. Les paires pointΘes ont la structure suivante:
  1551.     +----------+------------+
  1552.         |   CAR    |    CDR     |
  1553.     +----------+------------+
  1554.  
  1555. Les symboles ont la structure suivante :
  1556.     +----------+------------+----------+-------------+
  1557.     |  Valeur  | PropriΘtΘs | Fonction | Nom externe |  
  1558.         +----------+------------+----------+-------------+
  1559.                                 - 26 -
  1560.  
  1561.  
  1562. Le CAR d'un symbole donne donc sa valeur, un symbole n'ayant pas reτu de valeur
  1563. a pour valeur lui mΩme (la valeur pointe vers le mΩme symbole).
  1564. Le CDR d'un symbole porte la liste de propriΘtΘs associΘe au symbole, elle est
  1565. NIL par dΘfaut et peut Ωtre changΘe par RPLACD.
  1566. Le champ fonction du symbole est NIL si aucune fonction n'est associΘe, il
  1567. pointe vers la liste LAMBDA (ou FLAMBDA ou MLAMBDA) pour une fonction
  1568. utilisateur, et contient l'adresse de dΘbut pour une fonction en langage
  1569. machine (les deux derniers sont diffΘrenciΘs par le bit de poids fort, il est α
  1570. 1 pour une routine en langage machine au delα de l'adresse 8000h et α 0 pour
  1571. une fonction utilisateur)
  1572. Le champ nom externe (ou Print-name) pointe vers la chaεne de caractΦres
  1573. reprΘsentant le symbole.
  1574.  
  1575. Les nombres ont la structure suivante:
  1576.     +----------+------------+------------------------+
  1577.     |  Valeur  | PropriΘtΘs | reprΘsentation 32 bits |  
  1578.         +----------+------------+------------------------+
  1579.  
  1580. Le CAR d'un nombre (sa valeur) pointe toujours sur lui-mΩme.
  1581. Le CDR d'un nombre (sa propriΘtΘ) est T s'il est positif ou nul, NIL si nΘgatif.
  1582.  
  1583.  
  1584. c) La pile virtuelle
  1585. --------------------
  1586.  
  1587. Le langage LISP est par dΘfinition rΘcursif et ceci pose problΦme pour
  1588. l'implΘmentation sur le processeur 6502 qui possΦde un pointeur de pile 8 bits.
  1589. OricLisp implΘmente une pile virtuelle inΘdite qui lui dispense de simuler une
  1590. pile 16 bits, et lui permet d'utiliser les instructions normales de pile du
  1591. 6502 : JSR, RTS, PHA, PLA...
  1592. La pile virtuelle est constituΘe de segments de 64 octets, 4 segments sont
  1593. donc prΘsents dans la pile physique du 6502. De temps α autre (dans la routine
  1594. EVAL par exemple), la position du pointeur de pile est vΘrifiΘe afin de dΘtecter
  1595. si une frontiΦre de segment a ΘtΘ franchie. Ce franchissement peut provoquer la
  1596. sauvegarde d'un segment de la pile physique vers la pile virtuelle, ou la
  1597. rΘcupΘration d'un segment de la pile virtuelle, mais l'algorithme utilisΘ est
  1598. adaptΘ au parcours rΘcursif d'arbres binaires et fait que le transfert d'un
  1599. segment est peu courant (il n'y a pas de transfert lorsque le pointeur oscille
  1600. de part et d'autre d'une frontiΦre de segment).
  1601.  
  1602.  
  1603. d) Le ramasse-miettes
  1604. ---------------------
  1605.  
  1606. Une premiΦre passe marque les paires et les atomes accessibles α partir des
  1607. champs valeur, propriΘtΘs et fonction des symboles (on ne marque pas un
  1608. symbole dont la valeur pointe sur lui-mΩme et qui n'a pas dΘfinition de
  1609. fonction), ou α partir de la pile des liaisons.
  1610. Une deuxiΦme passe supprime les paires, les symboles et les nombres non marquΘs
  1611. et les compacte.
  1612. Une troisiΦme passe enlΦve le marquage des objets et ajuste les pointeurs vers
  1613. des objets dΘplacΘs par le compactage.
  1614. Une derniΦre passe compacte les chaεnes des symboles qui n'ont pas ΘtΘ ΘliminΘs
  1615. par le ramasse-miettes.
  1616.  
  1617.  
  1618.  
  1619.                                 - 27 -
  1620.  
  1621.  
  1622. E. Annexe E: Exemple du parcours du cavalier
  1623. --------------------------------------------
  1624.  
  1625. Le parcours du cavalier sur un Θchiquier est un problΦme classique qui consiste
  1626. α parcourir toutes les cases de l'Θchiquier une fois et une seule en respectant
  1627. la marche du cavalier aux Θchecs. LISP est bien adaptΘ α ce genre de recherche
  1628. de solution, en voici une rΘsolution assez concise pour un Θchiquier de taille
  1629. N quelconque:
  1630.  
  1631. ; une liste des 8 sauts possibles du cavalier, classΘs par une heuristique :
  1632. (SETQ DIR '((-2 1)(-2 -1)(-1 -2)(1 -2)(2 -1)(2 1)(1 2)(-1 2)))
  1633.  
  1634. ; d'abord une petite fonction qui construit la liste des entiers M,M-1...1
  1635. (PUTD REBOURS '(LAMBDA (M) (COND ((ZEROP M) NIL) ((CONS M (REBOURS (- M 1)))))))
  1636.  
  1637. ; puis une autre qui teste si une case n'est pas en dehors de l'Θchiquier
  1638. (PUTD TEST '(LAMBDA (X Y) (AND (< -1 X) (< X N) (< -1 Y) (< Y N))))
  1639.  
  1640. ; pour construire la liste des positions atteignables α partir de M
  1641. (PUTD SAUTS '(LAMBDA (PAS)
  1642.   (COND ((NULL PAS) NIL)
  1643.     ((TEST (+ (CAAR PAS) (MOD (- M 1) N)) (+ (CADAR PAS) (/ (- M 1) N)))
  1644.        (CONS (+ (+ M (CAAR PAS)) (* N (CADAR PAS))) (SAUTS (CDR PAS))))
  1645.     ((SAUTS (CDR PAS))))))
  1646.  
  1647. ; on construit en effet une table de ces listes pour l'ensemble des cases
  1648. (PUTD TABLE '(LAMBDA (M)
  1649.   (COND    ((ZEROP M) NIL)
  1650.     ((CONS (CONS M (SAUTS DIR)) (TABLE (- M 1)))))
  1651.  
  1652. ; maintenant le programme lui-mΩme: cherche un chemin par toutes les cases
  1653. (PUTD CHEMIN '(LAMBDA (CASES RESTE PARCOURS)
  1654.   (COND    ((ZEROP RESTE) PARCOURS)        ; trouvΘ !
  1655.     ((NULL CASES) NIL)            ; une impasse...
  1656.     ((MEMBER (CAR CASES) PARCOURS)        ; dΘjα passΘ par ici...
  1657.         (CHEMIN (CDR CASES) RESTE PARCOURS))
  1658.     ((CHEMIN (CDR (ASSOC (CAR CASES) TAB))
  1659.          (- REST 1)
  1660.          (CONS (CAR CASES) PARC)))    ; on essaie par lα...
  1661.     ((CHEMIN (CDR CASES) REST PARC)))))    ; et les autres aussi...
  1662.  
  1663. ; un programme principal pour lancer le tout, et c'est fini !
  1664. (PUTD PARCOURS '(LAMBDA (N TAB)
  1665.   (SETQ TAB (TABLE (* N N)))        ; on calcule la table une seule fois
  1666.   (CHEMIN (REBOURS (* N N)) (* N N))))    ; puis on cherche
  1667.  
  1668. Remarque: Pour trouver toutes les solutions, il suffit de remplacer la
  1669. premiΦre clause de la fonction chemin par :
  1670. (COND ((ZEROP RESTE) (PRINT PARCOURS) NIL)
  1671.  
  1672. Remarque2: Une image mΘmoire est fournie avec OricLisp, contenant une version
  1673. amΘliorΘe de ce programme pour trouver plus rapidement une solution.
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.                                 - 28 -
  1680.