LEÇON 1 / 45 minutes

Les bases de Vitte

Cette leçon présente un programme Vitte complet, son fichier source, son point d’entrée et les outils qui permettent de le compiler.

À retenir·Un programme Vitte se lit comme un ensemble de déclarations, organisé dans un espace de noms.

Notre premier programme

Voici le petit programme de départ fourni dans le dépôt. Il affiche un message et annonce au système qu’il s’est terminé sans erreur :

space examples/hello;

proc main() -> int {
    print("Hello from Vitte!");
    return 0;
}

Une première lecture peut se faire de haut en bas, sans chercher à mémoriser chaque détail. La structure générale suffit d’abord : un chemin de module, une procédure principale, un appel puis une valeur de retour.

La ligne space donne un nom au module

space examples/hello; déclare l’espace de noms auquel appartient ce fichier. Le chemin est formé de segments ; la grammaire accepte les séparateurs / ou :: selon la forme de déclaration. Même dans un petit programme, ce chemin évite les noms vagues ; dans un projet plus vaste, il organise les modules. Le point-virgule termine cette déclaration.

proc introduit une procédure

Une procédure est un morceau de programme qu’on peut appeler par son nom. main est ici le point d’entrée conventionnel : quand le programme est lancé, l’environnement cherche cette procédure. Les parenthèses sont vides parce que cette première version ne reçoit aucune information. La flèche -> int annonce le type de la valeur renvoyée. Les accolades délimitent le corps.

À l’intérieur, print(...) est un appel. On donne à la procédure print un texte entre guillemets. La ligne finit par un point-virgule. Enfin, return 0; renvoie le nombre zéro : par convention, cette valeur signifie que tout s’est bien passé.

Quel compilateur vérifie cet exemple ?

Dans le dépôt audité, print fonctionne avec le compilateur bootstrap, mais build/bin/vitte (frontend natif) le signale comme nom inconnu. La commande confirmée pour ce fichier utilise donc explicitement build/bin/vitte-bootstrap. Voir aussi l’état du support.

Installer et vérifier l’outil

Dans ce dépôt, la compilation du compilateur se lance avec make. Une fois le binaire disponible dans l’environnement, la version peut être consultée avec la commande indiquée dans le README :

make
make build/bin/vitte-bootstrap
build/bin/vitte-bootstrap run examples/hello.vit --quiet --no-color

make construit le binaire natif principal. La seconde commande construit aussi le compilateur bootstrap, qui est le chemin vérifié pour ce premier exemple. Le programme écrit Hello from Vitte! et se termine avec le code 0.

Les commandes à connaître

  • build/bin/vitte check fichier.vit vérifie le sous-ensemble du frontend natif.
  • build/bin/vitte lex fichier.vit affiche les tokens du fichier.
  • build/bin/vitte parse fichier.vit demande au parseur de reconnaître les formes syntaxiques.
  • build/bin/vitte run fichier.vit compile et exécute les constructions prises en charge ; les chapitres suivants donnent des cas réellement confirmés.
Un repère important

Un message disant que le texte est bien analysé ne garantit pas à lui seul que le programme complet pourra être compilé ou exécuté. Dans ce cours, on distinguera donc toujours la syntaxe du langage et les capacités actuelles de l’outil.

Lire un résultat de compilation

Les fichiers de démonstration peuvent être conservés sous examples/ afin de retrouver leur source et leur commande d’exécution. Une commande reproductible précise toujours le binaire, la sous-commande, le chemin du fichier et, lorsque c’est utile, le mode de diagnostic.

Lorsqu’une erreur apparaît, le premier diagnostic est généralement le meilleur point de départ. Son code, sa ligne et la construction concernée indiquent la phase qui a détecté le problème. Une erreur de syntaxe peut empêcher les vérifications suivantes ; plusieurs messages peuvent donc disparaître après une seule correction structurelle.

La leçon suivante reprend le même exemple pour expliquer la ponctuation, les commentaires et les blocs, qui constituent l’ossature visible d’un programme Vitte.

Lire le programme comme une suite de décisions

Relisez le fichier en observant le rôle de chaque ligne : « qu’est-ce que cette ligne apporte au reste du programme ? » space fixe le contexte du fichier. proc main déclare le point de départ. Le type int précise la forme de la réponse finale. L’appel à print produit l’affichage. Enfin, return 0 termine cette exécution avec un code que le système peut interpréter.

Il faut distinguer trois choses que l’on confond facilement au début :

  • Le texte source est le contenu du fichier Vitte.
  • Le programme compilé est le résultat produit par l’outil pour une cible donnée.
  • Le résultat d’exécution est ce que le programme affiche et le code avec lequel il termine.

Quand le fichier ne fonctionne pas, déterminez d’abord à quelle étape le problème apparaît. Une accolade oubliée concerne la lecture de la syntaxe ; une commande inconnue concerne la compilation ou la bibliothèque ; un texte différent de celui attendu concerne le comportement une fois le programme lancé.

Suivre l’exemple du fichier jusqu’au résultat

Depuis la racine du dépôt, les commandes du cours sont :

make build/bin/vitte-bootstrap
build/bin/vitte-bootstrap parse examples/hello.vit
build/bin/vitte-bootstrap run examples/hello.vit --quiet --no-color

La première prépare l’outil bootstrap utilisé pour cet exemple. La deuxième demande seulement au parseur de reconnaître la structure. La troisième compile puis exécute le programme. Le résultat attendu est le texte Hello from Vitte! et le code de sortie 0. Un code de sortie différent de zéro ne signifie pas nécessairement que la syntaxe est incorrecte : il signifie que le programme lancé a renvoyé une autre valeur.

