:: Enseignements :: ESIPE :: E4INFO :: 2011-2012 :: Génération de code ::
[LOGO]

Projet - Partie 3


Troisième et dernière partie, implantation d'un générateur de bytecode.

On cherche toujours à exécuter le code d'un script, mais au lieu d'utiliser un interpreteur pour exécuter le code, l'idée est plutôt de developper un générateur de bytecode Java pour générer le bytecode en mémoire puis de faire exécuter celui-ci par la machine virtuelle.
Pour repartir sur des bases saines (avoir un vrai typecheck qui marche), le fichier ZIP contient tout ce qu'il faut pour démarrer: ir2012-td5.zip.
Attention !, éviter le copier/coller entre le projet de la partie 1 et 2 celui de la partie 3, les packages ne sont pas les mêmes !
Comme pour les exercices précédent, il existe dans le répertoire lib un jar exécutable nommé engine-slim.jar qui implante déjà notre compilateur de bytecode. Cela vous permettra de tester la sortie de votre programme par rapport à la sortie de ce jar exécutable. Pour exécuter le jar: java -jar lib/engine-slim.jar samples/mon_super_samples.ir2012

Pour générer du bytecode, nous utiliserons la librarie ASM 4* (le jar asm-debug-all-4.0.jar est déjà présent dans le répertoire lib) qui à la bonne idée d'utiliser aussi le design pattern Visitor (ou un proche parent) pour générer le bytecode.
La spécification complète du bytecode JVM Spec (chapitre 6).
Un guide assez complet sur comment marche ASM ASM 4.0 Guide

Une note sur la génération des expressions binaires.
Il existe pas d'instruction binaire correspondant à ==, !=, <, <= etc dans le bytecode Java, mais il existe IF_ICMPEQ label, IF_ICMPNE label, etc qui sont des instructions qui prennent deux arguments sur la pile et saute au label indiqué si les deux valeurs sont égals, différentes, etc.
Donc pour générer a == b, on peut distinguer deux cas, soit on est dans un if/for (noter que ici, j'ai été gentil vous n'avez pas à implanter && et ||) soit on est en dehors. Si on est dans un if alors
        if a == b:
          print a
        end
      
se génére facilement en inversant la condition
        iload 0  // 0 = slot de a
        iload 1  // 1 = slot de b
        if_icmpne false_label
          // code de print a
      :false_label
      
Dans le cas, ou le test n'est pas dans un if, il faut créer des branches artificielllement donc c = a == b, se génére comme cela.
        iload 0
        iload 1
        if_icmpne false_label
        iconst_1     // true
        goto end_label
      :false_label
        iconst_0     // false
      :end_label
      

Exercice 1 - Implantation d'un générateur de code

Le but est d'écrire un visiteur qui générér le code, il utilisera pour cela les informations (types des expressions et symboles des variables) déjà calculer par le typechecker.
Il existe deux façon d'écrire ce genre de générateur, la première, celle que nous allons developpé ici consiste à générer une classe pour le script complet pour d'exécuter son main (Note, il n'y a aucun raison que le main est la même signature que le main du langage Java). Une autre solution consiste à générer une classe par fonction et de générer le code de chaque fonction lors de son premier appel. Les JITs fonctionnent plutôt suivant ce principe mais c'est un peu plus dure à implanter. Nous nous contenterons ici de générer un seul .class (en mémoire) pour tout un script, donc le parcours du visteur sera identique au parcours du typechecker et non à celui de l'interpréteur.
Donc, comme précédemment il faut fournir une implantation à toute les méthodes visit du visiteur nommé Generator (là où il y a des TODOs) mais avant il faut comprendre un peu le code et les classes annexes qui vous ont été fournies.
Comme d'habitude, les commentaires ont aussi été retiré, à vous de les ajouter.

  1. A quoi sert la classe GenEnv, ou plus précisément,
    • A quoi sert le champs mv ?
    • A quoi servent les champs slotMap et slotCount et pourquoi slotMap n'a pas de parent (comme SymbolTable) ?
    • A quoi sert falseBranchLabel ?
    • A quoi servent les champs breaLabel et continueLabel ,
  2. A quoi sert la classe typechecker.BindingMap ?
    Pourquoi le constructeur de la classe Generator prend une BindingMap en paramètre ?
  3. Ajouter les commentaires de doc pour ces classes.
Maintenant, passont aux choses sérieuses.

* car un des développeurs est quelqu'un que je trouve sympa.