Pour ceux qui ne suivent pas POJ (Pascal sur la JVM) c'est un compilateur qui transforme un sous-ensemble de Pascal en JASM ( Java Assembly) afin que nous puissions utiliser la JVM comme environnement d'exécution.
Dans le dernier post, le support de read/readln de Pascal a été implémenté, des fonctions qui permettent de lire des données à partir d'une entrée standard (stdin). Dans cette publication, nous réaliserons l'un des objectifs de POJ : lire un nombre à partir d'une entrée standard et calculer la factorielle de manière récursive.
Comme nous compilons pour la JVM, il est nécessaire de détailler le fonctionnement de différents points de cette incroyable machine virtuelle. C'est pourquoi, à différents moments, je détaille le fonctionnement interne de la JVM ainsi que certaines de ses instructions (opcodes).
Comme mentionné au début du projet, un des objectifs était de pouvoir calculer la factorielle de manière récursive, en lisant le nombre à calculer à partir de l'entrée standard. Les implémentations dans POJ à ce jour ont rendu cet objectif possible :
Le moment est désormais venu de valider ce qui a été développé jusqu’à présent. Cela dit, d'après le programme Pascal ci-dessous :
program fatorial; var numero : integer; function fatorial(n : integer) : integer; begin if n<0 then fatorial := 0 else begin if n<=1 then fatorial := 1 else fatorial := n * fatorial(n-1); end; end; begin write('Introduza numero inteiro: '); readln(numero); writeln; writeln('O fatorial de ', numero, ' e: ', fatorial(numero)); end.
POJ génère correctement l'assembly suivant :
// Code generated by POJ 0.1 public class fatorial { public static numero I static fatorial(I)I { iload 0 sipush 0 if_icmpge L4 iconst 1 goto L5 L4: iconst 0 L5: ifeq L1 sipush 0 istore 100 goto L2 L1: iload 0 sipush 1 if_icmpgt L9 iconst 1 goto L10 L9: iconst 0 L10:ifeq L6 sipush 1 istore 100 goto L7 L6: iload 0 iload 0 sipush 1 isub invokestatic fatorial.fatorial(I)I imul istore 100 L7: L2: iload 100 ireturn } public static main([java/lang/String)V { getstatic java/lang/System.out java/io/PrintStream ldc "Introduza numero inteiro: " invokevirtual java/io/PrintStream.print(java/lang/String)V invokestatic java/lang/System.console()java/io/Console invokevirtual java/io/Console.readLine()java/lang/String invokestatic java/lang/Integer.parseInt(java/lang/String)I putstatic fatorial.numero I getstatic java/lang/System.out java/io/PrintStream invokevirtual java/io/PrintStream.println()V getstatic java/lang/System.out java/io/PrintStream ldc "O fatorial de " invokevirtual java/io/PrintStream.print(java/lang/String)V getstatic java/lang/System.out java/io/PrintStream getstatic fatorial.numero I invokevirtual java/io/PrintStream.print(I)V getstatic java/lang/System.out java/io/PrintStream ldc " e: " invokevirtual java/io/PrintStream.print(java/lang/String)V getstatic java/lang/System.out java/io/PrintStream getstatic fatorial.numero I invokestatic fatorial.fatorial(I)I invokevirtual java/io/PrintStream.print(I)V getstatic java/lang/System.out java/io/PrintStream invokevirtual java/io/PrintStream.println()V return } }
Nous arrivons ici à la fin de ce parcours d'apprentissage avec ce projet.
Certaines choses intéressantes dans le domaine des compilateurs peuvent être explorées avec ce projet (comme l'optimisation du code généré). Qui sait, peut-être que dans un futur proche nous commencerons une nouvelle série avec des optimisations :-)
Le référentiel avec le code complet et la documentation du projet est ici.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!