/**
 * Un bloc/frame d'appel a la forme suivante :
 *  valeur de retour, adresse de retour, paramètres
 * La valeur de retour est créée et détruite par la partie appelante.
 * L'adresse de retour et les paramètres sont créés par l'appelant mais détruits
 * par l'appelé.
 */

public class Prog4Traduit {
  public static void main(String []args) {
    // a : 0
    int []memoire = new int[1000];
    int instruction=1;
    int sommetDePile = 1;
    while (true) {
      switch(instruction) {
      case 1: // a = 12;
        memoire[0] = 12; instruction++; break;
      case 2:
        System.out.println("Bonjour"); instruction++; break;
      case 3: // appel à f() stockage adresse de retour
        memoire[sommetDePile] = 4;
        sommetDePile = sommetDePile+1;
        instruction = 100; break;
      case 4:
        System.out.println("Voilà"); instruction++; break;
      case 5: // appel à f(3) stockage adresse de retour et paramètre 3
        memoire[sommetDePile] = 6;
        sommetDePile = sommetDePile+1;
        memoire[sommetDePile] = 3; // le paramètre
        sommetDePile = sommetDePile+1;
        instruction = 200; break;
      case 6:
        System.out.println("Voici");
        instruction++; break;
      case 7: // appel à g(a+5) valeur de retour, adresse de retour, paramètre a+5
        sommetDePile = sommetDePile+1; // création variable valeur de retour
        memoire[sommetDePile] = 8;
        sommetDePile = sommetDePile+1;
        memoire[sommetDePile] = memoire[0]+5; 
        sommetDePile = sommetDePile+1;
        instruction = 300; break;
      case 8: // a = .... (valeur de retour de l'appel à g)
        sommetDePile = sommetDePile-1;
        memoire[0] = 2*memoire[sommetDePile]+3;
        instruction++; break;
      case 9:
        System.out.println("a="+memoire[0]);
        instruction++; break;
      case 10:
        System.exit(0);

      case 100: // f()
        System.out.println("dans f()"); instruction++; break;
      case 101:
        sommetDePile = sommetDePile-1;
        instruction = memoire[sommetDePile];
        break;

      case 200: // f(int a)
        System.out.println("a="+memoire[sommetDePile-1]);
        instruction++; break;
      case 201:
        memoire[sommetDePile-1] = memoire[sommetDePile-1]+1;
        instruction++; break;
      case 202:
        System.out.println("a="+memoire[sommetDePile-1]);
        instruction++; break;
      case 203:
        sommetDePile = sommetDePile-1; // suppression de 'a'
        sommetDePile = sommetDePile-1; // récupération adresse retour
        instruction = memoire[sommetDePile];
        break;

      case 300: // g(int)
        memoire[sommetDePile-1] = memoire[sommetDePile-1]+1;
        instruction++; break;
      case 301:
        memoire[sommetDePile-3] = memoire[sommetDePile-1]+10;
        sommetDePile = sommetDePile-1; // suppression paramèter 'a'
        sommetDePile = sommetDePile-1; // récupération adresse retour
        instruction = memoire[sommetDePile]; break;
      }
    }
  }
}