Exercice 1. Obtenez une copie du code source de Gambit-C dans votre répertoire. Plus précisément la version v4.6.3 du site web de Gambit (http://gambit.iro.umontreal.ca). Il faut télécharger le fichier : http://www.iro.umontreal.ca/~gambit/download/gambit/v4.6/source/gambc-v4_6_3-devel.tgz Exercice 2. Construisez le système Gambit-C avec les commandes suivantes: % tar zxf gambc-v4_6_3-devel.tgz % cd gambc-v4_6_3-devel % ./configure --prefix=$HOME/g4 % make % make check La dernière commande vérifie le bon fonctionnement du système et devrait afficher "ALL TESTS SUCCESSFUL". Si c'est le cas faire % make install Cela va installer le système dans ~/g4 et en particulier les binaires exécutables de gsi et gsc (interprète et compilateur Gambit) dans ~/g4/bin . Maintenant ajoutez ~/g4/bin dans votre "PATH", par exemple si vous utilisez "bash" entrez cette commande (et ajoutez la aussi à votre fichier ~/.bashrc): export PATH=$HOME/g4/bin:$PATH Cela vous permettra de démarrer gsi et gsc simplement en entrant leur nom. Exercice 3. La structure des sources de Gambit-C est la suivante: gambc-v4_6_3-devel/ --> répertoire principal gsc/ --> sources Scheme du compilateur Gambit-C gsi/ --> sources Scheme de l'interprète Gambit-C lib/ --> sources Scheme et C du "runtime library" (fonctions prédéfinies telles string-append, make-vector, etc ainsi que le garbage collector, les fonctions de bas-niveau pour l'interface au système d'exploitation) include/ --> fichiers "gambit.h" et "config.h" tests/ --> tests pour vérifier le bon fonctionnement du système doc/ --> manuel d'utilisation de Gambit-C (gambit-c.pdf, ...) examples/ --> quelques exemples d'utilisation (faire "make examples") misc/ --> fichiers auxiliaires, benchmarks, makefiles pour Windows Exercice 4. Configurez emacs en ajoutant dans le fichier $HOME/.emacs les lignes suivantes: (setq load-path (cons "~/g4/share/emacs/site-lisp" load-path)) (setq scheme-program-name "gsi -:d-") (setq gambit-repl-command-prefix "\e") (require 'gambit) Cela va vous donner un environnement de travail convivial pour utiliser Gambit. Les erreurs d'exécution seront signalées en colorant le code fautif en jaune, et il sera possible de faire une exécution "pas-à-pas" facilement. Lancez emacs (en tappant "emacs"), puis démarrez un sous-processus pour interagir avec l'interprète Gambit (en tappant x run-scheme, note: " x" peut aussi se faire avec la touche "Alt" et "x" ensemble). Essayer d'évaluer quelques expressions interactivement pour vous assurer que ça fonctionne. Remarquez ce qui se passe dans le cas d'une erreur d'évaluation, par exemple (/ 1 0). Expérimentez avec les commandes "ctrl-x 1", ",t" et ",?". Le démonstrateur fera une petite démo en classe. Si vous avez un portable apportez-le en classe avec Gambit et emacs déjà configurés. Exercice 5. Maintenant, vous allez faire une toute petite modification au compilateur Gambit-C et recompiler tout le système avec le nouveau compilateur. - Faire un "make bootstrap". Cela va copier le compilateur exécutable "gsc/gsc" à "gsc-comp". Le compilateur "gsc-comp" est utilisé pour compiler le code source Scheme de Gambit. Donc après cette étape, "gsc-comp" correspond au compilateur Gambit-C 4.6.3 **non modifié**. - Dans le fichier gambc-v4_6_3-devel/gsc/_parms.scm ajoutez votre nom dans la chaîne system-version-string-suffix qui est définie vers la fin du fichier, par exemple: (define compiler-version-string-suffix " [Marc Feeley]") Cette chaîne est utilisée dans l'identification de la version du système. - Faire un "make" pour construire le compilateur modifié. La compilation de "gsc/_parms.scm" se fera avec "gsc-comp" (le compilateur Gambit-C 4.6.3 **non modifié**). Vous obtenez donc un nouveau "gsc/gsc". - Faire un "make bootstrap". Cela va copier le compilateur exécutable "gsc/gsc" à "gsc-comp". Maintenant "gsc-comp" correspond au compilateur Gambit-C 4.6.3 **modifié**. - Faire un "make bootclean" pour éliminer tous les modules du système compilés avec le compilateur non modifié. - Faire un "make" pour construire tout le système avec le compilateur modifié. - Exécuter le nouvel interprète en entrant la commande "gsi/gsi". À noter que votre nom est maintenant indiqué dans la bannière de bienvenue de l'interprète. Quitter avec la commande ",q". - Faire un "make install" pour installer cette nouvelle version du système dans ~/g4/bin . Exercice 6. Maintenant, vous allez faire une modification au runtime de Gambit-C pour ajouter une nouvelle fonction prédéfinie. - À la fin du fichier gambc-v4_6_3-devel/lib/_nonstd.scm ajoutez une définition pour la fonction factorielle. Par exemple (define (fact n) (if (= n 0) 1 (* n (fact (- n 1))))) - Faire un "make" pour construire tout le système avec la nouvelle définition de fonction. - Exécuter le nouvel interprète en entrant la commande "gsi/gsi". Vérifier que la nouvelle définition est accessible en demandant le calcul de (fact 1000). - Faire un "make install" pour installer cette nouvelle version du système dans ~/g4/bin . Exercice 7. Expliquez pourquoi il faut faire 2 "make" lorsqu'on modifie le compilateur et seulement 1 "make" lorsqu'on modifie le runtime. Exercice 8. Écrivez les fonctions Scheme suivantes (utilisez l'interprète gsi dans emacs pour déboguer, la section 5.5 du manuel explique comment configurer emacs pour utiliser l'interprète). Une fois déboguées, ajoutez les au runtime de Gambit. - (p arg1 arg2...) La fonction p prend un nombre quelconque de paramètre. Elle imprime chaque paramètre à tour de rôle avec la fonction display sur la sortie standard. Par exemple: (p "j'ai " (* 2 2) " pommes") imprime "j'ai 4 pommes" Note: c'est une fonction très pratique pour le déboguage! - (multimap fonction liste1 liste2...) La fonction multimap est la variante générale de la fonction prédéfinie map qui permet d'appliquer une fonction à plus d'un paramètre sur autant de listes d'arguments. Par exemple: (multimap cons '(1 2 3) '(11 22 33)) => ((1 . 11) (2 . 22) (3 . 33)) - (flatten liste) La fonction flatten prend une liste en paramètre. Cette liste peut contenir d'autres listes à un niveau d'imbrication quelconque. La fonction flatten retourne une liste à un seul niveau contenant toutes les valeurs non-liste contenues dans la liste. (flatten '((1 2) (((3)) 4) 5)) => (1 2 3 4 5)