#+TITLE: Le LISP et son implementation #+AUTHOR: Gabriel Pariat * Intro Bien le bonjour! Music Land of lisp: https://youtu.be/HM1Zb3xmvMc * Play Game! Jouons à un petit [[https://lisp.pariatech.com][Jeux d'aventure]]! * C'est quoi le LISP? Le LISP est une famille de language vielle comme le chemin. Datant de 1958 et on parle du deuxieme plus vieux language haut-niveau, le plus vieux étant FORTRAN de juste un ans. Les LISP les plus populaires sont Racket, Common Lisp, Scheme et Clojure. On manque pas de choix, et ils ont tous leurs petits partularités. Mais encore on parle pas de la centaine d'autre implémentation de LISP, qui doit existé, ont éxisté. Je vais vous montré pourquoi il y a autant d'implémentation de cette famille de language. * Comment ça marche? ** Les Grande lignes L'intépréteur a sont plus simple à cette structure. #+begin_export ascii TEXT => Reader - Génére l'arbre du code à partir du text brute. || \/ Evaluator - Évalue l'arbre pour en obtenir un résultat. || \/ TEXT <= Printer - Transform le résultat en du text pour l'usagé. #+end_export ** Reader Le travail du Reader est de créer un arbre à partir du text. *** Les pairs Un arbre est composé de pairs. Et des pairs enchainé ensemble donne une liste. #+begin_example (+ 1 2 (* 3 4)) => (+ . (1 . (2 . ((* . (3 . (4 . nil))) . nil)))) /\ / \ + /\ / \ 1 /\ / \ 2 /\ / \ /\ nil / \ * /\ / \ 3 /\ / \ 4 nil #+end_example *** Parsing La syntax très simple du LISP nous aide énormement pour cette partie. Tout ce qui nous importe c'est les parenthéses et les espaces. Tout le reste n'est que des symbols. Oui, mais sauf ci c'est un chiffre... À l'ouverture d'une parenthése détermine qu'on ouvre une paire. Et quand on referme cette parenthése on termine une liste. Chaque espace délimite les symbols. *** Mais est-ce vraiment si simple? Non pas vraiment, j'ai menti... Le seul petit caveat c'est les pairs. En gros les pairs individuel. Celle ci sont composé de deux symbols séparés par un point. #+begin_example (1 . 2) #+end_example Sinon il y d'autre "Sugar Syntax" populaire comme par example: #+begin_example ' => quote ` => quasiquote , => unquote ,@ => unquote-splicing "" => string [] => vector {} => hashmap etc... #+end_example La liste peux grandir autant qu'on veux. Mais sans rentré dans les détails mais souvent les implémenteurs sont lache et implémente dans le language la pausibilité d'ajouter des macros à la lecture pour ajouter ses propres "Sugar Syntax". ** Evaluator Maintenant qu'on a notre arbre, c'est le temps de le résoudre. Pour cela faut le parcourir et aussi savoir l'ordre d'opération. *** Parcour et l'ordre Le parcour n'est rien d'autre qu'une récursion. Mais avec quelques petits caveats. Quand on parcour l'arbre et on tombe sur une valeur qui est une paire. Il faut parcourir le premier élément de cette paire. Par le fait cet élément va etre évalué le premier. Il à deux possibilité de résultat: **** Opération spéciale Suivre les instructions de celle-ci. Comme example, IF: évalue la conditions et ensuite la bonne branche. **** Fonction Évalué chaque arguments de celle-ci et ensuite évalué le résultat de la fonction. *** Environment Bon c'est bien beau s'avoir quoi faire, mais faut encore savoir ce que nos symbols veullent dire. C'est la que l'environment vien en jeux. Il nous permet d'associer une valeur à un symbole. Par valeur on parle de n'importe quoi, une fonction, un chiffre, une string, une liste, etc... Donc quand on arrive sur une feuille de notre arbre on va voir dans cette table pour trouvé la valeur de notre symbol. C'est dans lui qu'on va stocker aussi les fonctions et les variables que notre code va généré. *** Bonus: Macros Si on parle LISP on ne peux pas ne pas parlé des macros. C'est ce qui donne la famille de language un edge considerable sur les autres. Ne voyez pas les Macros en C/C++ qui ne sont pas plus que de la substitution. Ni mêmes les templates de C++ qui tent dire un autre language a part entiere du C++. Mais du LISP qui génére du LISP. Oui, vous écrivez du code, le même que vous utilisé normalement, mais celui ci va être appelé avant l'évaluation pour générer du code qui lui va être évalué. Je vais être honête ça été un petit brainfuck pensé comment implémenté cela, une évaluation avant une évaluation, mais qui a besoin d'être évalué... Mais finalement c'est pas compliqué. ** Printer En gros le printer, c'est comme le reader, mais à l'envers. Tu parcour l'abre que l'évaluateur à retourné et converti chaque valeur en ça forme texte. ** Loop Et quand tu met tout ça dans une loop, tu a un REPL. Ce que vous voyez sur mon site c'est un REPL. Si vous installer un interpréteur Common Lisp, comme par example SBCL et vous le lancer. Vous allez voir un REPL. Le REPL c'est cool parceque tu peux jouer avec l'environment pendant que ton programme roule. Tu veux tester une fonction, let's go! Tu veux changer la vitesse que ton personnage bouge dans ton jeux, Let's go! Y'a une erreur dans une de tes fonctions et tu ne veux pas repartir ton programme, pas de problème amigos, juste fourni moi la version corrigé! * Questions? Vous avez des questions? Vous avez aimez? Le code ce trouve sur https://git.pariatech.com/pt-lisp. C'est sur la branche: refactoring. Je n'ai pas encore merger dans master, j'ai des bugs à régler avant... Si vous voulez en apprendre plus je recommende le livre LAND OF LISP par Conrad Barski. Extra chanson sur la programmation: Round worm, Eternal Flame: https://youtu.be/u-7qFAuFGao