Le binaire natif build/bin/vitte est une autre voie de compilation. Pour cette leçon, ne remplacez pas automatiquement le binaire indiqué par celui-ci : le dépôt audité rejette l’appel à print dans ce cas. La page sur le support explique les différences entre ces voies.

Une première méthode de dépannage

  1. La commande doit être exécutée depuis la racine du dépôt : le chemin examples/hello.vit est relatif à cet emplacement.
  2. Le nom du binaire, la sous-commande et le chemin du fichier doivent correspondre à l’installation présente.
  3. Le premier diagnostic complet fournit le code, le fichier et la ligne à examiner.
  4. Une seule modification à la fois permet d’identifier la cause d’une erreur.
  5. La commande exacte doit être conservée avec le résultat observé afin de rendre l’exécution reproductible.
Notions essentielles

Le programme est compris lorsque le rôle de space, de proc main, de son type de retour, de l’appel à print et de return est clair. Un échec d’analyse et un code de sortie non nul correspondent à deux situations différentes.

De la source à l’exécution : le trajet complet

Un fichier .vit est d’abord du texte. Le lexer transforme ce texte en unités reconnues — mots-clés, noms, littéraux, opérateurs et séparateurs — puis le parseur assemble ces unités en déclarations et en blocs. L’analyse vérifie ensuite les noms, les types et certaines règles sémantiques. La génération produit du code pour un backend, puis les outils de la plateforme peuvent encore intervenir pour l’édition des liens et le lancement. Un échec à chacune de ces étapes a une cause différente.

Cette succession explique pourquoi les commandes lex, parse, check et run ne répondent pas à la même question. La première montre les éléments lexicaux ; la deuxième la structure ; la troisième les vérifications disponibles ; la dernière cherche à obtenir un programme exécutable et à le lancer. Le succès d’une étape est une preuve limitée à cette étape : un parsing réussi ne garantit ni l’existence d’un symbole externe ni la génération du code final.

Le point d’entrée est une interface avec le processus

main relie le programme Vitte au lancement effectué par le système. Dans l’exemple du dépôt, sa signature proc main() -> int annonce une procédure sans paramètre dont le résultat sert de statut de fin. L’instruction return 0 termine le corps et fournit ce statut. La valeur n’est pas le texte affiché : l’appel à print agit sur la sortie, tandis que return transmet un résultat au processus appelant.

Cette distinction compte dans les commandes automatisées. Un terminal peut montrer une ligne de sortie et, indépendamment, signaler un code de sortie. Un programme peut afficher un diagnostic puis renvoyer un statut non nul ; inversement, une procédure peut terminer avec zéro sans afficher quoi que ce soit. Une vérification complète décrit donc les deux observations lorsqu’elles sont pertinentes : ce qui apparaît sur la sortie standard et le statut du processus.

Le dépôt, le binaire et le fichier forment une seule commande

Une commande de compilation est reproductible seulement si elle identifie le répertoire courant, le binaire exact, la sous-commande et le fichier source. Dans cet environnement, les chemins comme examples/hello.vit sont relatifs à la racine du dépôt. Une commande exécutée depuis un autre répertoire peut échouer avant même que Vitte lise le fichier. Le binaire sélectionné est tout aussi important : le bootstrap et le frontend natif n’acceptent pas encore exactement le même ensemble de constructions.

Pour cette raison, une affirmation comme « cet exemple fonctionne » doit rester attachée au chemin effectivement lancé. Le programme de départ avec print a une commande confirmée avec build/bin/vitte-bootstrap ; le frontend natif refuse actuellement ce nom dans le même contexte. Cette différence ne change pas la lecture de la syntaxe, mais elle change l’outil requis pour obtenir l’exécution annoncée. La page de support documente ces écarts au lieu de les masquer.

La commande de lancement distingue source, compilation et processus

Le mot run désigne une opération de la CLI, tandis que main désigne une procédure de la source. La CLI décide du compilateur et du mode d’exécution ; le programme décrit son propre point d’entrée. Cette différence apparaît clairement dans une commande telle que build/bin/vitte-bootstrap run examples/hello.vit : le chemin avant run choisit le binaire, le mot suivant choisit l’action de la CLI, et le dernier élément nomme la source.

Lorsque le résultat n’est pas celui attendu, il est donc utile de distinguer un échec de commande d’un échec du programme. Un chemin source absent empêche la lecture du fichier. Une erreur du parseur empêche la construction de la représentation syntaxique. Une erreur de génération empêche l’obtention du binaire. Une sortie inattendue appartient au comportement du programme lancé. Un code de statut non nul indique l’échec selon la convention de la commande, mais le diagnostic associé permet de déterminer la phase concernée.

Construire le compilateur est une étape séparée

make construit le compilateur depuis le dépôt ; il ne compile pas seulement le fichier d’exemple. La commande ciblée make build/bin/vitte-bootstrap prépare le binaire employé par le programme de départ. Cette étape peut dépendre des outils de construction du dépôt, des bibliothèques de l’environnement et du commit courant. Il faut donc distinguer le fait de construire l’outil du fait de construire un programme écrit en Vitte.

Cette séparation explique les diagnostics possibles avant la première ligne Vitte : une chaîne d’outils manquante ou une construction interrompue relève de l’environnement du dépôt. Une fois le binaire disponible, la commande parse peut examiner la source indépendamment du résultat runtime. Conserver les deux commandes rend la procédure d’apprentissage reproductible et indique précisément quelle étape doit être rejouée après une mise à jour.