| Ravi Welcome Documentation Documentation About Ravi Documentation Introduction Premiers pas avec Ravi ravitool Scheme Tutorial Objets Scheme Le shell ravi Starting Ravi Le module trace Les ports d'E/S The C Parser load, require, modules Système d'interruptions Scheme compiler C++ mode Generating C++ Modules La déclaration struct Le type "C-object" More information Installation | Scheme compilerOn trouve sur cette page:
On peut compiler un ou plusieurs fichiers avec des programmes en Scheme et créer ainsi un module Ravi. Commande de base (sous Unix) pour un fichier nom_fichier.scm:
Les options sont
La compilation (on voit que le compilateur est lui-même un module Ravi) crée un fichier nom_fichier.mobj avec le code objet. On rappele que la fonction load, appelée par va charger en priorité la version compilée, si les deux versions .scm et .mobj existent (cf. description de load). Très généralement, la compilation apporte plusieurs avantages:
Si le fichier à compiler contient rien que des définitions de fonctions, la compilation ne demande aucune précaution particulière. Dans d'autres situations, le fichier à compiler contient des déclarations permettant de cibler le travail du compilateur. Normalement, la compilation crée un module qui exporte certaines fonctions seulement : c'est la déclaration export, la plus importante. La forme du fichier à compiler est alors
Si le fichier contient des "initialisations" - des expressions autres que des définitions de fonctions - une précaution simple est exigée: toute utilisation d'une variable doit se trouver après le define qui introduit la variable. Par exemple (declare (export f1 f2 f3 ..)) (define col 13) ; nb : col n'est pas exporté (define f1 (+ col 3)) ...
On compile seulement du code bien mis au point. Restrictions
La fonction includeLa fonction include a pour effet d'inclure, textuellement, le code figurant dans un fichier: (include "file_name") Le code d'un module à compiler peut donc être découpé en plusieurs fichiers. Remarques:
Le chargement du code de module à proprement parler demande parfois quelques précautions. Il peut être complété par un "prélude" et un "postlude". Pour cela on utilise des déclarations
Le prélude est une séquence d'expressions interprétées, en dehors de l'environnement du module, et avant le chargement du module. Etant donné que le chargeur Ravi n'est pas ré-entrant, le compilateur construit automatiquement un prélude, avec tous les require et load rencontrés dans le fichier source. On peut contrôler cela plus finement avec un prélude explicite. En particulier, tout require ou load conditionnel doit se trouver dans le préfixe. Toutes les déclarations introduites dans le postlude sont mémorisées par le compilateur, pas besoind de les repéter dans un declare. L'exécution du postlude se fait en interprété, après chargement complet du module. L'exécution du postlude peut donc conduire à un nouveau chargement sans problème; notamment, un postlude permet le lancement d'un module.
Les déclarations permettent de préciser quelques choix ; seule la déclaration export est utile pour tout le monde, les autres servent dans des cas assez particuliers, ou carrement pour les développeurs.
Les variables modifiables sont:
Traitement non-homogène fonction - variable On compile seulement les lambda-expression, ce qui introduit une distinction entre "définition de fonction" et "définition de variable", distinction qui est totalement contraire aux principes de Scheme. {Selon les principes, une variable possède une valeur, laquelle valeur peut être une procédure/fonction, ou autre chose - les fonctions sont des objets "1ière classe"}. (export n) Si n est une variable "non-compilée", elle sera une variable globale. Toute affectation à n par un set! modife sa valeur. Si n est une fonction, il y a définition globale de n, mais il y a aussi une définition "privée" dans le module: une affectation à n ne va pas changer cette "définition interne". (export-only n) Si n est une fonction, c'est une vraie fonction globale - toute affectation à n modifie aussi les appels internes au module. Si n est une macro, sa définition est exportée, mais elle n'est pas utilisée pour la compilation du module! Macros Il existe 3 configurations pour une définition de macro-fonction. Pas de déclaration: la macro est utilisée pour la compilation du module, mais elle ne sera pas exportée. C'est le cas normal. Déclaration export: la macro est utilisée pour le module, et également exportée. Déclaration export-only: la macro est seulement exportée, elle n'est pas utilisée pour le module. Cas rar. Dans tous les cas, la définition d'une macro doit précéder sa première utilisation dans le texte du programme. Sinon le compilateur sort un warning obscur. Si une macro est utilisée sans être définie à la compilation, c'est le code compilé qui va planter: apply : illegal function | It is a kScTypeCons D'une facon générale, l'emploi de macros est périlleux - c'est pour des bonnes raisons qu'elles ne figurent pas dans la définition de Scheme, où elles sont remplacées par les syntax-transformer Voir le livre de Chazarain pour une bonne explication.
Pour deboguer ou modifier le compilateur, on l'utilise "à la main". Il y a alors un nombre considérable de traces et autres possibilités de suivre de prés ce qui se passe. Si la compilation provoque une erreur Scheme
Si le compilateur plante, utiliser (error-frame) pour localiser l'endroit. ============================================== |