De printf("Hello World") à votre propre langage de programmation
« Computer science is no more about computers than astronomy is about telescopes. »
L'informatique n'est pas l'art de faire fonctionner un ordinateur. C'est l'art de résoudre des problèmes en concevant des algorithmes — des séquences d'instructions finies et non-ambiguës — et en les exprimant dans un langage que la machine peut exécuter.
Un ordinateur, c'est juste du sable (silicium) dopé au phosphore qui laisse passer le courant ou pas. Ce qui transforme ce caillou en outil de pensée, c'est le programme : une structure de données + un algorithme. Rien de plus, rien de moins.
Ce cours vous emmène des bases — une variable, une boucle, une fonction — jusqu'à la construction d'un langage de programmation complet avec environnements, fermetures lexicales, objets, et même un transpileur vers Python. Tout ça en C. Tout ça en partant de zéro.
« The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. »
Il existe des dizaines de langages. Pourquoi commencer par le C ? Parce que le C est la langue la plus proche de la machine sans tomber dans l'assembleur. Quand vous écrivez du C, vous savez exactement ce que le processeur va faire :
Vous manipulez des adresses mémoire. Pas de garbage collector qui cache la réalité. malloc et free sont vos nouveaux meilleurs amis (et pires ennemis).
Vous organisez vos données comme vous voulez. Pas de classes, pas d'héritage — juste des struct et de l'imagination.
Pas d'interpréteur, pas de JIT. Un compilateur transforme votre code en binaire. Ce qui arrive au processeur est exactement ce que vous avez écrit.
Le C est partout : noyaux Linux, embedded, microcontrôleurs, interpréteurs Python, serveurs web, votre grille-pain (littéralement).
Connaître le C, c'est comprendre ce qui se passe sous le capot.
Quand un langage « haut niveau » fait quelque chose de magique, vous savez
que c'est juste un malloc bien placé, un pointeur de fonction,
ou une structure astucieuse. La magie n'existe pas en informatique.
Il n'y a que des couches d'abstraction.
« C is quirky, flawed, and an enormous success. While accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language. »
Ce cours n'est pas une suite d'exercices déconnectés. C'est une progression continue : chaque programme est une brique qui sert au suivant. Voici ce que vous allez écrire, dans l'ordre :
Le fil rouge : à chaque étape, vous ajoutez une couche d'abstraction.
factorielle.c : Vous écrivez une fonction
récursive, vous mesurez le temps d'exécution, vous observez l'assembleur
généré. Vous comprenez ce qu'est un programme.
vm.c : Vous construisez une machine
virtuelle à pile avec 23 opcodes. Vous réalisez qu'un processeur, c'est
juste un gros switch bien organisé.
calc.c : Vous écrivez un parseur
d'expressions arithmétiques en notation LISP. Vous découvrez que lire
du texte et le transformer en arbre, c'est finalement assez simple.
template.c : Vous créez un mini langage
de templates. Vous comprenez le principe de séparation données / code.
let.c : Vous construisez un évaluateur
LISP complet avec environnements chaînés, fermetures lexicales,
cellules mutables, et objets par passage de messages.
prolog.lisp : Vous écrivez une
bibliothèque standard en LISP — map, filter,
foldl — qui tourne sur votre propre interpréteur.
(map (lambda (x) (* x x)) (iota 10)) et d'obtenir
(0 1 4 9 16 25 36 49 64 81) — exécuté par votre propre
programme C. Vous avez littéralement construit un langage.
Pas mal pour un cours d'introduction.
C'est la question que tout le monde pose. La réponse est simple : parce que c'est la syntaxe la plus facile à analyser.
Comparez :
/* Combien de parenthèses ? */ /* Quelle est la priorité ? */ x = a + b * c << 2 + d && e || f;
Pour analyser ça, il faut une grammaire complexe, une table de précédence, et un soupçon de foi en l'humanité.
; Pas d'ambiguïté possible
(+ a (* b c) d)
Chaque parenthèse ouvrante est une liste. Le premier élément est l'opérateur. Point final. Un parseur de 50 lignes suffit.
Le choix du LISP n'est pas un caprice pédagogique. C'est un choix d'ingénierie :
'(+ 2 (* 3 4))' en arbre syntaxique tient en 50 lignes
de C. Les étudiants peuvent l'écrire et le comprendre
en une séance.
sexp_parse vous donne directement la structure
que vous allez évaluer.
let, les closures — ces concepts sont
naturels en LISP. On peut les implémenter en 200 lignes
de C. Essayez ça avec la syntaxe de Java.
quote, les macros, le
transpileur deviennent triviaux.
« LISP is worth learning for the profound enlightenment experience you will have when you finally get it. That experience will make you a better programmer for the rest of your days. »
En d'autres termes : on n'enseigne pas le LISP pour le LISP. On l'utilise comme langage cible parce que sa simplicité syntaxique permet de se concentrer sur les vrais concepts : l'évaluation, l'environnement, la portée lexicale, la récursion.
À la fin de ce cours, vous serez capable de répondre à ces questions :
Ce sont les fondations de l'informatique. Une fois que vous les avez, tous les langages et toutes les technologies deviennent plus faciles à apprendre.
Ce cours est conçu pour des débutants en programmation. Aucune connaissance préalable en C n'est requise. On part de zéro :
segfault, ça arrive. Et ça arrive souvent.
Le cours est organisé en 6 chapitres de slides + documentations, accompagnés de 3 séances de travaux dirigés (7 exercices chacune) qui vous guident pas à pas.
Chaque cours a ses slides (visuels, humour, code) et sa version documentaire (plus détaillée, plus technique).
3 séances de 2h, 7 exercices progressifs chacune. Du Hello World à un évaluateur LISP complet avec objets et transpileur.
<details>. Mais essayez d'abord.
La comprendre > la copier. Et si vous copiez, au moins changez le nom
des variables pour faire croire que c'est vous.