/**
 * Traduction "machine" du programme Simple.java.
 * Il s'agit demontrer comment un appel de fonction est réalisé.
 * Pour cela des conventions d'appel sont nécessaires :
 * - qu'est ce qui est transmis et dans quel ordre ?
 * - qui empile et dépile ?
 *
 * Toute convention fonctionnelle est correcte, même si certaines sont plus
 * malines que d'autres.
 * Ici nous avons convenu de :
 * - on transmet sur la pile en empilant dans l'ordre : l'adresse de retour,
 *   puis les paramètres dans l'ordre de leur apparition dans la définition
 * - l'appellant empile ET dépile tout lui-même.
 *
 * L'effet important à noter (au-delà de la convention) est qu'une fonction
 * accède donc à ses arguments, etc directement DANS la pile, et donc via
 * des adresses relatives!
 */
public class SimpleTraduit {
  public static void main(String []a) {
    // v:0
    // 1.. : la pile
    int []memoire = new int[1000];
    int instructionCourante = 1;
    boolean fin = false;
    int sommetDePile = 1; // adresse du debut de la pile
    while (!fin) {
      switch(instructionCourante) {
        // boucle for
      case 1: // v = 0;
	memoire[0] = 0;
	break;
      case 2: // test v<10 ?
	if (memoire[0]<10) instructionCourante = 3-1; // saut 1ere ins. boucle
	else instructionCourante = 12-1; // saut après boucle
	break;
      case 3: // 1ere ins. du corps de la boucle
	System.out.println("avant appel f()");
	break;
      case 4: // seconde instruction du corps de la boucle
        // préparation de l'appel, i.e. empile dans l'ordre "retour","arguments"
	// push (adresseDeRetour)
	memoire[sommetDePile] = 7-1; // on devra retourne en 7
	sommetDePile++;
	break;
      case 5: // push(v)
	memoire[sommetDePile] = memoire[0];
	sommetDePile++;
	break;
      case 6: // saut vers le debut de la fonction f
	instructionCourante = 1000-1; // tout est prêt
	break;
      case 7: // retour de l'appel on nettoie les choses devenues inutiles
	sommetDePile -= 1; // pop valeur transmise
	break;
      case 8:
	sommetDePile -= 1; // pop adresse de retour
	break;
      case 9: // instruction qui suit l'appel à f()
	System.out.println("apres appel f()");
	break;
      case 10: // v++, fin du corps de la boucle
        memoire[0]++;
	break;
      case 11: // retour au for...
        instructionCourante = 2-1;
	break;
      case 12: // après la boucle for
	System.out.println("Termine");
	break;
      case 13: // appel à f(50)
	memoire[sommetDePile] = 16-1; // adresse de retour 16
        sommetDePile++;
	break;
      case 14: // paramètre de valeur 50
        memoire[sommetDePile] = 50;
        sommetDePile++;
	break;
      case 15: // hop saut vers f()
        instructionCourante = 1000-1;
	break;
      case 16: // retour de l'appel
	sommetDePile--; // pop devenu inutile
	break;
      case 17:
	sommetDePile--; // pop devenu inutile
	break;
      case 18: // fin du programme
	fin = true;
        break;
      case 1000: // debut de la fonction f
	System.out.println("Voici la variable i : "+memoire[sommetDePile-1]);
	break;
      case 1001: // return : retour à l'appelant...
	instructionCourante = memoire[sommetDePile-2];
	break;
      }
      instructionCourante++;
    }
    System.out.println("Le somme de pile est : "+sommetDePile);
  }
}