Le bac à sable¶
Ouvrez-le, et revenez ici quand quelque chose vous intrigue.
Tapez un programme à gauche et appuyez sur Ctrl ou ⌘ + Entrée, ou cliquez sur Exécuter. La liste Programme charge n'importe lequel des dix-huit exemples, qui tournent tous tels quels.
Tout se passe dans votre navigateur. Rien n'est envoyé, rien n'est stocké. Il n'y a pas d'OCaml à l'autre bout : le compilateur est écrit en Python, et c'est Python qui tourne dans votre onglet.
Les cinq vues¶
Exécution¶
Ce que le programme affiche.
Un programme sans let () = ... n'affiche rien, sans que ce soit un échec : la moitié des exemples ne font que définir des fonctions. Pour voir quelque chose, ajoutez une ligne :
La ligne d'état, en haut à droite, indique les deux exécutions concordent quand tout s'est bien passé. Voici pourquoi.
Votre programme est exécuté deux fois. Une fois en parcourant l'arbre de syntaxe, et une fois en le compilant vers Python puis en exécutant ce Python. Deux back-ends indépendants, une seule bibliothèque d'exécution partagée. La ligne dit s'ils ont affiché la même chose. C'est le test de correction du projet lui-même, appliqué à ce que vous venez de taper. Il a débusqué de vrais défauts ; voyez L'exécuter, deux fois.
Types¶
La signature inférée, dans la forme qu'affiche le vrai ocamlc -i. Rien dans votre source ne dit de quel type est quoi que ce soit ; tout a été déterminé.
Une variable de type écrite '_weak1 plutôt que 'a n'a pas été généralisée. Ce n'est pas un bug. Essayez :
Vous obtenez '_weak1 list ref. Si c'était 'a, on pourrait mettre un int dans la case à un endroit et en relire une string à un autre, ce qui ferait mentir le système de types. Ce comportement s'appelle la restriction aux valeurs, et le vrai OCaml fait de même.
Noms¶
L'arbre des portées, un par espace de noms. C'est la vue qu'aucun autre bac à sable OCaml ne propose.
Chaque bloc indique ce qu'il lie :
| bloc | ce que c'est |
|---|---|
module top |
le fichier entier |
binding |
les paramètres d'une fonction |
case |
un cas d'un match |
fun |
les paramètres d'une fonction anonyme |
let |
le corps d'un let ... in |
for |
l'indice d'une boucle |
Le lire répond aux questions sur lesquelles on bute vraiment. À quel x renvoie ce x ? Cet appel récursif se résout-il ? Ce paramètre s'échappe-t-il de la fonction ? L'arbre le dit, sans qu'on ait à le reconstituer de tête.
Il y a cinq arbres, parce qu'OCaml sépare cinq sortes de noms : valeurs, constructeurs, champs d'enregistrement, noms de types et variables de types. Un champ x et une variable x sont des noms sans rapport en OCaml, donc ils sont dans des arbres différents. Constructeurs et exceptions en partagent un, parce qu'OCaml le partage.
Ce que le compilateur n'a pas su trouver est listé au-dessus des arbres.
Python¶
Ce qu'émet le second back-end. C'est fait pour être lisible : let f x y = ... devient def f(x, y) ; un appel avec les deux arguments devient un appel direct.
Là où vous voyez _rt.BINARY_OPS['/'] au lieu d'un / ordinaire, les deux langages divergent. La division entière d'OCaml tronque vers zéro et celle de Python arrondit vers le bas, donc (-7) / 2 vaut -3 en OCaml et -4 en Python. Et = est l'égalité structurelle, qui n'est pas le == de Python non plus. Là où ils s'accordent, l'opérateur est émis directement, ce qui explique que l'arithmétique se lise normalement.
Les noms sont renommés au besoin : un let x = ... qui en masque un autre ressort en x_2. C'est ce qui fait qu'une fermeture antérieure continue de lire le x qu'elle avait capturé.
Réécrit¶
Votre source, réimprimé à partir de l'arbre que le compilateur a construit. C'est ainsi qu'on vérifie qu'il a lu ce que vous vouliez dire : si une parenthèse apparaît là où vous n'en aviez pas mis, le groupement n'était pas celui que vous imaginiez.
Essayez 1 + 2 * 3, puis 1 + 2 :: l @ m, et regardez où atterrissent les parenthèses.
Partager¶
Copier le lien met tout votre programme dans l'URL, après #code=, et le copie. Quiconque ouvre ce lien voit votre code.
Rien n'est stocké nulle part ; le programme voyage dans le lien lui-même, donc un très long programme donne un très long lien.
Quand quelque chose ne va pas¶
Les problèmes apparaissent dans un bandeau rouge au-dessus des vues, précédés de l'étape qui les a trouvés.
syntax: 3:14: expected … found …- L'analyseur s'est arrêté ligne 3, colonne 14, et énumère tout ce qui aurait pu venir ensuite. Le plus souvent : un
inoublié, un->oublié, ou une,là où il fallait un;. names: 'foo' is not declared in vals- Un nom que rien ne définit. Vérifiez l'orthographe, puis que le
letqui le définit vient bien avant dans le fichier : l'ordre compte au niveau global. types: TypingError: this has type … but … was expected- Deux types devaient coïncider et ne coïncident pas. La cause la plus fréquente, et de loin, est le mélange de
intet defloat: OCaml a+et+., deux opérateurs différents. interpreter: OCamlError: …- Le programme a levé une exception que rien n'a rattrapée, exactement comme le vrai
ocamlse serait arrêté.
Une étape qui échoue n'arrête pas les autres. Un programme qui ne type pas s'exécute quand même, et montre quand même ses portées. C'est souvent le moyen le plus rapide de comprendre : regardez Noms pour voir ce que le compilateur croit être en portée.
Ce qu'il n'y a pas¶
Pas d'éditeur. Pas de complétion, pas de coloration, pas de soulignement. Une zone de texte et cinq réponses.
Pas de Printf, pas de Hashtbl, pas de modules à vous, pas d'objets, pas de foncteurs. L'aide-mémoire dit ce qu'il y a.
Un programme qui tourne longtemps fige l'onglet, parce que tout s'exécute sur un seul fil. Rechargez la page pour l'arrêter.