· code ilp1 [email protected] 28 septembre 2011 ces chiers sont diffusés pour...

61
Code ILP1 [email protected] 28 septembre 2011 Ces fichiers sont diffusés pour l’enseignement ILP (Implantation d’un langage de programmation) dis- pensé depuis l’automne 2004 à l’UPMC (Université Pierre et Marie Curie). Ces fichiers sont diffusés selon les termes de la GPL (Gnu Public Licence). Pour les transparents du cours, la bande son et les autres documents associés, consulter le site http ://www-master.ufr-info-p6.jussieu.fr/site-annuel-courant/ilp Table des matières 4 — LISEZ.MOI 5 — Grammars/Makefile 6 — Grammars/grammar1.rnc 7 — Java/jars/JARS.readme 8 — Java/src/fr/upmc/ilp/ilp1/interfaces/IAST.java 8 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTalternative.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTbinaryOperation.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTboolean.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTconstant.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTfloat.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinteger.java 9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinvocation.java 10 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASToperation.java 10 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTsequence.java 11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTstring.java 11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryBlock.java 11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryOperation.java 11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTvariable.java 11 — Java/src/fr/upmc/ilp/ilp1/fromxml/AST.java 12 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTException.java 12 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParser.java 15 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParserTest.java 20 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTalternative.java 21 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTblocUnaire.java 22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTbooleen.java 22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTchaine.java 22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTentier.java 23 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTflottant.java 23 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTfromXML.java 24 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocation.java 24 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocationPrimitive.java 25 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperation.java 25 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationBinaire.java 26 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationUnaire.java 26 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTsequence.java 27 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTvariable.java 27 — Java/src/fr/upmc/ilp/ilp1/fromxml/Main.java 28 — Java/src/fr/upmc/ilp/ilp1/fromxml/MainTest.java 29 — Java/src/fr/upmc/ilp/ilp1/fromxml/MainTestSuite.java 30 — Java/src/fr/upmc/ilp/ilp1/runtime/AbstractInvokableImpl.java 30 — Java/src/fr/upmc/ilp/ilp1/runtime/Common.java 33 — Java/src/fr/upmc/ilp/ilp1/runtime/CommonPlus.java 40 — Java/src/fr/upmc/ilp/ilp1/runtime/ConstantsStuff.java 41 — Java/src/fr/upmc/ilp/ilp1/runtime/EmptyLexicalEnvironment.java 42 — Java/src/fr/upmc/ilp/ilp1/runtime/EvaluationException.java 42 — Java/src/fr/upmc/ilp/ilp1/runtime/ICommon.java 42 — Java/src/fr/upmc/ilp/ilp1/runtime/ILexicalEnvironment.java 1 42 — Java/src/fr/upmc/ilp/ilp1/runtime/Invokable.java 43 — Java/src/fr/upmc/ilp/ilp1/runtime/LexicalEnvironment.java 44 — Java/src/fr/upmc/ilp/ilp1/runtime/PrintStuff.java 45 — Java/src/fr/upmc/ilp/ilp1/eval/EAST.java 45 — Java/src/fr/upmc/ilp/ilp1/eval/EASTConstant.java 46 — Java/src/fr/upmc/ilp/ilp1/eval/EASTException.java 46 — Java/src/fr/upmc/ilp/ilp1/eval/EASTFactory.java 47 — Java/src/fr/upmc/ilp/ilp1/eval/EASTFileTest.java 49 — Java/src/fr/upmc/ilp/ilp1/eval/EASTParser.java 53 — Java/src/fr/upmc/ilp/ilp1/eval/EASTPrimitiveTest.java 54 — Java/src/fr/upmc/ilp/ilp1/eval/EASTTest.java 58 — Java/src/fr/upmc/ilp/ilp1/eval/EASTalternative.java 59 — Java/src/fr/upmc/ilp/ilp1/eval/EASTblocUnaire.java 60 — Java/src/fr/upmc/ilp/ilp1/eval/EASTbooleen.java 60 — Java/src/fr/upmc/ilp/ilp1/eval/EASTchaine.java 61 — Java/src/fr/upmc/ilp/ilp1/eval/EASTentier.java 61 — Java/src/fr/upmc/ilp/ilp1/eval/EASTflottant.java 62 — Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocation.java 62 — Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocationPrimitive.java 63 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperation.java 63 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperationBinaire.java 64 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperationUnaire.java 65 — Java/src/fr/upmc/ilp/ilp1/eval/EASTsequence.java 65 — Java/src/fr/upmc/ilp/ilp1/eval/EASTvariable.java 66 — Java/src/fr/upmc/ilp/ilp1/eval/IASTEvaluable.java 66 — Java/src/fr/upmc/ilp/ilp1/eval/IEASTFactory.java 67 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenEnvironment.java 69 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenLexicalEnvironment.java 70 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenerationException.java 70 — Java/src/fr/upmc/ilp/ilp1/cgen/Cgenerator.java 74 — Java/src/fr/upmc/ilp/ilp1/cgen/CgeneratorTest.java 76 — Java/src/fr/upmc/ilp/ilp1/cgen/ICgenEnvironment.java 77 — Java/src/fr/upmc/ilp/ilp1/cgen/ICgenLexicalEnvironment.java 77 — Java/src/fr/upmc/ilp/ilp1/CoverageTest.java 78 — Java/src/fr/upmc/ilp/ilp1/JDependTest.java 78 — Java/src/fr/upmc/ilp/ilp1/Process.java 80 — Java/src/fr/upmc/ilp/ilp1/ProcessTest.java 80 — Java/src/fr/upmc/ilp/ilp1/WholeTestSuite.java 81 — Java/src/fr/upmc/ilp/tool/AbstractEnvironment.java 81 — Java/src/fr/upmc/ilp/tool/AbstractProcess.java 84 — Java/src/fr/upmc/ilp/tool/AbstractProcessTest.java 89 — Java/src/fr/upmc/ilp/tool/AbstractProcessTestTest.java 90 — Java/src/fr/upmc/ilp/tool/CStuff.java 90 — Java/src/fr/upmc/ilp/tool/CStuffTest.java 91 — Java/src/fr/upmc/ilp/tool/File.java 92 — Java/src/fr/upmc/ilp/tool/FileTool.java 93 — Java/src/fr/upmc/ilp/tool/FileToolTest.java 94 — Java/src/fr/upmc/ilp/tool/Finder.java 95 — Java/src/fr/upmc/ilp/tool/FinderTest.java 96 — Java/src/fr/upmc/ilp/tool/IContent.java 97 — Java/src/fr/upmc/ilp/tool/IFinder.java 97 — Java/src/fr/upmc/ilp/tool/IProcess.java 98 — Java/src/fr/upmc/ilp/tool/IProcessListener.java 99 — Java/src/fr/upmc/ilp/tool/Parameterized.java 100 — Java/src/fr/upmc/ilp/tool/ProgramCaller.java 103 — Java/src/fr/upmc/ilp/tool/ProgramCallerTest.java 105 — Java/src/fr/upmc/ilp/tool/ToolTestSuite.java 105 — Java/src/fr/upmc/ilp/annotation/ILPexpression.java 106 — Java/src/fr/upmc/ilp/annotation/ILPforParsing.java 106 — Java/src/fr/upmc/ilp/annotation/ILPvariable.java 107 — Java/src/fr/upmc/ilp/annotation/OrNull.java 107 — C/C.readme 107 — C/Makefile 108 — C/compileThenRun.sh 111 — C/ilp.c 115 — C/ilp.h 118 — C/ilpAlloc.c 2

Upload: others

Post on 25-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

Code ILP1

[email protected]

28 septembre 2011

Ces fichiers sont diffusés pour l’enseignement ILP (Implantation d’un langage de programmation) dis-pensé depuis l’automne 2004 à l’UPMC (Université Pierre et Marie Curie). Ces fichiers sont diffusés selonles termes de la GPL (Gnu Public Licence). Pour les transparents du cours, la bande son et les autresdocuments associés, consulter le site http ://www-master.ufr-info-p6.jussieu.fr/site-annuel-courant/ilp

Table des matières4 — LISEZ.MOI5 — Grammars/Makefile6 — Grammars/grammar1.rnc7 — Java/jars/JARS.readme8 — Java/src/fr/upmc/ilp/ilp1/interfaces/IAST.java8 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTalternative.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTbinaryOperation.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTboolean.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTconstant.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTfloat.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinteger.java9 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinvocation.java10 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASToperation.java10 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTsequence.java11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTstring.java11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryBlock.java11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryOperation.java11 — Java/src/fr/upmc/ilp/ilp1/interfaces/IASTvariable.java11 — Java/src/fr/upmc/ilp/ilp1/fromxml/AST.java12 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTException.java12 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParser.java15 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParserTest.java20 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTalternative.java21 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTblocUnaire.java22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTbooleen.java22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTchaine.java22 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTentier.java23 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTflottant.java23 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTfromXML.java24 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocation.java24 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocationPrimitive.java25 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperation.java25 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationBinaire.java26 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationUnaire.java26 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTsequence.java27 — Java/src/fr/upmc/ilp/ilp1/fromxml/ASTvariable.java27 — Java/src/fr/upmc/ilp/ilp1/fromxml/Main.java28 — Java/src/fr/upmc/ilp/ilp1/fromxml/MainTest.java29 — Java/src/fr/upmc/ilp/ilp1/fromxml/MainTestSuite.java30 — Java/src/fr/upmc/ilp/ilp1/runtime/AbstractInvokableImpl.java30 — Java/src/fr/upmc/ilp/ilp1/runtime/Common.java33 — Java/src/fr/upmc/ilp/ilp1/runtime/CommonPlus.java40 — Java/src/fr/upmc/ilp/ilp1/runtime/ConstantsStuff.java41 — Java/src/fr/upmc/ilp/ilp1/runtime/EmptyLexicalEnvironment.java42 — Java/src/fr/upmc/ilp/ilp1/runtime/EvaluationException.java42 — Java/src/fr/upmc/ilp/ilp1/runtime/ICommon.java42 — Java/src/fr/upmc/ilp/ilp1/runtime/ILexicalEnvironment.java

1

42 — Java/src/fr/upmc/ilp/ilp1/runtime/Invokable.java43 — Java/src/fr/upmc/ilp/ilp1/runtime/LexicalEnvironment.java44 — Java/src/fr/upmc/ilp/ilp1/runtime/PrintStuff.java45 — Java/src/fr/upmc/ilp/ilp1/eval/EAST.java45 — Java/src/fr/upmc/ilp/ilp1/eval/EASTConstant.java46 — Java/src/fr/upmc/ilp/ilp1/eval/EASTException.java46 — Java/src/fr/upmc/ilp/ilp1/eval/EASTFactory.java47 — Java/src/fr/upmc/ilp/ilp1/eval/EASTFileTest.java49 — Java/src/fr/upmc/ilp/ilp1/eval/EASTParser.java53 — Java/src/fr/upmc/ilp/ilp1/eval/EASTPrimitiveTest.java54 — Java/src/fr/upmc/ilp/ilp1/eval/EASTTest.java58 — Java/src/fr/upmc/ilp/ilp1/eval/EASTalternative.java59 — Java/src/fr/upmc/ilp/ilp1/eval/EASTblocUnaire.java60 — Java/src/fr/upmc/ilp/ilp1/eval/EASTbooleen.java60 — Java/src/fr/upmc/ilp/ilp1/eval/EASTchaine.java61 — Java/src/fr/upmc/ilp/ilp1/eval/EASTentier.java61 — Java/src/fr/upmc/ilp/ilp1/eval/EASTflottant.java62 — Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocation.java62 — Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocationPrimitive.java63 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperation.java63 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperationBinaire.java64 — Java/src/fr/upmc/ilp/ilp1/eval/EASToperationUnaire.java65 — Java/src/fr/upmc/ilp/ilp1/eval/EASTsequence.java65 — Java/src/fr/upmc/ilp/ilp1/eval/EASTvariable.java66 — Java/src/fr/upmc/ilp/ilp1/eval/IASTEvaluable.java66 — Java/src/fr/upmc/ilp/ilp1/eval/IEASTFactory.java67 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenEnvironment.java69 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenLexicalEnvironment.java70 — Java/src/fr/upmc/ilp/ilp1/cgen/CgenerationException.java70 — Java/src/fr/upmc/ilp/ilp1/cgen/Cgenerator.java74 — Java/src/fr/upmc/ilp/ilp1/cgen/CgeneratorTest.java76 — Java/src/fr/upmc/ilp/ilp1/cgen/ICgenEnvironment.java77 — Java/src/fr/upmc/ilp/ilp1/cgen/ICgenLexicalEnvironment.java77 — Java/src/fr/upmc/ilp/ilp1/CoverageTest.java78 — Java/src/fr/upmc/ilp/ilp1/JDependTest.java78 — Java/src/fr/upmc/ilp/ilp1/Process.java80 — Java/src/fr/upmc/ilp/ilp1/ProcessTest.java80 — Java/src/fr/upmc/ilp/ilp1/WholeTestSuite.java81 — Java/src/fr/upmc/ilp/tool/AbstractEnvironment.java81 — Java/src/fr/upmc/ilp/tool/AbstractProcess.java84 — Java/src/fr/upmc/ilp/tool/AbstractProcessTest.java89 — Java/src/fr/upmc/ilp/tool/AbstractProcessTestTest.java90 — Java/src/fr/upmc/ilp/tool/CStuff.java90 — Java/src/fr/upmc/ilp/tool/CStuffTest.java91 — Java/src/fr/upmc/ilp/tool/File.java92 — Java/src/fr/upmc/ilp/tool/FileTool.java93 — Java/src/fr/upmc/ilp/tool/FileToolTest.java94 — Java/src/fr/upmc/ilp/tool/Finder.java95 — Java/src/fr/upmc/ilp/tool/FinderTest.java96 — Java/src/fr/upmc/ilp/tool/IContent.java97 — Java/src/fr/upmc/ilp/tool/IFinder.java97 — Java/src/fr/upmc/ilp/tool/IProcess.java98 — Java/src/fr/upmc/ilp/tool/IProcessListener.java99 — Java/src/fr/upmc/ilp/tool/Parameterized.java100 — Java/src/fr/upmc/ilp/tool/ProgramCaller.java103 — Java/src/fr/upmc/ilp/tool/ProgramCallerTest.java105 — Java/src/fr/upmc/ilp/tool/ToolTestSuite.java105 — Java/src/fr/upmc/ilp/annotation/ILPexpression.java106 — Java/src/fr/upmc/ilp/annotation/ILPforParsing.java106 — Java/src/fr/upmc/ilp/annotation/ILPvariable.java107 — Java/src/fr/upmc/ilp/annotation/OrNull.java107 — C/C.readme107 — C/Makefile108 — C/compileThenRun.sh111 — C/ilp.c115 — C/ilp.h118 — C/ilpAlloc.c

2

Page 2:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

118 — C/ilpAlloc.h118 — C/ilpBasicError.c119 — C/ilpBasicError.h119 — C/ilpException.c120 — C/ilpException.h120 — C/templateTest.c

3

LISEZ.MOI

1 Ces fichiers sont diffusés pour l’enseignement ILP (Implantationd’un langage de programmation) dispensé depuis l’automne 2004 à l’UPMC(Université Pierre et Marie Curie). Ces fichiers sont diffusés selonles termes de la GPL (Gnu Public Licence). Pour les transparents ducours, la bande son et les autres documents associés, consulter le

6 site http://www-master.ufr-info-p6.jussieu.fr/site-annuel-courant/ilp

Adressez -moi toutes vos remarques concernant ce cours ou ces fichiersavec un courriel dont le titre contient la chaîne « ILP » ou, mieux,postez-les sur le forum associé au cours.

11

Quelques détails sur ILP=======================

Quelques répertoires contiennent de sommaires documentations dans des16 fichiers *.readme ou LISEZ.MOI. C’est le cas pour

Compiler/C/C.readmeCompiler/Java/jars/JARS.readme

21 Les Makefile sont également d’importantes sources d’information.

Installation============

26 Si vous lisez ce fichier c’est probablement que vous avez décompresséle fichier ILP-uneCertaineDate.tgz. Assurez vous que les répertoiresCompiler/, PlugIns/ etc. sont bien juste en dessous de votre espace detravail pour Eclipse (usuellement ~/workspace/). Le TME1 indique lamarche à suivre pour configurer votre Eclipse.

31

Demandez l’importation (menu File) de projets existant dans l’espacede travail (catégorie General) passez à la suite avec Next etsélectionnez alors le répertoire correspondant à l’espace de travail.Eclipse s’aperçoit alors que des projets existent déjà et tentera de

36 les récupérer tels quels.

Une fois ceci fait, pour tester que tout va bien, lancer la classefr.upmc.ilp.ilp1.WholeTestSuite (menu contextuel run as "JUnit Test"):tout doit passer au vert!

41

Greffon ILP===========

46 Depuis 2006, ILP a introduit un nouveau greffon à incorporer à Eclipse(au moins 3.2), facilitant quelques opérations. Ce greffon introduitquelques opérations contextuelles dans l’explorateur de projet. Voici,par type de fichiers, les opérations principales que l’on peutobtenir (dans le sous-menu ILP):

51

Sur un fichier .rnc (une grammaire compacte d’ILP)- conversion en .rng

Sur un fichier .rng (une grammaire (en XML) pour ILP)- positionnement comme grammaire ILP par défaut

56 Sur un fichier .xml (un programme ILP)- validation vis-à-vis d’une grammaire ILP choisie dynamiquement- validation vis-à-vis de la grammaire ILP par défaut

(il existe maintenant sous Eclipse 3.3, un menu contextuel "Validate"qui ne vérifie que la conformité syntaxique vis-à-vis d’XML).

61 Sur un répertoire (de grammaires .rng)- positionnement comme répertoire des grammaires par défaut

La grammaire par défaut et le répertoire des grammaires par défaut nesont pas conservés entre deux sessions.

66

Le greffon est susceptible d’évoluer, abonnez-vous au site de mise à jouren http://www.master.info.upmc.fr/2011/Ext/queinnec/ILP/ce qui va aussi servir à l’installer. Dans le Menu Help, cherchezSoftware Updates, Find and Install, Search for new features to install,

71 new Remote Site. Remplissez le formulaire en indiquant qu’ILP est à l’urlhttp://www.master.info.upmc.fr/2011/Ext/queinnec/ILP/, OKpuis Finish. Eclipse cherche alors le greffon...

Autres greffons76 ===============

D’autres greffons sont utiles (ou intéressants) mais on peut s’enpasser, je tenterai toutefois de les faire inclure dans l’installation

4

Page 3:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

à l’ARI. Ce sont:81

Checkstylehttp://eclipse-cs.sourceforge.net/

Jdepend pour eclipsehttp://andrei.gmxhome.de/eclipse/

86 PMD pour Eclipsehttp://pmd.sf.net/eclipse

FindBugshttp://findbugs.cs.umd.edu/eclipse

91 Depuis Eclipse Helios, on peut installer ces greffons grâce au menuHelp puis Eclipse Market. Chercher alors le greffon par son nom etl’installer.

Emacs96 =====

Le paquetage nxml est réputé. Il se trouve enhttp://www.thaiopensource.com/download/nxml-mode -20041004.tar.gz

mais une copie est dans le répertoire ELISP/ ainsi qu’un mode101 pour éditer des schémas RelaxNG facilement. On peut aussi demander à

Eclipse de plutôt lancer Emacs sur ces fichiers.

Divers======

106

Depuis la 3.2, Eclipse dispose d’un éditeur structurel de XML (suffixe.xml) ainsi qu’un éditeur de grammaires XMLSchema (suffixe .xsd).

Mon Eclipse est réglé, depuis cette année, sur UTF-8, La plupart des111 fichiers *.java sont dans ce mode mais d’autres sont restés en Latin1

(iso-8859-1 ou -15). C’est un mal qui affecte le monde entier et quine sera surmonté qu’avec le temps.

Grammars/Makefile

1 work : create.rng.files \validate.xml.files

clean :: cleanMakefile-rm -f grammar*.rng

6 # Regenerer toutes les grammaires possibles.all :

for g in *.rnc ; do make $${g%c}g ; done

# 2007sep06: trang ne fonctionne pas avec le java d’Ubuntu (gij)! De11 # plus, le code de trang n’est pas generique (a ne pas recompiler donc).

JAVA = javaTRANG = ../Java/jars/trang.jarJING = ../Java/jars/jing.jar

16 #CODING = iso-8859-15CODING = utf-8

.SUFFIXES: .rnc .rng .xsd .dtd

.rnc.rng :21 ${JAVA} -jar ${TRANG} \

-i encoding=${CODING} \-o encoding=${CODING} \$*.rnc $*.rng

.rnc.xsd :26 ${JAVA} -jar ${TRANG} \

-i encoding=${CODING} \-o encoding=${CODING} \$*.rnc $*.xsd

.rnc.dtd :31 ${JAVA} -jar ${TRANG} \

-i encoding=${CODING} \-o encoding=${CODING} \$*.rnc $*.dtd

36 # NOTA: Valider un document XML d.xml avec un schéma f.rng et jing ainsi:# ${JAVA} -jar ${JING} f.rng d.xml

GRAMMARS = \grammar1.rnc \

41 grammar2.rnc \grammar3.rnc \grammar4.rnc \

5

grammar5.rnc \grammar6.rnc

46

# Créer les équivalents XML des schémas RelaxNG compacts:

create.rng.files : ${GRAMMARS:.rnc=.rng}

51 # Creer les équivalents XSD des schémas RelaxNG compacts:

create.xsd.files : ${GRAMMARS:.rnc=.xsd}

# Les grammaires s’incluent ce qui cree des dependances:56 grammar2.rng : grammar1.rng

grammar3.rng : grammar2.rnggrammar4.rng : grammar3.rnggrammar5.rng : grammar4.rnggrammar6.rng : grammar4.rng

61

# Valider les exemples de programmes qui sont en Samples/# Verifier que les grammaires sont bien incluses: tout ce que reconnait# grammar1 doit etre reconnu par grammar2, etc.

66 validate.xml.files : ${GRAMMARS:.rnc=.rng}for i in 6 5 4 3 2 1 ; do \for p in Samples/?*-[1-$$i].xml ; do \echo Validating $$p with grammar$$i ; \${JAVA} -jar ${JING} grammar$$i.rng $$p ; \

71 done ; done

Grammars/grammar1.rnc

# Première version du langage étudié: ILP1 pour « Innocent Langage# Parachuté. » Il sera complété dans les cours qui suivent.

3

start = programme1

programme1 = element programme1 {instructions

8 }

instructions = instruction +

# Ce langage est un langage d’instructions , assez réduit pour13 # l’instant. Voici les instructions possibles:

instruction =alternative

| sequence18 | blocUnaire

| expression

# Le si-alors-sinon. L’alternant est facultatif car c’est un langage# d’instructions.

23

alternative = element alternative {element condition { expression },element consequence { instructions },element alternant { instructions } ?

28 }

# La séquence qui permet de regrouper plusieurs instructions en une seule.# Il est obligatoire qu’il y ait au moins une instruction dans la séquence.

33 sequence = element sequence {instructions

}

# Un bloc local unaire. C’est, pour l’instant, la seule construction38 # permettant d’introduire une variable localement. Elle sera bientôt remplacée

# par une construction permettant d’introduire plusieurs variables# locales en meme temps.

blocUnaire = element blocUnaire {43 variable ,

element valeur { expression },element corps { instructions }

}

48 # Comme en C, une expression est une instruction dont la valeur est# ignorée. Il n’y a pas d’expression parenthésée car ce n’est qu’une

6

Page 4:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

# fioriture syntaxique. Les expressions sont:

expression =53 constante

| variable| operation| invocationPrimitive

58 # Une variable n’est caractérisée que par son nom. Les variables dont# les noms comportent la séquence ilp ou ILP sont réservés et ne# peuvent être utilisés par les programmeurs.# FUTUR: restreindre plus les noms de variables aux seuls caracteres normaux!

63 variable = element variable {attribute nom { xsd:Name - ( xsd:Name { pattern = "(ilp|ILP)" } ) },empty

}

68 # L’invocation d’une fonction primitive. Une fonction primitive est# procurée par l’implantation et ne peut (usuellement) être définie# par l’utilisateur. Les fonctions primitives sont, pour être# utilisables , prédéfinies. Une fonction primitive n’est caractérisée# que par son nom (éventuellement masquable).

73

invocationPrimitive = element invocationPrimitive {attribute fonction { xsd:Name },expression *

}78

# Les opérations sont en fait des sortes d’invocations à des fonctions# primitives sauf que ces fonctions sont implantées par le matériel# par des instructions particulières. On ne distingue que les# opérations unaires et binaires (les plus usuelles):

83

operation =operationUnaire

| operationBinaire

88 operationUnaire = element operationUnaire {attribute operateur { "-" | "!" },element operande { expression }

}operationBinaire = element operationBinaire {

93 element operandeGauche { expression },attribute operateur {

"+" | "-" | "*" | "/" | "%" | # arithmétiques"|" | "&" | "^" | # booléens"<" | "<=" | "==" | ">=" | ">" | "<>" | "!=" # comparaisons

98 },element operandeDroit { expression }

}

# Les constantes sont les données qui peuvent apparaître dans les103 # programmes sous forme textuelle (ou littérale comme l’on dit

# souvent). Ici l’on trouve toutes les constantes usuelles à part les# caractères:

constante =108 element entier {

attribute valeur { xsd:integer },empty }

| element flottant {attribute valeur { xsd:float },

113 empty }| element chaine { text }| element booleen {

attribute valeur { "true" | "false" },empty }

Java/jars/JARS.readme

Ce répertoire contient des archives .jar contenant les classes et ressources2 utiles pour les bibliothèques telles que jing ou trang. Les paquets .tgz

ou .zip contiennent les distributions originales et notamment la documentationdes interfaces (API).

Les bibliothèques vraiment importantes sont7 jing.jar

trang.jarxmlunit1.3.jar

7

jcommander -1.18

12 Les bibliothèques Junit (3 et 4) à utiliser sont celles fournies par Eclipse.

JCommander est une bibliothèque pour analyser les options de la lignede commander. Elle n’est utilisée que pour des tests.

17 Les documentations (Javadoc) de jing et trang sont dans le .zip demême nom. Il faut indiquer à Eclipse où elles sont pour l’aidecontextuelle.

Les autres bibliothèques sont les suivantes22 hansel une bibliothèque pour mesurer les taux de couverture de test

bcel une bibliothèque d’instrumentation de code octet utiliséepar hansel

easymock une bibliothèque pour aider aux tests.

Java/src/fr/upmc/ilp/ilp1/interfaces/IAST.java

package fr.upmc.ilp.ilp1.interfaces;

/** Interface des arbres de syntaxe abstraite.4 *

* Les arbres de syntaxe abstraite (AST) ne sont utilisés que via* cette interface ou, plus exactement , via une de ses* sous-interfaces. Cette interface ressemble un peu à celle du DOM* (Document Object Model) sauf qu’elle est beaucoup plus légère: elle

9 * est plus typée mais elle ne permet que de descendre dans les AST.** La raison d’être de cette interface est qu’elle sert de point de* rencontre entre les analyseurs syntaxiques qui doivent produire des* IAST qui seront ainsi manipulables par les premières passes de

14 * l’interprète ou du compilateur.*/

public interface IAST {

19 /** Décrit l’AST sous forme d’une chaîne imprimable.** En fait, c’était pour mettre quelque chose (ce qui n’est pas* obligatoire) ! Cette méthode vient avec toute implantation* puisque l’objet implantant hérite d’Object qui définit

24 * toString()! Par contre, la mentionner ici rend sa définition* explicite obligatoire dans les classes qui implantent IAST.*/

String toString ();

29 // FUTURE ajoute-t-on toXML() pour sérialiser les IAST ?

}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTalternative.java

package fr.upmc.ilp.ilp1.interfaces;

3 import fr.upmc.ilp.annotation.OrNull;

/** Décrit une alternative (si-alors-sinon).** Une alternative comporte une condition (booléenne), une conséquence

8 * (une expression quelconque) ainsi, éventuellement , qu’un alternant* (une expression aussi). La méthode isTernary() permet de distinguer* entre ces deux cas.*/

13 public interface IASTalternative extends IAST {

/** Renvoie la condition. */IAST getCondition ();

18 /** Renvoie la conséquence. */IAST getConsequent ();

/** Renvoie l’alternant si présent ou null. */@OrNull IAST getAlternant ();

23

/** Indique si l’alternative est ternaire (qu’elle a un alternant). */boolean isTernary ();

}8

Page 5:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTbinaryOperation.java

package fr.upmc.ilp.ilp1.interfaces;

3 /** Interface décrivant les opérations binaires.** Cette interface hérite de celle des opérations qui permet l’accès* à l’opérateur et à la liste des opérandes.*/

8

public interface IASTbinaryOperation extends IASToperation {

/** renvoie l’opérande de gauche. */IAST getLeftOperand ();

13

/** renvoie l’opérande de droite. */IAST getRightOperand ();

}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTboolean.java

package fr.upmc.ilp.ilp1.interfaces;

3 /** Decrit la citation d’un booleen. */

public interface IASTboolean extends IASTconstant {/** Renvoie le booleen cite. */boolean getValue ();

8 }

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTconstant.java

package fr.upmc.ilp.ilp1.interfaces;2

/** Decrit une constante litterale. Cette interface n’existe que pour* etre raffinee en des sous-interfaces plus specialisees. */

public interface IASTconstant extends IAST {}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTfloat.java

package fr.upmc.ilp.ilp1.interfaces;

import java.math.BigDecimal;4

/** Citation d’un flottant. */

public interface IASTfloat extends IASTconstant {/** Renvoie le flottant cité comme constante. */

9 BigDecimal getValue ();}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinteger.java

package fr.upmc.ilp.ilp1.interfaces;

import java.math.BigInteger;

5 /** Citation d’un entier. */

public interface IASTinteger extends IASTconstant {/** Renvoie l’entier cite comme constante. */BigInteger getValue ();

10 }

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTinvocation.java

9

package fr.upmc.ilp.ilp1.interfaces;

import fr.upmc.ilp.annotation.OrNull;

5

/** Décrit une invocation de fonction. La fonction peut être calculée* ou pas, c’est néanmoins un AST. Si le nom n’est pas calculée, c’est* une référence à un nom de variable (car, en JavaScript , les* fonctions sont dans le même espace de nom).

10 */

public interface IASTinvocation extends IAST {

/** Renvoie la fonction invoquée. */15 IAST getFunction ();

/** Renvoie les arguments de l’invocation sous forme d’une liste. */IAST[] getArguments ();

20 /** Renvoie le nombre d’arguments de l’invocation. */int getArgumentsLength ();

/** Renvoie le i-ème argument de l’invocation ou null. */@OrNull IAST getArgument (int i);

25 }

Java/src/fr/upmc/ilp/ilp1/interfaces/IASToperation.java

package fr.upmc.ilp.ilp1.interfaces;

4 /** Interface décrivant les opérations.** Une opération implique un opérateur et un ou plusieurs opérandes.* Les opérations peuvent être unaires ou binaires cf. les* sous-interfaces appropriées.

9 */

public interface IASToperation extends IAST {

/** Renvoie le nom de l’opérateur concerné par l’opération. */14 String getOperatorName ();

/** Renvoie l’arité de l’opérateur concerné par l’opération. L’arité* est toujours de 1 pour une IASTunaryOperation et de 2 pour une* IASTbinaryOperation. */

19 int getArity ();

/** Renvoie les opérandes d’une opération.** NOTA: cette méthode est générale, les méthodes d’accès aux

24 * opérandes des opérations unaires ou binaires sont, probablement ,* plus efficaces.** NOTA2: normalement le nombre d’operandes doit être égal à l’arité* de l’opérateur (mais il se peut que certains opérateurs soit n-aires)

29 * auquel cas, que l’arité soit un simple entier n’est pas une bonne idée!*/

IAST[] getOperands ();}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTsequence.java

package fr.upmc.ilp.ilp1.interfaces;2

import fr.upmc.ilp.annotation.OrNull;

/** Décrit une séquence d’instructions. On reprend le même* style d’interface que IASTinvocation. */

7

public interface IASTsequence extends IAST {

/** Renvoie la séquence des instructions contenues. */IAST[] getInstructions ();

12

/** Renvoie le nombre d’instructions de la sequence. */int getInstructionsLength ();

10

Page 6:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** Renvoie la i-ème instruction ou null. */17 @OrNull IAST getInstruction (int i);

// FUTURE ? ajouter getAllButLastInstructions() ???}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTstring.java

package fr.upmc.ilp.ilp1.interfaces;

/** Citation d’une chaine de caracteres.*/4

public interface IASTstring extends IASTconstant {/** Renvoie la chaine de caracteres citee. */String getValue ();

}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryBlock.java

package fr.upmc.ilp.ilp1.interfaces;2

/** Décrit un bloc local ne liant qu’une unique variable. */

public interface IASTunaryBlock extends IAST {

7 /** Renvoie la variable liée localement. */IASTvariable getVariable();

/** Renvoie l’expression initialisant la variable locale. */IAST getInitialization();

12

/** Renvoie la sequence d’instructions présentes dans le corps du* bloc local. */

IASTsequence getBody();}

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTunaryOperation.java

package fr.upmc.ilp.ilp1.interfaces;

3 /** Interface décrivant les opérations unaires. */

public interface IASTunaryOperation extends IASToperation {/** renvoie l’unique operande. */IAST getOperand ();

8 }

Java/src/fr/upmc/ilp/ilp1/interfaces/IASTvariable.java

package fr.upmc.ilp.ilp1.interfaces;2

/*** Cette interface décrit une variable mais seulement une variable. D’autres* interfaces existent pour lire ou écrire des variables. Usuellement , les* variables n’apparaissent que dans des lieurs (fonctions , methodes ou blocs

7 * locaux).*/

public interface IASTvariable extends IAST {/** Renvoie le nom de la variable. */

12 String getName();}

Java/src/fr/upmc/ilp/ilp1/fromxml/AST.java

11

package fr.upmc.ilp.ilp1.fromxml;2 import fr.upmc.ilp.ilp1.interfaces.*;

public abstract class AST implements IAST {

/** Décrit l’AST en XML (surtout utile pour la mise au point).7 *

* NOTA: cette signature conduit à une implantation naïve* déraisonnablement coûteuse! Il vaudrait mieux se trimballer un* unique StringBuffer dans lequel concaténer les fragments XML.*/

12

public abstract String toXML ();

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTException.java

package fr.upmc.ilp.ilp1.fromxml;

/** Une exception comme les autres mais qu’utilisent préférentiellement4 * les classes du paquetage fromxml.

*/

public class ASTException extends Exception {

9 static final long serialVersionUID = +1234567890001000L;

public ASTException (Throwable cause) {super(cause);

}14

public ASTException (String message) {super(message);

}

19 }

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParser.java

package fr.upmc.ilp.ilp1.fromxml;import java.util.List;import java.util.Vector;

5 import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;

10 /** Le but de cette classe est de transformer un document XML en un* AST conforme à fr.upmc.ilp.interfaces.IAST. */

public class ASTParser {

15 /** Constructeur. */

public ASTParser () {}

/** Transformer un document (ou un n?ud) DOM en un AST (et donc un20 * IAST).

** C’est une grande méthode monolithique qui analyse le DOM (une* structure de données arborescente correspondant au document XML* initial) en un AST où chaque n?ud est typé suivant sa catégorie

25 * syntaxique. Il est difficile d’avoir un style objet sur ce type* de code qui correspond à une construction. Nous verrons une* nouvelle organisation de ce code bientôt.** @throws ASTException en cas de problème.

30 * NOTA: comme le document d’entrée est supposé être valide pour le* schéma RelaxNG approprié , de nombreux risques d’erreur sont ainsi* éliminés et ne sont donc pas explicitement testés. Par exemple,* le fait qu’un fils « condition » apparaît toujours sous «* alternative , » que l’attribut « valeur » est présent dans «

35 * entier, » etc. Tous ces faits sont assumés corrects.*/

12

Page 7:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

public AST parse (Node n)throws ASTException {

40 switch ( n.getNodeType() ) {

case Node.DOCUMENT_NODE: {Document d = (Document) n;return this.parse(d.getDocumentElement());

45 }

case Node.ELEMENT_NODE: {Element e = (Element) n;NodeList nl = e.getChildNodes();

50 String name = e.getTagName();

if ( "programme1".equals(name) ) {return new ASTsequence(parseList(nl));

55 } else if ( "alternative".equals(name) ) {AST cond = findThenParseChild(nl, "condition");AST conseq = findThenParseChildAsInstructions(nl, "consequence");try {

AST alt = findThenParseChildAsInstructions(nl, "alternant");60 return new ASTalternative(cond, conseq, alt);

} catch (ASTException exc) {return new ASTalternative(cond, conseq);

}

65 } else if ( "sequence".equals(name) ) {return new ASTsequence(this.parseList(nl));

} else if ( "blocUnaire".equals(name) ) {ASTvariable var = (ASTvariable) findThenParseChild(nl, "variable");

70 AST init = findThenParseChild(nl, "valeur");ASTsequence body = (ASTsequence) findThenParseChild(nl, "corps");return new ASTblocUnaire(var, init, body);

} else if ( "variable".equals(name) ) {75 // La variable sera, suivant les contextes , encapsulée

// dans une référence.String nick = e.getAttribute("nom");return new ASTvariable(nick);

80 } else if ( "invocationPrimitive".equals(name) ) {String op = e.getAttribute("fonction");List<AST> largs = parseList(nl);return new ASTinvocationPrimitive(op, largs.toArray(new AST[0]));

85 } else if ( "operationUnaire".equals(name) ) {String op = e.getAttribute("operateur");AST rand = findThenParseChild(nl, "operande");return new ASToperationUnaire(op, rand);

90 } else if ( "operationBinaire".equals(name) ) {String op = e.getAttribute("operateur");AST gauche = findThenParseChild(nl, "operandeGauche");AST droite = findThenParseChild(nl, "operandeDroit");return new ASToperationBinaire(op, gauche, droite);

95

} else if ( "entier".equals(name) ) {return new ASTentier(e.getAttribute("valeur"));

} else if ( "flottant".equals(name) ) {100 return new ASTflottant(e.getAttribute("valeur"));

} else if ( "chaine".equals(name) ) {String text = e.getTextContent();return new ASTchaine(text);

105

} else if ( "booleen".equals(name) ) {return new ASTbooleen(e.getAttribute("valeur"));

// Une série d’éléments devant être analysés comme des expressions:110 } else if ( "operandeGauche".equals(name) ) {

return this.parseUniqueChild(nl);} else if ( "operandeDroit".equals(name) ) {return this.parseUniqueChild(nl);

} else if ( "operande".equals(name) ) {115 return this.parseUniqueChild(nl);

13

} else if ( "condition".equals(name) ) {return this.parseUniqueChild(nl);

} else if ( "consequence".equals(name) ) {return this.parseUniqueChild(nl);

120 } else if ( "alternant".equals(name) ) {return this.parseUniqueChild(nl);

} else if ( "valeur".equals(name) ) {return this.parseUniqueChild(nl);

125 // Une série d’éléments devant être analysée comme une séquence:} else if ( "corps".equals(name) ) {return new ASTsequence(this.parseList(nl));

} else {130 String msg = "Unknown element name: " + name;

throw new ASTException(msg);}

}

135 default: {String msg = "Unknown node type: " + n.getNodeName();throw new ASTException(msg);

}}

140 }

/** Analyser une séquence d’éléments pour en faire un ASTlist* c’est-à-dire une séquence d’AST.*/

145

protected List<AST> parseList (NodeList nl)throws ASTException {List<AST> result = new Vector<AST>();int n = nl.getLength();

150 LOOP:for ( int i = 0 ; i<n ; i++ ) {

Node nd = nl.item(i);switch ( nd.getNodeType() ) {

155 case Node.ELEMENT_NODE: {AST p = this.parse(nd);result.add(p);continue LOOP;

}160

default: {// On ignore tout ce qui n’est pas élément XML:

}}

165 }return result;

}

/** Trouver un élément d’après son nom et l’analyser pour en faire170 * un AST.

** @throws ASTException* lorsqu’un tel élément n’est pas trouvé.*/

175

protected AST findThenParseChild (NodeList nl, String childName)throws ASTException {int n = nl.getLength();for ( int i = 0 ; i<n ; i++ ) {

180 Node nd = nl.item(i);switch ( nd.getNodeType() ) {

case Node.ELEMENT_NODE: {Element e = (Element) nd;

185 if ( childName.equals(e.getTagName()) ) {return this.parse(e);

}break;

}190

default: {// On ignore tout ce qui n’est pas élément XML:

}}

14

Page 8:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

195 }String msg = "No such child element " + childName;throw new ASTException(msg);

}

200 /** Trouver un élément d’après son nom et analyser son contenu pour* en faire un ASTsequence.** @throws ASTException* lorsqu’un tel élément n’est pas trouvé.

205 */

protected ASTsequence findThenParseChildAsInstructions (NodeList nl, String childName)

throws ASTException {210 int n = nl.getLength();

for ( int i = 0 ; i<n ; i++ ) {Node nd = nl.item(i);switch ( nd.getNodeType() ) {

215 case Node.ELEMENT_NODE: {Element e = (Element) nd;if ( childName.equals(e.getTagName()) ) {return new ASTsequence(this.parseList(e.getChildNodes()));

}220 break;

}

default: {// On ignore tout ce qui n’est pas élément XML:

225 }}

}String msg = "No such child element " + childName;throw new ASTException(msg);

230 }

/** Analyser une suite comportant un unique élément.** @throws ASTException

235 * lorsque la suite ne contient pas exactement un seul élément.*/

protected AST parseUniqueChild (NodeList nl)throws ASTException {

240 AST result = null;int n = nl.getLength();for ( int i = 0 ; i<n ; i++ ) {

Node nd = nl.item(i);switch ( nd.getNodeType() ) {

245

case Node.ELEMENT_NODE: {Element e = (Element) nd;if ( result == null ) {

result = this.parse(e);250 } else {

String msg = "Non unique child";throw new ASTException(msg);

}break;

255 }

default: {// On ignore tout ce qui n’est pas élément XML:

}260 }

}if ( result == null ) {throw new ASTException("No child at all");

}265 return result;

}

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTParserTest.java

15

1 package fr.upmc.ilp.ilp1.fromxml;

import org.custommonkey.xmlunit.XMLTestCase;

import fr.upmc.ilp.ilp1.interfaces.IAST;6 import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;import fr.upmc.ilp.ilp1.interfaces.IASTboolean;import fr.upmc.ilp.ilp1.interfaces.IASTfloat;import fr.upmc.ilp.ilp1.interfaces.IASTinteger;import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;

11 import fr.upmc.ilp.ilp1.interfaces.IASTsequence;import fr.upmc.ilp.ilp1.interfaces.IASTstring;import fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock;import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;

16 /** Tests (JUnit) simples d’equivalence depuis XML -> AST -> XML. */

public class ASTParserTest extends XMLTestCase {

public void testEntier () throws ASTException {21 String program = "<entier valeur=’34’/>";

AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTentier);IASTinteger iast = (IASTinteger) a;

26 assertEquals(34, iast.getValue().intValue());}

public void testEntierNeg () throws ASTException {String program = "<entier valeur=’-34’/>";

31 AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTentier);IASTinteger iast = (IASTinteger) a;assertEquals(-34, iast.getValue().intValue());

36 }

public void testFlottant () throws ASTException {String program = "<flottant valeur=’3.14’/>";AST a = ASTfromXML.toAST(program);

41 assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTflottant);IASTfloat iast = (IASTfloat) a;assertEquals(3.14, iast.getValue().doubleValue(), 0.01);

}46

public void testFlottantExp () throws ASTException {String program = "<flottant valeur=’-3.14e+3’/>";AST a = ASTfromXML.toAST(program);//assertEquals(program, a.toXML()); // Pas la meme forme en sortie!

51 assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTflottant);IASTfloat iast = (IASTfloat) a;assertEquals(-3140, iast.getValue().doubleValue(), 0.01);

}

56 public void testBoolTrue () throws ASTException {String program = "<booleen valeur=’true’/>";AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTbooleen);

61 IASTboolean iast = (IASTboolean) a;assertEquals(true, iast.getValue());

}

public void testBoolFalse () throws ASTException {66 String program = "<booleen valeur=’false’/>";

AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTbooleen);IASTboolean iast = (IASTboolean) a;

71 assertEquals(false, iast.getValue());}

public void testChaine () throws ASTException {String program = "<chaine>foobar </chaine>";

76 AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTchaine);IASTstring iast = (IASTstring) a;assertEquals("foobar", iast.getValue());

16

Page 9:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

81 }

// {{{// Bogue signalée par Jacques Malenfant <[email protected]>:// les conditions et consequences étaient incapables de prendre

86 // plusieurs instructions! On en profite pour utiliser XMLUnit// signalé par Jérémy Bobbio <[email protected]>

public void testAlternativeTernaire () throws Exception {String program = "<alternative >"

91 + "<condition ><booleen valeur=’true’/></condition >"+ "<consequence ><entier valeur=’1’/></consequence >"+ "<alternant ><chaine>foobar </chaine ></alternant >"+ "</alternative >";

AST a = ASTfromXML.toAST(program);96 String result = a.toXML();

//System.err.println(result);//assertEquals(program, result);assertXpathExists("/alternative", result);assertXpathExists("/alternative/condition", result);

101 assertXpathExists("/alternative/condition/booleen", result);assertXpathExists("/alternative/consequence/sequence/entier", result);assertXpathValuesEqual("1",

"/alternative/consequence/sequence/entier/@valeur",result);

106 assertXpathExists("/alternative/alternant/sequence/chaine", result);assertXpathValuesEqual("foobar",

"/alternative/consequence/sequence/chaine",result);

assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTalternative);111 ASTalternative iast = (ASTalternative) a;

assertXMLEqual("<booleen valeur=’true’/>",((AST)iast.getCondition()).toXML());

assertXMLEqual("<sequence ><entier valeur=’1’/></sequence >",((AST)iast.getConsequent()).toXML());

116 assertXMLEqual("<sequence ><chaine>foobar </chaine></sequence >",((AST)iast.getAlternant()).toXML());

}

public void testAlternativeBinaire () throws Exception {121 String program = "<alternative >"

+ "<condition ><booleen valeur=’true’/></condition >"+ "<consequence ><entier valeur=’1’/></consequence >"+ "</alternative >";

AST a = ASTfromXML.toAST(program);126 String result = a.toXML();

//assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTalternative);ASTalternative iast = (ASTalternative) a;assertXMLEqual("<booleen valeur=’true’/>",

131 ((AST)iast.getCondition()).toXML());assertXMLEqual("<sequence ><entier valeur=’1’/></sequence >",

((AST)iast.getConsequent()).toXML());assertXpathExists("/alternative/consequence", result);assertXpathExists("/alternative/consequence/sequence", result);

136 assertXpathExists("/alternative/consequence/sequence/entier", result);assertXpathNotExists("/alternative/alternant", result);assertNull(iast.getAlternant());

}

141 public void testAlternativeWithConsequences () throws ASTException {String program = "<alternative >"

+ "<condition ><booleen valeur=’true’/></condition >"+ "<consequence ><entier valeur=’1’/><entier valeur=’11’/></consequence >"+ "</alternative >";

146 AST a = ASTfromXML.toAST(program);assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTalternative);IAST c = ((ASTalternative) a).getConsequent();assertTrue(c instanceof fr.upmc.ilp.ilp1.fromxml.ASTsequence);assertEquals(2, ((ASTsequence) c).getInstructions().length);

151 }

public void testAlternativeWithAlternants () throws Exception {String program = "<alternative >"

+ "<condition ><booleen valeur=’true’/></condition >"156 + "<consequence ><entier valeur=’1’/><entier valeur=’11’/></consequence >"

+ "<alternant ><chaine>foo</chaine><chaine>bar</chaine ></alternant >"+ "</alternative >";

AST a = ASTfromXML.toAST(program);assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTalternative);

161 IAST c = ((ASTalternative) a).getConsequent();17

assertTrue(c instanceof fr.upmc.ilp.ilp1.fromxml.ASTsequence);assertEquals(2, ((ASTsequence) c).getInstructions().length);String result = a.toXML();assertXpathExists("/alternative", result);

166 assertXpathExists("/alternative/consequence", result);assertXpathExists("/alternative/consequence/sequence", result);assertXpathExists("/alternative/consequence/sequence/entier[@valeur=’1’]",

result);assertXpathExists("/alternative/consequence/sequence/entier[@valeur=’11’]",

171 result);assertXpathExists("/alternative/alternant", result);assertXpathExists("/alternative/alternant/sequence", result);assertXpathEvaluatesTo("2",

"count(/alternative/alternant/sequence/chaine)",176 result);

}

// }}}

181 public void testSequence () throws Exception {String program = "<sequence>"

+ "<booleen valeur=’true’/>"+ "<entier valeur=’1’/>"+ "</sequence>";

186 AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTsequence);IASTsequence iast = (IASTsequence) a;IAST[] iastlist = iast.getInstructions();

191 assertNotNull(iastlist);assertTrue(iastlist.length == 2);IAST e1 = iastlist[0];assertXMLEqual("<booleen valeur=’true’/>", ((AST)e1).toXML());IAST e2 = iastlist[1];

196 assertXMLEqual("<entier valeur=’1’/>", ((AST)e2).toXML());}

public void testSequenceOne () throws Exception {String program = "<sequence>"

201 + "<entier valeur=’1’/>"+ "</sequence>";

AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTsequence);

206 IASTsequence iast = (IASTsequence) a;IAST[] iastlist = iast.getInstructions();assertNotNull(iastlist);assertTrue(iastlist.length == 1);IAST e1 = iastlist[0];

211 assertXMLEqual("<entier valeur=’1’/>", ((AST)e1).toXML());}

public void testSequenceEmpty () throws ASTException {String program = "<sequence>"

216 + "</sequence>";AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTsequence);IASTsequence iast = (IASTsequence) a;

221 IAST[] iastlist = iast.getInstructions();assertNotNull(iastlist);assertTrue(iastlist.length == 0);

}

226 public void testVariable () throws ASTException {String program = "<variable nom=’foo’/>";AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTvariable);

231 assertTrue(a instanceof fr.upmc.ilp.ilp1.interfaces.IASTvariable);ASTvariable var = (ASTvariable) a;assertEquals("foo", var.getName());

}

236 public void testBlocUnaire () throws Exception {String program = "<blocUnaire >"

+ "<variable nom=’foo’/>"+ "<valeur><entier valeur=’11’/></valeur>"+ "<corps><variable nom=’bar’/></corps>"

241 + "</blocUnaire >";AST a = ASTfromXML.toAST(program);

18

Page 10:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

//assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTblocUnaire);IASTunaryBlock iast = (ASTblocUnaire) a;

246 assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock);assertXMLEqual("<variable nom=’foo’/>",

((AST)iast.getVariable()).toXML());assertXMLEqual("<entier valeur=’11’/>",

((AST)iast.getInitialization()).toXML());251 //System.err.println(iast.getBody().toXML());

assertXMLEqual("<sequence ><variable nom=’bar’/></sequence >",((AST)iast.getBody()).toXML());

}

256 public void testInvocationPrimitive2 () throws Exception {String program = "<invocationPrimitive fonction=’xy’>"

+ "<variable nom=’foo’/>"+ "<entier valeur=’11’/>"+ "</invocationPrimitive >";

261 AST a = ASTfromXML.toAST(program);//assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTinvocationPrimitive);IASTinvocation iast = (ASTinvocation) a;assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTinvocation);

266 assertEquals(2, iast.getArgumentsLength());assertEquals("<variable nom=’xy’/>",

((AST)iast.getFunction()).toXML());IAST[] iastlist = iast.getArguments();assertTrue(iastlist.length == 2);

271 IAST e1 = iastlist[0];assertXMLEqual("<variable nom=’foo’/>", ((AST)e1).toXML());assertXMLEqual("<variable nom=’foo’/>",

((AST)iast.getArgument(0)).toXML());IAST e2 = iastlist[1];

276 assertXMLEqual("<entier valeur=’11’/>", ((AST)e2).toXML());assertXMLEqual("<entier valeur=’11’/>",

((AST)iast.getArgument(1)).toXML());}

281 public void testInvocationPrimitive1 () throws Exception {String program = "<invocationPrimitive fonction=’xy’>"

+ "<entier valeur=’11’/>"+ "</invocationPrimitive >";

AST a = ASTfromXML.toAST(program);286 //assertEquals(program, a.toXML());

assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTinvocationPrimitive);IASTinvocation iast = (ASTinvocation) a;assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTinvocation);assertEquals(1, iast.getArgumentsLength());

291 assertEquals("<variable nom=’xy’/>",((AST)iast.getFunction()).toXML());

IAST[] iastlist = iast.getArguments();assertTrue(iastlist.length == 1);IAST e1 = iastlist[0];

296 assertXMLEqual("<entier valeur=’11’/>", ((AST)e1).toXML());assertXMLEqual("<entier valeur=’11’/>",

((AST)iast.getArgument(0)).toXML());}

301 public void testInvocationPrimitive0 () throws Exception {String program = "<invocationPrimitive fonction=’xy’>"

+ "</invocationPrimitive >";AST a = ASTfromXML.toAST(program);//assertEquals(program, a.toXML());

306 assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASTinvocationPrimitive);IASTinvocation iast = (ASTinvocation) a;assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTinvocation);assertEquals(0, iast.getArgumentsLength());assertXMLEqual("<variable nom=’xy’/>",

311 ((AST)iast.getFunction()).toXML());IAST[] iastlist = iast.getArguments();assertTrue(iastlist.length == 0);

}

316 public void testOperationUnaire () throws Exception {String program = "<operationUnaire operateur=’-’>"

+ "<operande><entier valeur=’123’/></operande>"+ "</operationUnaire >";

AST a = ASTfromXML.toAST(program);321 assertEquals(program, a.toXML());

assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASToperationUnaire);

19

IASTunaryOperation iast = (IASTunaryOperation) a;assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation);//System.err.println(iast.getOperator().toXML());

326 assertEquals("-", iast.getOperatorName());assertEquals(1, iast.getArity());assertXMLEqual("<entier valeur=’123’/>",

((AST)iast.getOperand()).toXML());IAST[] iastlist = iast.getOperands();

331 assertTrue(iastlist.length == 1);IAST e1 = iastlist[0];assertXMLEqual("<entier valeur=’123’/>", ((AST)e1).toXML());

}

336 public void testOperationBinaire () throws Exception {String program = "<operationBinaire operateur=’+’>"

+ "<operandeGauche ><entier valeur=’123’/></operandeGauche >"+ "<operandeDroit ><entier valeur=’-34’/></operandeDroit >"+ "</operationBinaire >";

341 AST a = ASTfromXML.toAST(program);assertEquals(program, a.toXML());assertTrue(a instanceof fr.upmc.ilp.ilp1.fromxml.ASToperationBinaire);IASTbinaryOperation iast = (IASTbinaryOperation) a;assertTrue(iast instanceof fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation);

346 //System.err.println(iast.getOperator().toXML());assertEquals("+", iast.getOperatorName());assertEquals(2, iast.getArity());assertXMLEqual("<entier valeur=’123’/>",

((AST)iast.getLeftOperand()).toXML());351 assertXMLEqual("<entier valeur=’-34’/>",

((AST)iast.getRightOperand()).toXML());IAST[] iastlist = iast.getOperands();assertTrue(iastlist.length == 2);AST e1 = (AST) iastlist[0];

356 assertXMLEqual("<entier valeur=’123’/>", e1.toXML());AST e2 = (AST) iastlist[1];assertXMLEqual("<entier valeur=’-34’/>", e2.toXML());

}}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTalternative.java

package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.annotation.OrNull;import fr.upmc.ilp.ilp1.interfaces.IAST;

4 import fr.upmc.ilp.ilp1.interfaces.IASTalternative;

/** La représentation des alternatives (binaires ou ternaires). */

public class ASTalternative extends AST9 implements IASTalternative {

public ASTalternative (AST condition ,AST consequence ,AST alternant ) {

14 this.condition = condition;this.consequence = consequence;this.alternant = alternant;

}

19 // NOTA: Masquer l’implantation de l’alternative binaire afin// d’éviter la propagation de null.

public ASTalternative (AST condition , AST consequence) {this(condition , consequence , null);

24 }

private final AST condition;private final AST consequence;private final AST alternant;

29

public IAST getCondition () {return this.condition;

}

34 public IAST getConsequent () {return this.consequence;

}20

Page 11:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

public @OrNull IAST getAlternant () {39 return this.alternant;

}

/** Vérifie que l’alternative est ternaire c’est-à-dire qu’elle a unvéritable alternant. */

44

public boolean isTernary () {return alternant != null;

}

49 @Overridepublic String toXML () {

StringBuffer sb = new StringBuffer();sb.append("<alternative ><condition >");sb.append(condition.toXML());

54 sb.append("</condition ><consequence >");sb.append(consequence.toXML());sb.append("</consequence >");if ( isTernary() ) {

sb.append("<alternant >");59 sb.append(alternant.toXML());

sb.append("</alternant >");}sb.append("</alternative >");return sb.toString();

64 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTblocUnaire.java

package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.*;

3

/** Description d’un bloc local pourvu d’une seule variable locale, de* l’expression initialisant cette variable locale et d’un corps qui* est une séquence d’instructions.*/

8

public class ASTblocUnaire extends ASTimplements IASTunaryBlock {

public ASTblocUnaire (ASTvariable variable,13 AST initialization ,

ASTsequence body){this.variable = variable;this.initialization = initialization;

18 this.body = body;}

private final ASTvariable variable;private final AST initialization;

23 private final ASTsequence body;

public IASTvariable getVariable () {return this.variable;

}28 public IAST getInitialization () {

return this.initialization;}public IASTsequence getBody () {return this.body;

33 }

@Overridepublic String toXML () {

StringBuffer sb = new StringBuffer();38 sb.append("<blocUnaire >");

sb.append(variable.toXML());sb.append("<valeur>");sb.append(initialization.toXML());sb.append("</valeur><corps>");

43 sb.append(body.toXML());sb.append("</corps></blocUnaire >");

21

return sb.toString();}

48 }

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTbooleen.java

1 package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.*;

/** Une constante booleenne. */

6 public class ASTbooleen extends ASTimplements IASTboolean {

public ASTbooleen (String valeur) {this.valeur = "true".equals(valeur);

11 }private final boolean valeur;

public boolean getValue () {return valeur;

16 }

@Overridepublic String toXML () {return "<booleen valeur=’" + valeur + "’/>";

21 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTchaine.java

1 package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.*;

/** Une constante chaine de caracteres. */

6 public class ASTchaine extends ASTimplements IASTstring {

public ASTchaine (String valeur) {this.valeur = valeur;

11 }private final String valeur;

public String getValue () {return valeur;

16 }

@Overridepublic String toXML () {return "<chaine>" + valeur + "</chaine>";

21 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTentier.java

1 package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.*;

import java.math.BigInteger;

6 /** Une constante entière. */

public class ASTentier extends ASTimplements IASTinteger {

11 public ASTentier (String valeur) {this.valeur = Integer.parseInt(valeur);this.bigint = new BigInteger(valeur);

}22

Page 12:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

private final int valeur;16 private final BigInteger bigint;

public BigInteger getValue () {return bigint;

}21

@Overridepublic String toXML () {return "<entier valeur=’" + valeur + "’/>";

}26

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTflottant.java

package fr.upmc.ilp.ilp1.fromxml;2 import fr.upmc.ilp.ilp1.interfaces.*;

import java.math.BigDecimal;

/** Une constante flottante. */7

public class ASTflottant extends ASTimplements IASTfloat {

public ASTflottant (String valeur) {12 this.valeur = Double.parseDouble(valeur);

this.bigfloat = new BigDecimal(valeur);}private final double valeur;private final BigDecimal bigfloat;

17

public BigDecimal getValue () {return bigfloat;

}

22 @Overridepublic String toXML () {return "<flottant valeur=’" + valeur + "’/>";

}

27 }

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTfromXML.java

package fr.upmc.ilp.ilp1.fromxml;2

import java.io.StringReader;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;

7 import org.xml.sax.InputSource;

import fr.upmc.ilp.ilp1.interfaces.IAST;

/** Utilitaires pour convertir un fragment d’XML en un AST. Ces12 * utilitaires sont utiles pour les tests avec JUnit (voir

* ASTParserTest.java par exemple).*/

public class ASTfromXML {17

/** Convertir un fragment d’XML en AST. */

public static AST toAST (String xml)throws ASTException {

22 try {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(xml);InputSource is = new InputSource(sr);

27 Document d = db.parse(is);ASTParser ap = new ASTParser();AST ast = ap.parse(d);

23

return ast;} catch (ASTException exc) {

32 throw exc;} catch (Throwable cause) {throw new ASTException(cause);

}}

37

/** Convertir un fragment d’XML en un IAST. */

public static IAST toIAST (String xml)throws ASTException {

42 return ASTfromXML.toAST(xml);}

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocation.java

package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;

/** Une invocation mentionne une fonction et des arguments. */5

public class ASTinvocation extends ASTimplements IASTinvocation {

public ASTinvocation (AST fonction , AST[] arguments) {10 this.fonction = fonction;

this.argument = arguments;}private final AST fonction;private final AST[] argument;

15

public AST getFunction () {return this.fonction;

}

20 public AST[] getArguments () {return this.argument;

}

public int getArgumentsLength () {25 return this.argument.length;

}

public AST getArgument (int i) {return this.argument[i];

30 }

@Overridepublic String toXML () {

StringBuffer sb = new StringBuffer();35 sb.append("<invocation ><function >");

sb.append(fonction.toXML());sb.append("</function >");//sb.append("<arguments >");for ( AST arg : this.argument ) {

40 sb.append(arg.toXML());}// sb.append("</arguments >");sb.append("</invocation >");return sb.toString();

45 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTinvocationPrimitive.java

package fr.upmc.ilp.ilp1.fromxml;2

/** Le cas particulier , parmi les invocations de fonctions ,* des primitives.*/

24

Page 13:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

7 public class ASTinvocationPrimitiveextends ASTinvocation {

public ASTinvocationPrimitive (String fonction , AST[] arguments) {super(new ASTvariable(fonction), arguments);

12 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperation.java

package fr.upmc.ilp.ilp1.fromxml;

/** La classe abstraite des opérations.

5 * Il y en a deux sortes: les unaires et les binaires.*/

public abstract class ASToperation extends AST{

10 protected ASToperation (String operateur , int arity) {this.operateur = operateur;this.arity = arity;

}private final String operateur;

15 private final int arity;

public String getOperatorName () {return this.operateur;

}20

public int getArity () {return this.arity;

}

25 }

Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationBinaire.java

package fr.upmc.ilp.ilp1.fromxml;

import java.util.List;4 import java.util.Vector;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;

9 /** Opérations binaires. */

public class ASToperationBinaire extends ASToperationimplements IASTbinaryOperation {

14 public ASToperationBinaire(String operateur , AST operandeGauche ,AST operandeDroit) {

super(operateur , 2);this.operandeGauche = operandeGauche;this.operandeDroit = operandeDroit;

19 }private final AST operandeGauche;private final AST operandeDroit;

public IAST getLeftOperand() {24 return this.operandeGauche;

}

public IAST getRightOperand() {return this.operandeDroit;

29 }

public IAST[] getOperands() {// On calcule paresseusement car ce n’est pas une méthode usuelle:if (operands == null) {

34 List<AST> loperands = new Vector<AST>();25

loperands.add(operandeGauche);loperands.add(operandeDroit);operands = loperands.toArray(new AST[0]);

}39 return operands;

}

// NOTA: remarquer que ce mode paresseux interdit de qualifier ce// champ de « final » ce qui n’est pas sûr!

44 private IAST[] operands;

@Overridepublic String toXML() {

StringBuffer sb = new StringBuffer();49 // Comme signalé par [email protected], il faudrait coder

// getOperatorName() pour utiliser les entités &lt; &gt; etc.sb.append("<operationBinaire operateur=’" + getOperatorName() + "’>");sb.append("<operandeGauche >");sb.append(operandeGauche.toXML());

54 sb.append("</operandeGauche ><operandeDroit >");sb.append(operandeDroit.toXML());sb.append("</operandeDroit ></operationBinaire >");return sb.toString();

}59

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASToperationUnaire.java

package fr.upmc.ilp.ilp1.fromxml;

import java.util.List;4 import java.util.Vector;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;

9 /** Opérations unaires. */

public class ASToperationUnaire extends ASToperationimplements IASTunaryOperation {

14 public ASToperationUnaire(String operateur , AST operand) {super(operateur , 1);this.operand = operand;

}private final AST operand;

19

public IAST getOperand() {return this.operand;

}

24 public IAST[] getOperands() {// On calcule paresseusement car ce n’est pas une méthode usuelle:if (operands == null) {

List<AST> loperands = new Vector<AST>();loperands.add(operand);

29 operands = loperands.toArray(new AST[0]);}return operands;

}private AST[] operands = null;

34

@Overridepublic String toXML() {

StringBuffer sb = new StringBuffer();sb.append("<operationUnaire operateur=’" + getOperatorName() + "’>");

39 sb.append("<operande >");sb.append(operand.toXML());sb.append("</operande ></operationUnaire >");return sb.toString();

}44

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTsequence.java

26

Page 14:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

package fr.upmc.ilp.ilp1.fromxml;

import java.util.List;4

import fr.upmc.ilp.annotation.OrNull;import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;

9 public class ASTsequence extends ASTimplements IASTsequence {

public ASTsequence(List<AST> instructions) {this.instructions = instructions;

14 }private final List<AST> instructions;

public IAST[] getInstructions() {return this.instructions.toArray(new IAST[0]);

19 }

// NOTA: si i est hors limite, cette methode ne ramene pas null comme le// dit l’interface mais signale une exception IndexOutOfRange.public @OrNull IAST getInstruction(int i) {

24 return this.instructions.get(i);}

public int getInstructionsLength() {return this.instructions.size();

29 }

@Overridepublic String toXML() {

StringBuffer sb = new StringBuffer("<sequence>");34 for (AST instruction : this.instructions) {

sb.append(instruction.toXML());}sb.append("</sequence >");return sb.toString();

39 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/ASTvariable.java

package fr.upmc.ilp.ilp1.fromxml;import fr.upmc.ilp.ilp1.interfaces.*;

3

/** Description d’une variable. */

public class ASTvariableextends AST

8 implements IASTvariable {

public ASTvariable (String name) {this.name = name;

}13 private final String name;

public String getName () {return name;

}18

@Overridepublic String toXML () {return "<variable nom=’" + name + "’/>";

}23

}

Java/src/fr/upmc/ilp/ilp1/fromxml/Main.java

package fr.upmc.ilp.ilp1.fromxml;import java.io.*;import javax.xml.parsers.*;import org.w3c.dom.*;

27

5 import org.xml.sax.*;import com.thaiopensource.validate.*;

/** Lit puis évalue un programme. Le langage utilisé est ILP1 défini* par grammar1.rnc

10 ** Usage: java fr.upmc.ilp.fromxml.Main grammaire.rng programme.xml*/

public class Main {15

public static void main (String[] argument)throws ASTException {Main m = new Main(argument);m.run();

20 }

protected Main (String[] argument)throws ASTException {if ( argument.length < 2 ) {

25 throw new ASTException("Usage: Main grammaire.rng programme.xml");}this.rngfile = new File(argument[0]);this.xmlfile = new File(argument[1]);if ( !this.rngfile.exists() ) {

30 throw new ASTException("Fichier .rng introuvable.");}if ( !this.xmlfile.exists() ) {throw new ASTException("Fichier .xml introuvable.");

}35 }

private File rngfile;private File xmlfile;

40 protected void run ()throws ASTException {

try {

45 // (1) validation vis-à-vis de RNG:// MOCHE: c’est redondant avec (2) car le programme est relu encore une// fois avec SAX. Les phases 1 et 2 pourraient s’effectuer ensemble.ValidationDriver vd = new ValidationDriver();InputSource isg = ValidationDriver.fileInputSource(

50 rngfile.getAbsolutePath());vd.loadSchema(isg);InputSource isp = ValidationDriver.fileInputSource(

this.xmlfile.getAbsolutePath());if ( ! vd.validate(isp) ) {

55 throw new ASTException("programme XML non valide");}

// (2) convertir le fichier XML en DOM:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

60 DocumentBuilder db = dbf.newDocumentBuilder();Document d = db.parse(this.xmlfile);

// (3) conversion vers un AST donc un IAST:ASTParser ap = new ASTParser();

65 AST ast = ap.parse(d);

// (3bis) Impression en XML:System.out.println(ast.toXML());

70 } catch (ASTException e) {throw e;

} catch (Throwable cause) {throw new ASTException(cause);

}75 }

}

Java/src/fr/upmc/ilp/ilp1/fromxml/MainTest.java

package fr.upmc.ilp.ilp1.fromxml;28

Page 15:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

2

import java.io.File;

import junit.framework.TestCase;

7 /** Tests (JUnit3) simples d’equivalence depuis fichier XML -> AST ->* XML. Tests a completer (notamment pour verifier que l’XML engendre* est valide.*/

12 public class MainTest extends TestCase {

public void processFile (String grammarName , String fileName)throws ASTException {

Main m = new Main(new String[] {17 grammarName ,

fileName});m.run();

}22

public void testP1 () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p1-1.xml");}

27

public void testP2 () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p2-1.xml");}

32

public void testP2un () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p2un-1.xml");}

37

public void testP3if () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p3if-1.xml");}

42

public void testP3if2 () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p3if2 -1.xml");}

47

public void testP4seq () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p4seq -1.xml");}

52

public void testP5let1 () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p5let1 -1.xml");}

57

public void testP6letvar () throws ASTException {processFile("Grammars" + File.separator + "grammar1.rng",

"Grammars" + File.separator + "Samples" + File.separator + "p6letvar -1.xml");}

62

// et tous les programmes u*-1.xml

}

Java/src/fr/upmc/ilp/ilp1/fromxml/MainTestSuite.java

package fr.upmc.ilp.ilp1.fromxml;

import junit.framework.Test;4 import junit.framework.TestSuite;

/** Regroupement de classes de tests pour le paquetage fromxml. */

public class MainTestSuite extends TestSuite {9

public static Test suite() {TestSuite suite = new TestSuite();

29

suite.addTest(new TestSuite(ASTParserTest.class));suite.addTest(new TestSuite(MainTest.class));

14 return suite;}

}

Java/src/fr/upmc/ilp/ilp1/runtime/AbstractInvokableImpl.java

package fr.upmc.ilp.ilp1.runtime;2

/** Une classe abstraite de fonction qui peut servir de base à des* implantations particulières. Il suffit, si la fonction a moins de* quatre arguments , de définir la méthode invoke appropriée.* @see fr.upmc.ilp.ilp1.runtime.PrintStuff

7 */

public abstract class AbstractInvokableImplimplements Invokable {

12 private static final String WRONG_ARITY ="Wrong arity";

/** Une fonction invoquée avec un nombre quelconque d’arguments. Les* petites arités sont renvoyées sur les méthodes appropriées. */

17

public Object invoke (final Object[] arguments)throws EvaluationException {switch (arguments.length) {case 0: return this.invoke();

22 case 1: return this.invoke(arguments[0]);case 2: return this.invoke(arguments[0], arguments[1]);case 3: return this.invoke(arguments[0], arguments[1], arguments[2]);default: throw new EvaluationException(WRONG_ARITY);}

27 }

/** Invocation d’une fonction zéro-aire (ou niladique) */

public Object invoke ()32 throws EvaluationException {

throw new EvaluationException(WRONG_ARITY);}

/** Invocation d’une fonction unaire (ou monadique) */37

public Object invoke (final Object argument1)throws EvaluationException {throw new EvaluationException(WRONG_ARITY);

}42

/** Invocation d’une fonction binaire (ou dyadique) */

public Object invoke (final Object argument1 ,final Object argument2)

47 throws EvaluationException {throw new EvaluationException(WRONG_ARITY);

}

/** Invocation d’une fonction ternaire */52

public Object invoke (final Object argument1 ,final Object argument2 ,final Object argument3)

throws EvaluationException {57 throw new EvaluationException(WRONG_ARITY);

}

}

Java/src/fr/upmc/ilp/ilp1/runtime/Common.java

package fr.upmc.ilp.ilp1.runtime;import java.math.BigInteger;

30

Page 16:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

4 /** Cette interface définit les caractéristiques globales d’un* interprète du langage ILP1. On y trouve, notamment , la définition* des opérateurs du langage.*/

9 public class Common implements ICommon {

public Common () {}

/** Les opérateurs unaires.14 *

* Comme il n’y a que deux tels opérateurs , leur définition est* intégrée dans cette méthode. */

public Object applyOperator (String opName, Object operand)19 throws EvaluationException {

checkNotNull(opName, 1, operand);

if ( "-".equals(opName) ) {if ( operand instanceof BigInteger ) {

24 BigInteger bi = (BigInteger) operand;return bi.negate();

} else if ( operand instanceof Double ) {double bd = ((Double) operand).doubleValue();return new Double(-bd);

29 } else {return signalWrongType(opName, 1, operand, "number");

}

} else if ( "!".equals(opName) ) {34 if ( operand instanceof Boolean ) {

Boolean b = (Boolean) operand;return Boolean.valueOf( ! b.booleanValue() );

} else {return signalWrongType(opName, 1, operand, "boolean");

39 }

} else {String msg = "Unknown unary operator: " + opName;throw new EvaluationException(msg);

44 }}

/** Les opérateurs binaires.*

49 * Cette méthode n’est qu’un grand aiguillage. */

public Object applyOperator (String opName,Object leftOperand ,Object rightOperand)

54 throws EvaluationException{if ( "+".equals(opName) ) {return operatorPlus(opName, leftOperand , rightOperand);

} else if ( "-".equals(opName) ) {59 return operatorMinus(opName, leftOperand , rightOperand);

// continuer TEMP

} else {64 String msg = "Unknown binary operator: " + opName;

throw new EvaluationException(msg);}

}

69 // Vérifications diverses:

private void checkNotNull (String opName, int rank, Object o)throws EvaluationException {if ( o == null ) {

74 String msg = opName + ": Argument " + rank + " is null!\n"+ "Value is: " + o;

throw new EvaluationException(msg);}

}79

private Object signalWrongType (String opName, int rank, Object o,String expectedType)

31

throws EvaluationException {String msg = opName + ": Argument " + rank + " is not "

84 + expectedType + "\n" + "Value is: " + o;throw new EvaluationException(msg);

}

// {{{ Les opérateurs binaires:89

/** Le traitement de l’addition. C’est compliqué car il y a de* nombreuses conversions possibles. */

private Object operatorPlus (String opName, Object a, Object b)94 throws EvaluationException {

checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

BigInteger bi1 = (BigInteger) a;99 if ( b instanceof BigInteger ) {

BigInteger bi2 = (BigInteger) b;return bi1.add(bi2);

} else if ( b instanceof Double ) {double bd1 = bi1.doubleValue();

104 double bd2 = ((Double) b).doubleValue();return new Double(bd1 + bd2);

} else {return signalWrongType(opName, 2, b, "number");

}109 } else if ( a instanceof Double ) {

Double bd1 = (Double) a;if ( b instanceof Double ) {

Double bd2 = (Double) b;return new Double(bd1.doubleValue() + bd2.doubleValue());

114 } else if ( b instanceof BigInteger ) {BigInteger bi2 = (BigInteger) b;double bd2 = bi2.doubleValue();return new Double(bd1.doubleValue() + bd2);

} else {119 return signalWrongType(opName, 2, b, "number");

}} else {return signalWrongType(opName, 1, a, "number");

}124 }

/** Le traitement de la soustraction. Ca ressemble à l’addition. */

private Object operatorMinus (String opName, Object a, Object b)129 throws EvaluationException {

checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

BigInteger bi1 = (BigInteger) a;134 if ( b instanceof BigInteger ) {

BigInteger bi2 = (BigInteger) b;return bi1.subtract(bi2);

} else if ( b instanceof Double ) {double bd1 = bi1.doubleValue();

139 double bd2 = ((Double) b).doubleValue();return new Double(bd1 - bd2);

} else {return signalWrongType(opName, 2, b, "number");

}144 } else if ( a instanceof Double ) {

Double bd1 = (Double) a;if ( b instanceof Double ) {

Double bd2 = (Double) b;return new Double(bd1.doubleValue() - bd2.doubleValue());

149 } else if ( b instanceof BigInteger ) {BigInteger bi2 = (BigInteger) b;double bd2 = bi2.doubleValue();return new Double(bd1.doubleValue() - bd2);

} else {154 return signalWrongType(opName, 2, b, "number");

}} else {return signalWrongType(opName, 1, a, "number");

}159 }

32

Page 17:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

// }}}

}

Java/src/fr/upmc/ilp/ilp1/runtime/CommonPlus.java

1 //// ATTENTION: NE PAS MODIFIER! CETTE CLASSE A ÉTÉ ENGENDRÉE AUTOMATIQUEMENT// A PARTIR DE BinOp.php (voir build.xml pour les détails).

/* ******************************************************************6 * ILP -- Implantation d’un langage de programmation.

* Copyright (C) 2004-2005 <[email protected]>* $Id: CommonPlus.java 930 2010-08-21 07:55:05Z queinnec $* GPL version >=2* ******************************************************************/

11

package fr.upmc.ilp.ilp1.runtime;

import java.math.BigInteger;

16 /** Cette classe (engendrée par PHP) implante les caractéristiques* générales d’un interprète du langage ILP1. On y trouve, notamment ,* la définition des opérateurs du langage.*/

21 public class CommonPlus implements ICommon {

public CommonPlus () {}

// Vérifications diverses:26

private void checkNotNull (final String opName,final int rank,final Object o)

throws EvaluationException {31 if ( o == null ) {

final String msg = opName + ": Argument " + rank + " is null!\n"+ "Value is: " + o;

throw new EvaluationException(msg);}

36 }

private Object signalWrongType (final String opName,final int rank,final Object o,

41 final String expectedType)throws EvaluationException {final String msg = opName + ": Argument " + rank + " is not "

+ expectedType + "\n" + "Value is: " + o;throw new EvaluationException(msg);

46 }

/** Les opérateurs unaires.** Comme il n’y a que deux tels opérateurs , leur définition est

51 * intégrée directement dans cette méthode plutôt que d’être* macro-générée. */

public Object applyOperator (final String opName, final Object operand)throws EvaluationException {

56 checkNotNull(opName, 1, operand);

if ( "-".equals(opName) ) {if ( operand instanceof BigInteger ) {

final BigInteger bi = (BigInteger) operand;61 return bi.negate();

} else if ( operand instanceof Double ) {// Profitons du déballage (unboxing) automatique:// final double bd = ((Double) operand).doubleValue();final double bd = (Double) operand;

66 return new Double(-bd);} else {

return signalWrongType(opName, 1, operand, "number");}

33

71 } else if ( "!".equals(opName) ) {if ( operand instanceof Boolean ) {

final Boolean b = (Boolean) operand;return Boolean.valueOf( ! b.booleanValue() );

} else {76 return signalWrongType(opName, 1, operand, "boolean");

}

} else {final String msg = "Unknown unary operator: " + opName;

81 throw new EvaluationException(msg);}

}

/** Les opérateurs binaires.86 *

* Cette méthode n’est qu’un grand aiguillage. */

public Object applyOperator (final String opName,final Object leftOperand ,

91 final Object rightOperand)throws EvaluationException{

// Les opérateurs:

96 if ( "+".equals(opName) ) {return operatorPlus(opName, leftOperand , rightOperand);

} elseif ( "-".equals(opName) ) {

return operatorMinus(opName, leftOperand , rightOperand);101 } else

if ( "*".equals(opName) ) {return operatorMultiply(opName, leftOperand , rightOperand);

} elseif ( "/".equals(opName) ) {

106 return operatorQuotient(opName, leftOperand , rightOperand);} elseif ( "%".equals(opName) ) {

return operatorModulo(opName, leftOperand , rightOperand);} else

111

// Les comparateurs:

if ( "<".equals(opName) ) {return operatorLT(opName, leftOperand , rightOperand);

116 } elseif ( "<=".equals(opName) ) {

return operatorLE(opName, leftOperand , rightOperand);} elseif ( "==".equals(opName) ) {

121 return operatorEQ(opName, leftOperand , rightOperand);} elseif ( ">=".equals(opName) ) {

return operatorGE(opName, leftOperand , rightOperand);} else

126 if ( ">".equals(opName) ) {return operatorGT(opName, leftOperand , rightOperand);

} elseif ( "!=".equals(opName) ) {

return operatorNEQ(opName, leftOperand , rightOperand);131 } else

// L’operateur != est aussi connu sous l’alias <>// Cet oubli a été signalé par [email protected]:if ( "<>".equals(opName) ) {

return operatorNEQ(opName, leftOperand , rightOperand);136 } else

// Les opérateurs booléens:if ( "&".equals(opName) ) {

if ( leftOperand == Boolean.FALSE ) {141 return Boolean.FALSE;

} else {return rightOperand;

}} else

146 if ( "|".equals(opName) ) {if ( leftOperand != Boolean.FALSE ) {

return leftOperand;} else {

34

Page 18:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

return rightOperand;151 }

} elseif ( "^".equals(opName) ) {

boolean left = (leftOperand != Boolean.FALSE);boolean right = (rightOperand != Boolean.FALSE);

156 return (Boolean) (left != right);} else

// NOTA: il serait plus astucieux de ranger les branches de// ces alternatives par ordre d’usage décroissant!

161 {final String msg = "Unknown binary operator: " + opName;throw new EvaluationException(msg);

}}

166

// Le cas de l’opérateur binaire + est plus compliqué car il permet// aussi la concaténation de chaînes de caractères. Il sera donc// traité à part et donc écrit à la main. C’est tout comme pour// modulo qui ne s’applique qu’à des entiers et non à des flottants.

171 // Tous les autres opérateurs binaires seront macro-générés.

/** Définition de l’opérateur binaire + */

private Object operatorPlus (final String opName,176 final Object a,

final Object b)throws EvaluationException {checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);

181 if ( a instanceof BigInteger ) {final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return bi1.add(bi2);

186 } else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return new Double(bd1 + bd2);

191 } else {return signalWrongType(opName, 2, b, "number");

}} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;196 if ( b instanceof Double ) {

final Double bd2 = (Double) b;//return new Double(bd1.doubleValue() + bd2.doubleValue());return new Double(bd1 + bd2);

} else if ( b instanceof BigInteger ) {201 final BigInteger bi2 = (BigInteger) b;

final double bd2 = bi2.doubleValue();return new Double(bd1.doubleValue() + bd2);

} else {return signalWrongType(opName, 2, b, "number");

206 }} else if ( a instanceof String ) {

final String sa = (String) a;if ( b instanceof String ) {

final String sb = (String) b;211 return sa + sb;

} else {return signalWrongType(opName, 2, b, "string");

}} else {

216 return signalWrongType(opName, 1, a, "number");}

}

/** Définition de l’opérateur binaire modulo % */221

private Object operatorModulo (final String opName,final Object a,final Object b)

throws EvaluationException {226 checkNotNull(opName, 1, a);

checkNotNull(opName, 2, b);

35

if ( a instanceof BigInteger ) {final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

231 final BigInteger bi2 = (BigInteger) b;return bi1.mod(bi2);

} else {return signalWrongType(opName, 2, b, "integer");

}236 } else {

return signalWrongType(opName, 1, a, "integer");}

}

241 // Les opérateurs binaires (engendrés par PHP)

/** Définition de l’opérateur binaire - à l’aide de BigInteger.subtract.*/

246 private Object operatorMinus (final String opName, final Object a, final Object b)throws EvaluationException {

checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

251 final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return bi1.subtract(bi2);

} else if ( b instanceof Double ) {256 final double bd1 = bi1.doubleValue();

//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return new Double(bd1 - bd2);

} else {261 return signalWrongType(opName, 2, b, "number");

}} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;if ( b instanceof Double ) {

266 final Double bd2 = (Double) b;//return new Double(bd1.doubleValue() - bd2.doubleValue());return new Double(bd1 - bd2);

} else if ( b instanceof BigInteger ) {final BigInteger bi2 = (BigInteger) b;

271 final double bd2 = bi2.doubleValue();//return new Double(bd1.doubleValue() - bd2);return new Double(bd1 - bd2);

} else {return signalWrongType(opName, 2, b, "number");

276 }} else {

return signalWrongType(opName, 1, a, "number");}

}281

/** Définition de l’opérateur binaire * à l’aide de BigInteger.multiply.*/

private Object operatorMultiply (final String opName, final Object a, final Object b)throws EvaluationException {

286 checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

291 final BigInteger bi2 = (BigInteger) b;return bi1.multiply(bi2);

} else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();

296 final double bd2 = (Double) b;return new Double(bd1 * bd2);

} else {return signalWrongType(opName, 2, b, "number");

}301 } else if ( a instanceof Double ) {

final Double bd1 = (Double) a;if ( b instanceof Double ) {

36

Page 19:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

final Double bd2 = (Double) b;//return new Double(bd1.doubleValue() * bd2.doubleValue());

306 return new Double(bd1 * bd2);} else if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;final double bd2 = bi2.doubleValue();//return new Double(bd1.doubleValue() * bd2);

311 return new Double(bd1 * bd2);} else {

return signalWrongType(opName, 2, b, "number");}

} else {316 return signalWrongType(opName, 1, a, "number");

}}

/** Définition de l’opérateur binaire / à l’aide de BigInteger.divide.*/

321

private Object operatorQuotient (final String opName, final Object a, final Object b)throws EvaluationException {

checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);

326 if ( a instanceof BigInteger ) {final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return bi1.divide(bi2);

331 } else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return new Double(bd1 / bd2);

336 } else {return signalWrongType(opName, 2, b, "number");

}} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;341 if ( b instanceof Double ) {

final Double bd2 = (Double) b;//return new Double(bd1.doubleValue() / bd2.doubleValue());return new Double(bd1 / bd2);

} else if ( b instanceof BigInteger ) {346 final BigInteger bi2 = (BigInteger) b;

final double bd2 = bi2.doubleValue();//return new Double(bd1.doubleValue() / bd2);return new Double(bd1 / bd2);

} else {351 return signalWrongType(opName, 2, b, "number");

}} else {

return signalWrongType(opName, 1, a, "number");}

356 }

// Les comparateurs binaires (engendrés par PHP)

361 /** Définition de l’opérateur binaire LT à l’aide de BigInteger.compareTo().*/

private Object operatorLT (final String opName, final Object a, final Object b)throws EvaluationException {checkNotNull(opName, 1, a);

366 checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;371 return Boolean.valueOf(bi1.compareTo(bi2) < 0);

} else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;

376 return Boolean.valueOf(bd1 < bd2);} else {

return signalWrongType(opName, 2, b, "number");}

37

} else if ( a instanceof Double ) {381 final Double bd1 = (Double) a;

if ( b instanceof Double ) {final Double bd2 = (Double) b;//return Boolean.valueOf(bd1.doubleValue() < bd2.doubleValue());return Boolean.valueOf(bd1 < bd2);

386 } else if ( b instanceof BigInteger ) {final BigInteger bi2 = (BigInteger) b;final double bd2 = bi2.doubleValue();return Boolean.valueOf(bd1.doubleValue() < bd2);

} else {391 return signalWrongType(opName, 2, b, "number");

}} else {

return signalWrongType(opName, 1, a, "number");}

396 }

/** Définition de l’opérateur binaire LE à l’aide de BigInteger.compareTo().*/

private Object operatorLE (final String opName, final Object a, final Object b)401 throws EvaluationException {

checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

final BigInteger bi1 = (BigInteger) a;406 if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return Boolean.valueOf(bi1.compareTo(bi2) <= 0);

} else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();

411 //final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return Boolean.valueOf(bd1 <= bd2);

} else {return signalWrongType(opName, 2, b, "number");

416 }} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;if ( b instanceof Double ) {

final Double bd2 = (Double) b;421 //return Boolean.valueOf(bd1.doubleValue() <= bd2.doubleValue());

return Boolean.valueOf(bd1 <= bd2);} else if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;final double bd2 = bi2.doubleValue();

426 return Boolean.valueOf(bd1.doubleValue() <= bd2);} else {

return signalWrongType(opName, 2, b, "number");}

} else {431 return signalWrongType(opName, 1, a, "number");

}}

/** Définition de l’opérateur binaire EQ à l’aide de BigInteger.compareTo().*/

436

private Object operatorEQ (final String opName, final Object a, final Object b)throws EvaluationException {checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);

441 if ( a instanceof BigInteger ) {final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return Boolean.valueOf(bi1.compareTo(bi2) == 0);

446 } else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return Boolean.valueOf(bd1 == bd2);

451 } else {return signalWrongType(opName, 2, b, "number");

}} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;38

Page 20:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

456 if ( b instanceof Double ) {final Double bd2 = (Double) b;//return Boolean.valueOf(bd1.doubleValue() == bd2.doubleValue());return Boolean.valueOf(bd1 == bd2);

} else if ( b instanceof BigInteger ) {461 final BigInteger bi2 = (BigInteger) b;

final double bd2 = bi2.doubleValue();return Boolean.valueOf(bd1.doubleValue() == bd2);

} else {return signalWrongType(opName, 2, b, "number");

466 }} else {

return signalWrongType(opName, 1, a, "number");}

}471

/** Définition de l’opérateur binaire GE à l’aide de BigInteger.compareTo().*/

private Object operatorGE (final String opName, final Object a, final Object b)throws EvaluationException {

476 checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

481 final BigInteger bi2 = (BigInteger) b;return Boolean.valueOf(bi1.compareTo(bi2) >= 0);

} else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();

486 final double bd2 = (Double) b;return Boolean.valueOf(bd1 >= bd2);

} else {return signalWrongType(opName, 2, b, "number");

}491 } else if ( a instanceof Double ) {

final Double bd1 = (Double) a;if ( b instanceof Double ) {

final Double bd2 = (Double) b;//return Boolean.valueOf(bd1.doubleValue() >= bd2.doubleValue());

496 return Boolean.valueOf(bd1 >= bd2);} else if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;final double bd2 = bi2.doubleValue();return Boolean.valueOf(bd1.doubleValue() >= bd2);

501 } else {return signalWrongType(opName, 2, b, "number");

}} else {

return signalWrongType(opName, 1, a, "number");506 }

}

/** Définition de l’opérateur binaire GT à l’aide de BigInteger.compareTo().*/

511 private Object operatorGT (final String opName, final Object a, final Object b)throws EvaluationException {checkNotNull(opName, 1, a);checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

516 final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;return Boolean.valueOf(bi1.compareTo(bi2) > 0);

} else if ( b instanceof Double ) {521 final double bd1 = bi1.doubleValue();

//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;return Boolean.valueOf(bd1 > bd2);

} else {526 return signalWrongType(opName, 2, b, "number");

}} else if ( a instanceof Double ) {

final Double bd1 = (Double) a;if ( b instanceof Double ) {

531 final Double bd2 = (Double) b;39

//return Boolean.valueOf(bd1.doubleValue() > bd2.doubleValue());return Boolean.valueOf(bd1 > bd2);

} else if ( b instanceof BigInteger ) {final BigInteger bi2 = (BigInteger) b;

536 final double bd2 = bi2.doubleValue();return Boolean.valueOf(bd1.doubleValue() > bd2);

} else {return signalWrongType(opName, 2, b, "number");

}541 } else {

return signalWrongType(opName, 1, a, "number");}

}

546 /** Définition de l’opérateur binaire NEQ à l’aide de BigInteger.compareTo().*/

private Object operatorNEQ (final String opName, final Object a, final Object b)throws EvaluationException {checkNotNull(opName, 1, a);

551 checkNotNull(opName, 2, b);if ( a instanceof BigInteger ) {

final BigInteger bi1 = (BigInteger) a;if ( b instanceof BigInteger ) {

final BigInteger bi2 = (BigInteger) b;556 return Boolean.valueOf(bi1.compareTo(bi2) != 0);

} else if ( b instanceof Double ) {final double bd1 = bi1.doubleValue();//final double bd2 = ((Double) b).doubleValue();final double bd2 = (Double) b;

561 return Boolean.valueOf(bd1 != bd2);} else {

return signalWrongType(opName, 2, b, "number");}

} else if ( a instanceof Double ) {566 final Double bd1 = (Double) a;

if ( b instanceof Double ) {final Double bd2 = (Double) b;//return Boolean.valueOf(bd1.doubleValue() != bd2.doubleValue());return Boolean.valueOf(bd1 != bd2);

571 } else if ( b instanceof BigInteger ) {final BigInteger bi2 = (BigInteger) b;final double bd2 = bi2.doubleValue();return Boolean.valueOf(bd1.doubleValue() != bd2);

} else {576 return signalWrongType(opName, 2, b, "number");

}} else {

return signalWrongType(opName, 1, a, "number");}

581 }

}

// fin de génération de CommonPlus.java

Java/src/fr/upmc/ilp/ilp1/runtime/ConstantsStuff.java

package fr.upmc.ilp.ilp1.runtime;

import fr.upmc.ilp.ilp1.interfaces.IASTvariable;

5 /** Cette classe permet d’etendre un environnement lexical avec une definition* de la constante Pi.*/

public class ConstantsStuff {10

public ConstantsStuff () {}

/** Étendre un environnement lexical pour l’evaluation pour y* installer la constante Pi. */

15

public ILexicalEnvironment extendWithPredefinedConstants (final ILexicalEnvironment lexenv ) {

final ILexicalEnvironment lexenv1 = lexenv.extend(new IASTvariable() {

40

Page 21:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

20 public String getName () {return "pi";

}},new Double(3.141592653589793238462643) );

25 return lexenv1;}

/* NOTA: ce serait bien de regrouper cette methode avec la precedente* mais cela induirait une dependance du paquetage runtime (pour

30 * l’evaluation (cf. cours2)) envers la compilation (cf. cours3) ce qui* est inutile.** Étendre un environnement lexical pour la compilation pour y* installer la constante Pi.

35

public static ICgenLexicalEnvironment extendWithPredefinedConstants (final ICgenLexicalEnvironment lexenv){

final ICgenLexicalEnvironment lexenv1 = lexenv.extend(new IASTvariable () {

40 public String getName () {return "pi";

}}, "ILP_PI");

return lexenv1;45 }

*/

}

Java/src/fr/upmc/ilp/ilp1/runtime/EmptyLexicalEnvironment.java

1 package fr.upmc.ilp.ilp1.runtime;import fr.upmc.ilp.ilp1.interfaces.*;

/** Une définition de l’environnement vide. */

6 public class EmptyLexicalEnvironmentimplements ILexicalEnvironment {

// La technique du singleton:protected EmptyLexicalEnvironment () {}

11 private static final EmptyLexicalEnvironment THE_EMPTY_LEXICAL_ENVIRONMENT;static {

THE_EMPTY_LEXICAL_ENVIRONMENT = new EmptyLexicalEnvironment();}

16 /** Creer un environnement lexical vide.* L’environnement vide ne contient rien et signale* systématiquement une erreur si l’on cherche la valeur d’une* variable.*/

21 public static EmptyLexicalEnvironment create () {return EmptyLexicalEnvironment.THE_EMPTY_LEXICAL_ENVIRONMENT;

}

/** Chercher la valeur d’une variable dans un environnement lexical.26 *

* @param variable la variable dont la valeur est cherchee* @throws EvaluationException si la variable n’a pas de valeur*/

31 public Object lookup (IASTvariable variable)throws EvaluationException {String msg = "Variable sans valeur: "

+ variable.getName();throw new EvaluationException(msg);

36 }

/** On peut étendre l’environnement vide.** Malheureusement , cela crée une dépendance avec la classe des

41 * environnements non vides et çà c’est moche! FIXME.*/public ILexicalEnvironment extend (IASTvariable variable, Object value) {return new LexicalEnvironment(variable , value, this);

}41

46

}

Java/src/fr/upmc/ilp/ilp1/runtime/EvaluationException.java

package fr.upmc.ilp.ilp1.runtime;2

public class EvaluationException extends Exception {

static final long serialVersionUID = +1234567890003000L;

7 public EvaluationException (String message) {super(message);

}

public EvaluationException (Throwable cause) {12 super(cause);

}

}

Java/src/fr/upmc/ilp/ilp1/runtime/ICommon.java

package fr.upmc.ilp.ilp1.runtime;

/**4 * Cette interface définit les caractéristiques globales d’un interprète du

* langage ILP1. On y trouve, notamment , la définition des opérateurs du* langage.*/

9 public interface ICommon {

/** Appliquer un opérateur unaire sur un opérande. */Object applyOperator(String opName, Object operand)

throws EvaluationException;14

/** Appliquer un opérateur binaire sur deux opérandes. */Object applyOperator(String opName, Object leftOperand , Object rightOperand)

throws EvaluationException;

19 }

Java/src/fr/upmc/ilp/ilp1/runtime/ILexicalEnvironment.java

package fr.upmc.ilp.ilp1.runtime;import fr.upmc.ilp.ilp1.interfaces.*;

/** Cette interface définit un environnement lexical pour une5 * évaluation. Un environnement est une structure de données présente

* à l’exécution et contenant une suite de couples (on dit « liaison* ») variable - valeur de cette variable.*/

10 public interface ILexicalEnvironment {

/** Renvoie la valeur d’une variable si présente dans* l’environnement.*

15 * @throws EvaluationException si la variable est absente.*/

Object lookup (IASTvariable variable)throws EvaluationException;

20 /** Étend l’environnement avec un nouveau couple variable -valeur. */ILexicalEnvironment extend (IASTvariable variable , Object value);

}

Java/src/fr/upmc/ilp/ilp1/runtime/Invokable.java

42

Page 22:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

1 package fr.upmc.ilp.ilp1.runtime;

import fr.upmc.ilp.ilp1.runtime.EvaluationException;

/** L’interface des fonctions. La plupart des fonctions ont moins de 46 * arguments aussi des méthodes d’arité diverses sont-elles procurées

* pour invoquer une fonction avec 0, 1, 2 ou 3 arguments.*/

public interface Invokable {11

/** Une fonction invoquée avec un nombre quelconque d’arguments. */

Object invoke (Object[] arguments)throws EvaluationException;

16

/** Invocation d’une fonction zéro-aire (ou niladique) */

Object invoke ()throws EvaluationException;

21

/** Invocation d’une fonction unaire (ou monadique) */

Object invoke (Object argument1)throws EvaluationException;

26

/** Invocation d’une fonction binaire (ou dyadique) */

Object invoke (Object argument1 , Object argument2)throws EvaluationException;

31

/** Invocation d’une fonction ternaire */

Object invoke (Object argument1 , Object argument2 , Object argument3)throws EvaluationException;

36

}

Java/src/fr/upmc/ilp/ilp1/runtime/LexicalEnvironment.java

package fr.upmc.ilp.ilp1.runtime;2 import fr.upmc.ilp.ilp1.interfaces.*;

/** Cette implantation d’environnement est très naïve: c’est une* simple liste chaînée (mais comme nous n’avons pour l’instant que* des blocs unaires cela suffit!).

7 */

public class LexicalEnvironmentimplements ILexicalEnvironment {

12 public LexicalEnvironment (IASTvariable variable ,Object value,ILexicalEnvironment next )

{this.variableName = variable.getName();

17 this.value = value;this.next = next;

}protected final String variableName;protected volatile Object value;

22 protected final ILexicalEnvironment next;

/** Renvoie la valeur d’une variable si présente dans* l’environnement.*/

27 public Object lookup (IASTvariable variable)throws EvaluationException {if ( variableName.equals(variable.getName()) ) {return value;

} else {32 return next.lookup(variable);

}}

/** On peut étendre tout environnement. */37 public ILexicalEnvironment extend (IASTvariable variable, Object value) {

return new LexicalEnvironment(variable , value, this);43

}

}

Java/src/fr/upmc/ilp/ilp1/runtime/PrintStuff.java

package fr.upmc.ilp.ilp1.runtime;

3 import java.io.IOException;import java.io.StringWriter;import java.io.Writer;

import fr.upmc.ilp.ilp1.interfaces.IASTvariable;8

/** les primitives pour imprimer à savoir print et newline. En fait,* newline pourrait se programmer à partir de print et de la chaîne* contenant une fin de ligne mais comme nous n’avons pas encore de* fonctions , elle est utile.

13 */

public class PrintStuff {

private Writer output;18

public PrintStuff () {this(new StringWriter());

}public PrintStuff (Writer writer) {

23 this.output = writer;}

/** Renvoyer les caractères imprimés. */

28 public synchronized String getPrintedOutput () {final String result = output.toString();return result;

}

33 /** étendre un environnement lexical pour l’evaluation pour y installer* les primitives print() et newline(). */

public ILexicalEnvironmentextendWithPrintPrimitives (final ILexicalEnvironment lexenv) {

38 final ILexicalEnvironment lexenv1 = lexenv.extend(new IASTvariable() {

public String getName () {return "print";

}43 }, new PrintPrimitive());

final ILexicalEnvironment lexenv2 = lexenv1.extend(new IASTvariable() {

public String getName () {return "newline";

48 }}, new NewlinePrimitive());

return lexenv2;}

53 // Cf. NOTA de ConstantsStuff pour l’extension de l’environnement de// compilation.

/** Cette classe implante la fonction print() qui permet d’imprimer* une valeur. Elle ne se soucie pas du succès de l’opération! */

58

protected class PrintPrimitive extends AbstractInvokableImpl {public PrintPrimitive () {}// La fonction print() est unaire:@Override

63 public Object invoke (Object value) {try {

output.append(value.toString());} catch (IOException e) {}return Boolean.FALSE;

68 }}

/** Cette classe implante la fonction newline() qui permet de passer* à la ligne. Elle ne se soucie pas du succès de l’opération! */

44

Page 23:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

73

protected class NewlinePrimitive extends AbstractInvokableImpl {public NewlinePrimitive () {}// La fonction print() est zéro-aire:@Override

78 public Object invoke () {try {

output.append("\n");} catch (IOException e) {}return Boolean.FALSE;

83 }}

}

Java/src/fr/upmc/ilp/ilp1/eval/EAST.java

package fr.upmc.ilp.ilp1.eval;import fr.upmc.ilp.ilp1.interfaces.*;import fr.upmc.ilp.ilp1.runtime.*;

4

public abstract class EASTimplements IAST, IASTEvaluable {

/** La méthode qui évalue un EAST et retourne sa valeur. Attention:9 * les valeurs sont des objets JAVA (POJO comme l’on dit). */

public abstract Object eval (ILexicalEnvironment lexenv, ICommon common)throws EvaluationException;

14 /** Un programme qui calcule n’importe quoi. C’est, par exemple,* utilisé pour les alternatives binaires.** NOTA: une fois que ce n’importe-quoi est déterminé , ici, il ne* change plus!

19 */

public static EAST voidConstant () {return THE_VOID_CONSTANT;

}24 private static final EAST THE_VOID_CONSTANT;

static {THE_VOID_CONSTANT = new EASTbooleen("false");

}

29 /** Rendre une valeur quelconque. Ici c’est la valeur de* voidConstant(lexenv, common) qui a été choisie.*/public static Object voidConstantValue () {

return Boolean.FALSE;34 }

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTConstant.java

package fr.upmc.ilp.ilp1.eval;import fr.upmc.ilp.ilp1.runtime.ICommon;

3 import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

/** La classe abstraite des constantes. Elles partagent un même* comportement à savoir rendre leur propre valeur (un objet Java).*

8 * Attention , même si le code de la méthode eval serait le même dans* les sous-classes de EASTConstant , le type de valeur est varié et ne* peut être , sans précaution , partagé! Noter le abstract de la* classe, le protected du constructeur. Noter le protected final sur* valueAsObject (explication en EASTentier).

13 */

public abstract class EASTConstantextends EAST

{18

protected EASTConstant (Object value) {this.valueAsObject = value;

}45

protected final Object valueAsObject;23

/** Toutes les constantes valent leur propre valeur. */

@Overridepublic Object eval (ILexicalEnvironment lexenv, ICommon common) {

28 return valueAsObject;}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTException.java

package fr.upmc.ilp.ilp1.eval;

3 /** Une exception comme les autres mais qu’utilisent préférentiellement* les classes du paquetage eval.*/

public class EASTException extends Exception {8

static final long serialVersionUID = +1234567890002000L;

public EASTException (Throwable cause) {super(cause);

13 }

public EASTException (String message) {super(message);

}18

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTFactory.java

package fr.upmc.ilp.ilp1.eval;import java.util.List;

import fr.upmc.ilp.ilp1.interfaces.IAST;5 import fr.upmc.ilp.ilp1.interfaces.IASTalternative;import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;import fr.upmc.ilp.ilp1.interfaces.IASTboolean;import fr.upmc.ilp.ilp1.interfaces.IASTfloat;import fr.upmc.ilp.ilp1.interfaces.IASTinteger;

10 import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;import fr.upmc.ilp.ilp1.interfaces.IASTstring;import fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock;import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;

15 import fr.upmc.ilp.ilp1.interfaces.IASTvariable;

/** Une fabrique pour fabriquer des EAST. */

public class EASTFactory implements IEASTFactory <EASTException > {20

/** Créer une séquence d’AST. */public IASTsequence newSequence (List<IAST> asts) {return new EASTsequence(asts);

}25

/** Créer une alternative binaire. */public IASTalternative newAlternative (

IAST condition ,IAST consequent) {

30 return new EASTalternative(condition , consequent);}

/** Créer une alternative ternaire. */public IASTalternative newAlternative (

35 IAST condition ,IAST consequent ,IAST alternant) {

return new EASTalternative(condition , consequent , alternant);}

40

/** Créer un bloc local unaire (avec une seule variable locale). */46

Page 24:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

public IASTunaryBlock newUnaryBlock (IASTvariable variable,IAST initialisation ,

45 IASTsequence body) {return new EASTblocUnaire(variable , initialisation , body);

}

/** Créer une variable. */50 public IASTvariable newVariable (String name) {

return new EASTvariable(name);}

/** Créer une invocation (un appel à une fonction). */55 public IASTinvocation newInvocation (String name, List<IAST> asts) {

return new EASTinvocationPrimitive(name, asts);}

/** Créer une opération unaire. */60 public IASTunaryOperation newUnaryOperation (String operatorName ,

IAST operand) {return new EASToperationUnaire(operatorName , operand);

}

65 /** Créer une opération binaire. */public IASTbinaryOperation newBinaryOperation (String operatorName ,

IAST leftOperand ,IAST rightOperand) {

return new EASToperationBinaire(operatorName , leftOperand , rightOperand);70 }

/** Créer une constante littérale entière. */public IASTinteger newIntegerConstant (String value) {return new EASTentier(value);

75 }

/** Créer une constante littérale flottante. */public IASTfloat newFloatConstant (String value) {return new EASTflottant(value);

80 }

/** Créer une constante littérale chaîne de caractères. */public IASTstring newStringConstant (String value) {return new EASTchaine(value);

85 }

/** Créer une constante littérale booléenne. */public IASTboolean newBooleanConstant (String value) {return new EASTbooleen(value);

90 }

/** Signaler un problème avec un message. */public IAST throwParseException (String message)throws EASTException {

95 throw new EASTException(message);}

/** Signaler un problème avec une exception. */public IAST throwParseException (Throwable cause)

100 throws EASTException {throw new EASTException(cause);

}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTFileTest.java

package fr.upmc.ilp.ilp1.eval;

import java.io.File;import java.io.FilenameFilter;

5 import java.io.IOException;import java.io.StringWriter;import java.util.regex.Matcher;import java.util.regex.Pattern;

10 import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;

47

import junit.framework.TestCase;15

import org.w3c.dom.Document;import org.xml.sax.SAXException;

import fr.upmc.ilp.ilp1.runtime.CommonPlus;20 import fr.upmc.ilp.ilp1.runtime.ConstantsStuff;import fr.upmc.ilp.ilp1.runtime.EmptyLexicalEnvironment;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

25 import fr.upmc.ilp.ilp1.runtime.PrintStuff;import fr.upmc.ilp.tool.FileTool;

/** Test d’evaluation de programmes XML.*

30 * Ces fichiers (situés en Grammars/Samples/) ont été préparés par des* programmes rédigés en Scheme (situés en Grammars/Scheme/), ils sont* accompagnes d’un fichier .result qui représente la valeur attendue* et un fichier .print qui contient ce qui est imprimé. Cette classe* doit etre executee dans le repertoire qui contient Java et Grammars

35 * (car Eclipse ne semble pas permettre que l’on indique Java/ tout court!).*/

public class EASTFileTest extends TestCase {

40 /** Établir l’environnement de test. */

@Overridepublic void setUp () {

common = new CommonPlus();45 lexenv = EmptyLexicalEnvironment.create();

sw = new StringWriter();ps = new PrintStuff(sw);lexenv = ps.extendWithPrintPrimitives(lexenv);cs = new ConstantsStuff();

50 lexenv = cs.extendWithPredefinedConstants(lexenv);factory = new EASTFactory();

}protected ILexicalEnvironment lexenv;protected ICommon common;

55 protected EASTFactory factory;protected StringWriter sw;protected PrintStuff ps;protected ConstantsStuff cs;

60 /** Les caractéristiques des programmes XML à tester: */

protected final File directory = new File("Grammars" + File.separator + "Samples" + File.separator );

protected final Pattern p = Pattern.compile("^u\\d+-1.xml$");65 protected final Pattern pfull =

Pattern.compile("(.*" + File.separator + "u\\d+-1).xml$");

/** Tester un programme c’est-à-dire le lire depuis XML, le* convertir en un EAST, l’évaluer et comparer le résultat avec ce

70 * qui était attendu. */

protected void handleFile (String basefilename)throws IOException , ParserConfigurationException , SAXException ,

EASTException , EvaluationException {75 // Vider le tampon de sortie

sw.getBuffer().delete(0, sw.getBuffer().length());File xmlFile = new File(basefilename + ".xml");DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();

80 Document d = db.parse(xmlFile);EASTParser parser = new EASTParser(factory);EAST east = (EAST) parser.parse(d);// Évaluer et comparer les résultats:Object result = east.eval(lexenv, common);

85 System.err.println("Obtained result is: " + result);String expectedResult = FileTool.readExpectedResult(basefilename);System.err.println("Expected result was: " + expectedResult);if ( result instanceof Double ) {

double fExpectedResult = Double.parseDouble(expectedResult);90 assertEquals(fExpectedResult , (Double)result, 0.1);

} else {// Comme noté par [email protected], il faut équeuter

48

Page 25:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

// (par trim()) les deux termes de la comparaison:assertEquals(expectedResult , result.toString().trim());

95 }// Comparer les impressions:String expectedPrinting = FileTool.readExpectedPrinting(basefilename);String printing = ps.getPrintedOutput();System.err.println("Obtained printing:" + printing);

100 System.err.println("Expected printing:" + expectedPrinting);assertEquals(expectedPrinting , printing.trim());

}

/** Rechercher tous les fichiers u*-1.xml et les tester. */105

public void testUFiles ()throws IOException , ParserConfigurationException , SAXException ,

EASTException , EvaluationException {FilenameFilter ff = new FilenameFilter() {

110 public boolean accept (File dir, String name) {final Matcher m = p.matcher(name);return m.matches();

}};

115 final File[] testFiles = directory.listFiles(ff);// Si cette assertion n’est pas remplie, on n’est certainement pas// dans le bon repertoire (celui qui contient Grammars).assertNotNull(testFiles);// Au moins 38 programmes de test:

120 assertTrue(testFiles.length >= 38);// Trier les noms de fichiers en place:java.util.Arrays.sort(testFiles , new java.util.Comparator <File>() {

public int compare (File f1, File f2) {return f1.getName().compareTo(f2.getName());

125 }@Overridepublic boolean equals (Object comparator) {return false;

}130 });

for ( int i = 0 ; i<testFiles.length ; i++ ) {final String filename = testFiles[i].getPath();System.err.println("Testing " + filename);final Matcher m = pfull.matcher(filename);

135 assertTrue(m.matches());handleFile(m.group(1));

}}

140 /*** Un point d’entree pour lancer cette classe de Test pour Junit3* comme une application Java. Elle requiert sur la ligne de* commande , le nom d’un fichier ILP a evaluer.*/

145

public static void main (String[] argument)throws Exception {

if ( argument.length != 1 ) {String msg = "Missing ILP filename!";

150 throw new RuntimeException(msg);}File f = new File(argument[0]);if ( f.exists() && f.canRead() ) {

String baseFileName = f.getAbsolutePath();155 if ( baseFileName.endsWith(".xml") ) {

int n = baseFileName.lastIndexOf(".xml");baseFileName = baseFileName.substring(0, n);

}EASTFileTest tc = new EASTFileTest();

160 tc.setUp();tc.handleFile(baseFileName);

}}

165 }

Java/src/fr/upmc/ilp/ilp1/eval/EASTParser.java

package fr.upmc.ilp.ilp1.eval;

49

import java.util.List;4 import java.util.Vector;

import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;

9 import org.w3c.dom.NodeList;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTvariable;

14 /** Le but de cette classe est de transformer un document XML en un* AST avec évaluation conforme à fr.upmc.ilp.interfaces.IAST.** Cet analyseur améliore ASTParser en ce sens qu’il est paramétré par* une fabrique de construction d’AST. À part sa construction , cet

19 * analyseur s’utilise tout comme un ASTParser.*/

public class EASTParser {

24 /** Constructeur d’analyseur de document (ou noeud) DOM en un AST* dont les constructeurs particuliers sont fournis par une* fabrique. */

public EASTParser (final IEASTFactory <EASTException > factory) {29 this.factory = factory;

}

protected final IEASTFactory <EASTException > factory;

34 /** Analyseur de DOM en AST. Les noeuds de l’AST sont créés par la* fabrique spécifiée à la construction de l’EASTParser. Même les* exceptions sont signalées par cette même fabrique.*/

39 public IAST parse (final Node n)throws EASTException {

try {switch ( n.getNodeType() ) {

44 case Node.DOCUMENT_NODE: {final Document d = (Document) n;return this.parse(d.getDocumentElement());

}

49 case Node.ELEMENT_NODE: {final Element e = (Element) n;final NodeList nl = e.getChildNodes();final String name = e.getTagName();

54 if ( "programme1".equals(name) ) {return factory.newSequence(parseList(nl));

} else if ( "alternative".equals(name) ) {final IAST cond = findThenParseChild(nl, "condition");

59 final IAST conseq =findThenParseChildAsInstructions(nl, "consequence");

try {final IAST alt =

findThenParseChildAsInstructions(nl, "alternant");64 return factory.newAlternative(cond, conseq, alt);

} catch (EASTException exc) {return factory.newAlternative(cond, conseq);

}

69 } else if ( "sequence".equals(name) ) {return factory.newSequence(this.parseList(nl));

} else if ( "blocUnaire".equals(name) ) {final IASTvariable var =

74 (IASTvariable) findThenParseChild(nl, "variable");final IAST init = findThenParseChild(nl, "valeur");final EASTsequence body =

(EASTsequence) findThenParseChild(nl, "corps");return factory.newUnaryBlock(var, init, body);

79

} else if ( "variable".equals(name) ) {

50

Page 26:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

final String nick = e.getAttribute("nom");return factory.newVariable(nick);

84 } else if ( "invocationPrimitive".equals(name) ) {final String op = e.getAttribute("fonction");final List<IAST> args = parseList(nl);return factory.newInvocation(op, args);

89 } else if ( "operationUnaire".equals(name) ) {final String op = e.getAttribute("operateur");final IAST rand = findThenParseChild(nl, "operande");return factory.newUnaryOperation(op, rand);

94 } else if ( "operationBinaire".equals(name) ) {final String op = e.getAttribute("operateur");final IAST gauche = findThenParseChild(nl, "operandeGauche");final IAST droite = findThenParseChild(nl, "operandeDroit");return factory.newBinaryOperation(op, gauche, droite);

99

} else if ( "entier".equals(name) ) {return factory.newIntegerConstant(e.getAttribute("valeur"));

} else if ( "flottant".equals(name) ) {104 return factory.newFloatConstant(e.getAttribute("valeur"));

} else if ( "chaine".equals(name) ) {final String text = n.getTextContent();//final String text = this.extractText(e);

109 return factory.newStringConstant(text);

} else if ( "booleen".equals(name) ) {return factory.newBooleanConstant(e.getAttribute("valeur"));

114 // Une série d’éléments devant être analysés comme des expressions:} else if ( "operandeGauche".equals(name) ) {

return this.parseUniqueChild(nl);} else if ( "operandeDroit".equals(name) ) {

return this.parseUniqueChild(nl);119 } else if ( "operande".equals(name) ) {

return this.parseUniqueChild(nl);} else if ( "condition".equals(name) ) {

return this.parseUniqueChild(nl);} else if ( "consequence".equals(name) ) {

124 return this.parseUniqueChild(nl);} else if ( "alternant".equals(name) ) {

return this.parseUniqueChild(nl);} else if ( "valeur".equals(name) ) {

return this.parseUniqueChild(nl);129

// Une série d’éléments devant être analysée comme une séquence:} else if ( "corps".equals(name) ) {

return factory.newSequence(this.parseList(nl));

134 } else {final String msg = "Unknown element name: " + name;return factory.throwParseException(msg);

}}

139

default: {final String msg = "Unknown node type: " + n.getNodeName();return factory.throwParseException(msg);

}144 }

} catch (final EASTException e) {throw e;

} catch (final Exception e) {throw new EASTException(e);

149 }}

/** Analyser une séquence d’éléments pour en faire un ASTlist* c’est-à-dire une séquence d’AST.

154 */

public List<IAST> parseList (final NodeList nl)throws EASTException {

51

final List<IAST> result = new Vector<IAST >();159 final int n = nl.getLength();

LOOP:for ( int i = 0 ; i<n ; i++ ) {

final Node nd = nl.item(i);switch ( nd.getNodeType() ) {

164

case Node.ELEMENT_NODE: {final IAST p = this.parse(nd);result.add(p);continue LOOP;

169 }

default: {// On ignore tout ce qui n’est pas élément XML:

}174 }

}return result;

}

179 /** Trouver un élément d’après son nom et l’analyser pour en faire* un AST. */

public IAST findThenParseChild (final NodeList nl, final String childName)throws EASTException {

184 IAST result = null;final int n = nl.getLength();for ( int i = 0 ; i<n ; i++ ) {

final Node nd = nl.item(i);switch ( nd.getNodeType() ) {

189

case Node.ELEMENT_NODE: {final Element e = (Element) nd;if ( childName.equals(e.getTagName()) ) {

if ( result == null ) {194 result = this.parse(e);

} else {final String msg = "Non unique child with name " + childName;return factory.throwParseException(msg);

}199 }

break;}

default: {204 // On ignore tout ce qui n’est pas élément XML:

}}

}if ( result == null ) {

209 final String msg = "No such child element " + childName;return factory.throwParseException(msg);

}return result;

}214

/** Trouver un élément d’après son nom et analyser son contenu pour* en faire un ASTsequence.** @throws ILPException

219 * lorsqu’un tel élément n’est pas trouvé.*/

public IAST findThenParseChildAsInstructions (final NodeList nl,

224 final String childName)throws EASTException {

int n = nl.getLength();for ( int i = 0 ; i<n ; i++ ) {

Node nd = nl.item(i);229 switch ( nd.getNodeType() ) {

case Node.ELEMENT_NODE: {Element e = (Element) nd;if ( childName.equals(e.getTagName()) ) {

234 return factory.newSequence(this.parseList(e.getChildNodes()));}

52

Page 27:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

break;}

239 default: {// On ignore tout ce qui n’est pas élément XML:

}}

}244 String msg = "No such child element " + childName;

return factory.throwParseException(msg);}

/** Analyser une suite comportant un unique élément. */249

public IAST parseUniqueChild (final NodeList nl)throws EASTException {

IAST result = null;final int n = nl.getLength();

254 for ( int i = 0 ; i<n ; i++ ) {final Node nd = nl.item(i);switch ( nd.getNodeType() ) {

case Node.ELEMENT_NODE: {259 final Element e = (Element) nd;

if ( result == null ) {result = this.parse(e);

} else {final String msg = "Non unique child";

264 return factory.throwParseException(msg);}break;

}

269 default: {// On ignore tout ce qui n’est pas élément XML:

}}

}274 if ( result == null ) {

factory.throwParseException("No child at all");}return result;

}279

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTPrimitiveTest.java

package fr.upmc.ilp.ilp1.eval;

import java.util.List;4 import java.util.Vector;

import junit.framework.TestCase;import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.runtime.Common;

9 import fr.upmc.ilp.ilp1.runtime.ConstantsStuff;import fr.upmc.ilp.ilp1.runtime.EmptyLexicalEnvironment;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

14 import fr.upmc.ilp.ilp1.runtime.PrintStuff;

/** Tests (Junit3) d’invocation des primitives (dans PrintStuff). */

public class EASTPrimitiveTest extends TestCase {19

@Overridepublic void setUp() {

common = new Common();lexenv = EmptyLexicalEnvironment.create();

24 ps = new PrintStuff();lexenv = ps.extendWithPrintPrimitives(lexenv);cs = new ConstantsStuff();lexenv = cs.extendWithPredefinedConstants(lexenv);

}29

private ILexicalEnvironment lexenv;53

private ICommon common;private PrintStuff ps;private ConstantsStuff cs;

34

public void testPi() throws EASTException , EvaluationException {EASTvariable var = new EASTvariable("pi");Object result = var.eval(lexenv, common);assertTrue(result instanceof Double);

39 assertEquals((Double) result, 3.14, 0.1);}

public void testNewline() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();

44 EAST o = new EASTinvocationPrimitive("newline", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("\n", ps.getPrintedOutput());

49 }

public void testPrintEntier() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTentier("34"));

54 EAST o = new EASTinvocationPrimitive("print", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("34", ps.getPrintedOutput());

59 }

public void testPrintFlottant() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTflottant("3.14"));

64 EAST o = new EASTinvocationPrimitive("print", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("3.14", ps.getPrintedOutput());

69 }

public void testPrintString() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTchaine("foobar"));

74 EAST o = new EASTinvocationPrimitive("print", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("foobar", ps.getPrintedOutput());

79 }

public void testPrintBoolTrue() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTbooleen("true"));

84 EAST o = new EASTinvocationPrimitive("print", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("true", ps.getPrintedOutput());

89 }

public void testPrintBoolFalse() throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTbooleen("false"));

94 EAST o = new EASTinvocationPrimitive("print", args);Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);assertEquals("false", ps.getPrintedOutput());

99 }

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTTest.java

package fr.upmc.ilp.ilp1.eval;

3 import java.math.BigInteger;import java.util.List;

54

Page 28:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

import java.util.Vector;

import junit.framework.TestCase;8 import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.runtime.Common;import fr.upmc.ilp.ilp1.runtime.CommonPlus;import fr.upmc.ilp.ilp1.runtime.EmptyLexicalEnvironment;import fr.upmc.ilp.ilp1.runtime.EvaluationException;

13 import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

/** Tests (JUnit3) d’évaluation sans utiliser de fabrique. */

18 public class EASTTest extends TestCase {

@Overridepublic void setUp () {

lexenv = EmptyLexicalEnvironment.create();23 common = new Common();

}

private ILexicalEnvironment lexenv;

28 private ICommon common;

public void testEntier () throws EASTException , EvaluationException {EAST o = new EASTentier("34");Object result = o.eval(lexenv, common);

33 assertTrue(result instanceof BigInteger);assertEquals(result, new BigInteger("34"));

}

public void testFlottant () throws EASTException , EvaluationException {38 EAST o = new EASTflottant("3.14");

Object result = o.eval(lexenv, common);assertTrue(result instanceof Double);assertEquals(result, new Double("3.14"));

}43

public void testChaine () throws EASTException , EvaluationException {EAST o = new EASTchaine("foobar");Object result = o.eval(lexenv, common);assertTrue(result instanceof String);

48 assertEquals(result, "foobar");}

public void testBooleenVrai () throws EASTException , EvaluationException {EAST o = new EASTbooleen("true");

53 Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.TRUE);

}

58 public void testBooleenFaux () throws EASTException , EvaluationException {EAST o = new EASTbooleen("false");Object result = o.eval(lexenv, common);assertTrue(result instanceof Boolean);assertEquals(result, Boolean.FALSE);

63 }

public void testAlternativeVraie () throws EASTException ,EvaluationException {

EAST o = new EASTalternative(new EASTbooleen("true"), new EASTentier(68 "1"), new EASTentier("0"));

Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("1"));

}

73 public void testAlternativeFausse () throws EASTException ,EvaluationException {

EAST o = new EASTalternative(new EASTbooleen("false"), new EASTentier("1"), new EASTentier("0"));

Object result = o.eval(lexenv, common);78 assertEquals(result, new BigInteger("0"));

}

public void testSequence1 () throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();

83 args.add(new EASTentier("0"));EAST o = new EASTsequence(args);

55

Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("0"));

}88

public void testSequence2 () throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTentier("1"));args.add(new EASTentier("0"));

93 EAST o = new EASTsequence(args);Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("0"));

}

98 public void testSequence3 () throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();args.add(new EASTentier("1"));args.add(new EASTentier("0"));args.add(new EASTbooleen("true"));

103 EAST o = new EASTsequence(args);Object result = o.eval(lexenv, common);assertEquals(result, Boolean.TRUE);

}

108 public void testSequence0 () throws EASTException , EvaluationException {List<IAST> args = new Vector<IAST >();EAST o = new EASTsequence(args);Object result = o.eval(lexenv, common);assertNotNull(result);

113 }

public void testVariable1 () throws EASTException , EvaluationException {lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));EAST o = new EASTvariable("x");

118 Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("23"));

}

public void testVariable2 () throws EASTException , EvaluationException {123 lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));

lexenv = lexenv.extend(new EASTvariable("y"), new BigInteger("25"));EAST o = new EASTvariable("x");Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("23"));

128 }

public void testVariable0 () throws EASTException , EvaluationException {lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));lexenv = lexenv.extend(new EASTvariable("y"), new BigInteger("25"));

133 EAST o = new EASTvariable("z");try {

o.eval(lexenv, common);} catch (EvaluationException exc) {

assertTrue(true);138 }

}

public void testBlocUnaireVarless () throws EASTException ,EvaluationException {

143 lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));lexenv = lexenv.extend(new EASTvariable("y"), new BigInteger("25"));List<IAST> instructions = new Vector<IAST >();instructions.add(new EASTentier("1"));EAST o = new EASTblocUnaire(new EASTvariable("z"),

148 new EASTentier("345"), new EASTsequence(instructions));Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("1"));

}

153 public void testBlocUnaireWithVar () throws EASTException ,EvaluationException {

lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));lexenv = lexenv.extend(new EASTvariable("y"), new BigInteger("25"));List<IAST> instructions = new Vector<IAST >();

158 instructions.add(new EASTvariable("z"));EAST o = new EASTblocUnaire(new EASTvariable("z"),

new EASTentier("345"), new EASTsequence(instructions));Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("345"));

163 }

public void testBlocUnaireOuterScope () throws EASTException ,56

Page 29:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

EvaluationException {lexenv = lexenv.extend(new EASTvariable("x"), new BigInteger("23"));

168 lexenv = lexenv.extend(new EASTvariable("y"), new BigInteger("25"));List<IAST> instructions = new Vector<IAST >();instructions.add(new EASTvariable("y"));EAST o = new EASTblocUnaire(new EASTvariable("z"),

new EASTentier("345"), new EASTsequence(instructions));173 Object result = o.eval(lexenv, common);

assertEquals(result, new BigInteger("25"));}

public void testOperateurUnaireMoinsI () throws EASTException ,178 EvaluationException {

EAST o = new EASToperationUnaire("-", new EASTentier("42"));Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("-42"));

}183

public void testOperateurUnaireMoinsF () throws EASTException ,EvaluationException {

EAST o = new EASToperationUnaire("-", new EASTflottant("4.2"));Object result = o.eval(lexenv, common);

188 assertEquals(result, new Double("-4.2"));}

public void testOperateurUnaireMoins2I () throws EASTException ,EvaluationException {

193 EAST o = new EASToperationUnaire("-", new EASToperationUnaire("-",new EASTentier("42")));

Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("42"));

}198

public void testOperateurUnaireMoins2F () throws EASTException ,EvaluationException {

EAST o = new EASToperationUnaire("-", new EASToperationUnaire("-",new EASTflottant("4.2")));

203 Object result = o.eval(lexenv, common);assertEquals(result, new Double("4.2"));

}

public void testOperateurUnaireNot () throws EASTException ,208 EvaluationException {

EAST o = new EASToperationUnaire("!", new EASTbooleen("true"));Object result = o.eval(lexenv, common);assertEquals(result, Boolean.FALSE);

}213

// Operateur binaire: addition.

public void testOperateurBinairePlusII () throws EASTException ,EvaluationException {

218 EAST o = new EASToperationBinaire("+", new EASTentier("1"),new EASTentier("2"));

Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("3"));

}223

public void testOperateurBinairePlusIF () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("+", new EASTentier("1"),new EASTflottant("3.1"));

228 Object result = o.eval(lexenv, common);assertEquals(result, new Double("4.1"));

}

public void testOperateurBinairePlusFI () throws EASTException ,233 EvaluationException {

EAST o = new EASToperationBinaire("+", new EASTflottant("3.1"),new EASTentier("1"));

Object result = o.eval(lexenv, common);assertEquals(result, new Double("4.1"));

238 }

public void testOperateurBinairePlusFF () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("+", new EASTflottant("3.1"),243 new EASTflottant("1.1"));

Object result = o.eval(lexenv, common);assertEquals(result, new Double("4.2"));

}57

248 // Operateur binaire: soustraction

public void testOperateurBinaireMinusII () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("-", new EASTentier("11"),253 new EASTentier("2"));

Object result = o.eval(lexenv, common);assertEquals(result, new BigInteger("9"));

}

258 public void testOperateurBinaireMinusIF () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("-", new EASTentier("10"),new EASTflottant("3.1"));

Object result = o.eval(lexenv, common);263 assertEquals(result, new Double("6.9"));

}

public void testOperateurBinaireMinusFI () throws EASTException ,EvaluationException {

268 EAST o = new EASToperationBinaire("-", new EASTflottant("3.1"),new EASTentier("1"));

Object result = o.eval(lexenv, common);assertEquals(result, new Double("2.1"));

}273

public void testOperateurBinaireMinusFF () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("-", new EASTflottant("3.1"),new EASTflottant("1.1"));

278 Object result = o.eval(lexenv, common);assertEquals(result, new Double("2.0"));

}

// Les operateurs booleens. Ils ont besoin de CommonPlus.283

public void testOperateurBinaireEtFT () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("&", new EASTbooleen("false"),new EASTbooleen("true"));

288 common = new CommonPlus();Object result = o.eval(lexenv, common);assertEquals(result, Boolean.FALSE);

}

293 public void testOperateurBinaireOuFT () throws EASTException ,EvaluationException {

EAST o = new EASToperationBinaire("|", new EASTbooleen("false"),new EASTbooleen("true"));

common = new CommonPlus();298 Object result = o.eval(lexenv, common);

assertEquals(result, Boolean.TRUE);}

public void testOperateurBinaireXorFT () throws EASTException ,303 EvaluationException {

EAST o = new EASToperationBinaire("^", new EASTbooleen("false"),new EASTbooleen("true"));

common = new CommonPlus();Object result = o.eval(lexenv, common);

308 assertEquals(result, Boolean.TRUE);}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTalternative.java

package fr.upmc.ilp.ilp1.eval;

3 import fr.upmc.ilp.annotation.OrNull;import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTalternative;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;

8 import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

public class EASTalternative extends EASTimplements IASTalternative {

58

Page 30:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

13 public EASTalternative(IAST condition , IAST consequence , IAST alternant) {this.condition = (EAST) condition;this.consequence = (EAST) consequence;this.alternant = (EAST) alternant;

}18

// NOTA: Masquer l’implantation de l’alternative binaire afin// d’éviter la propagation de null.

public EASTalternative(IAST condition , IAST consequence) {23 this.condition = (EAST) condition;

this.consequence = (EAST) consequence;this.alternant = null;

}

28 protected EAST condition;protected EAST consequence;protected EAST alternant;

public IAST getCondition() {33 return this.condition;

}

public IAST getConsequent() {return this.consequence;

38 }

/** Quand il n’y a pas d’alternant , on rend n’importe quoi. Ce* n’importe-quoi est engendré par un utilitaire partagé au niveau d’AST. */

43 @OrNull public IAST getAlternant() {return this.alternant;

}

public boolean isTernary() {48 return alternant != null;

}

@Overridepublic Object eval(ILexicalEnvironment lexenv, ICommon common)

53 throws EvaluationException {Object bool = condition.eval(lexenv, common);if (Boolean.FALSE == bool) {if (isTernary()) {return alternant.eval(lexenv, common);

58 } else {// Et pas EAST.voidConstant() comme signalé par// <[email protected]>return EAST.voidConstantValue();

}63 } else {

return consequence.eval(lexenv, common);}

}

68 }

Java/src/fr/upmc/ilp/ilp1/eval/EASTblocUnaire.java

1 package fr.upmc.ilp.ilp1.eval;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;import fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock;

6 import fr.upmc.ilp.ilp1.interfaces.IASTvariable;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

11 /** Les blocs locaux à une seule variable. */

public class EASTblocUnaireextends EASTimplements IASTunaryBlock {

16

public EASTblocUnaire (IASTvariable variable ,59

IAST initialization ,IASTsequence body)

{21 this.variable = (EASTvariable) variable;

this.initialization = (EAST) initialization;this.body = (EASTsequence) body;

}

26 protected EASTvariable variable;protected EAST initialization;protected EASTsequence body;

public IASTvariable getVariable () {31 return this.variable;

}public IAST getInitialization () {return this.initialization;

}36 public IASTsequence getBody () {

return this.body;}

@Override41 public Object eval (ILexicalEnvironment lexenv, ICommon common)

throws EvaluationException {ILexicalEnvironment newlexenv =

lexenv.extend(variable, initialization.eval(lexenv, common));return body.eval(newlexenv , common);

46 }

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTbooleen.java

1 package fr.upmc.ilp.ilp1.eval;import fr.upmc.ilp.ilp1.interfaces.IASTboolean;

/** Une constante booleenne. */

6 public class EASTbooleenextends EASTConstantimplements IASTboolean

{

11 /** Nota: Encore un cas ennuyeux où l’appel à super() n’est pas* trivial. Il y a quelques années, le vérifieur de code-octet avait* tendance à refuser ce genre de programmation! */

public EASTbooleen (String valeur) {16 super( ("true".equals(valeur))

? Boolean.TRUE : Boolean.FALSE );this.valeur = "true".equals(valeur);

}private final boolean valeur;

21

public boolean getValue () {return valeur;

}

26 }

Java/src/fr/upmc/ilp/ilp1/eval/EASTchaine.java

package fr.upmc.ilp.ilp1.eval;import fr.upmc.ilp.ilp1.interfaces.IASTstring;

3

/** Les constantes de type chaine de caracteres. */

public class EASTchaineextends EASTConstant

8 implements IASTstring {

public EASTchaine (String valeur) {super(valeur);this.valeur = valeur;

60

Page 31:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

13 }private final String valeur;

public String getValue () {return valeur;

18 }

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTentier.java

package fr.upmc.ilp.ilp1.eval;import java.math.BigInteger;

4 import fr.upmc.ilp.ilp1.interfaces.IASTinteger;

/** Les constantes entières littérales. Elles sont représentées par* des BigInteger ce qui permet de ne pas rendre syntaxiquement faux* un programme qui mentionnerait des entiers plus grand que ce que

9 * sait faire la machine. En outre, cela permet de donner une* arithmétique complète à cette implantation.*/

public class EASTentier14 extends EASTConstant

implements IASTinteger {

/** Constructeur.*

19 * NOTA: Pour initialiser le champ valueAsObject , on fait le bon* appel à super() mais comme un BigInteger est un gros objet que* l’on ne tient pas à dupliquer , on l’utilise tel qu’il apparaît* dans EASTConstant. Conclusion: valueAsObject ne peut plus être* privée à EASTConstant et voilà comment les « protected »

24 * croissent dans les codes!*/

public EASTentier (String valeur) {super(new BigInteger(valeur));

29 }

public BigInteger getValue () {return (BigInteger) this.valueAsObject;

}34

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTflottant.java

package fr.upmc.ilp.ilp1.eval;import java.math.BigDecimal;

4 import fr.upmc.ilp.ilp1.interfaces.IASTfloat;

/** Les constantes flottantes. */

public class EASTflottant9 extends EASTConstant

implements IASTfloat {

/** Constructeur.*

14 * Ici, le double est pris comme une chaîne puis manipulé comme un* Double (en guise d’objet Java) pour l’évaluation. En revanche* pour les IAST, il est manipulé comme un BigDecimal pour ne pas* subir de dégradation de précision. L’implantation perd donc de la* précision par rapport à la syntaxe!

19 */

public EASTflottant (String valeur) {super(new Double(valeur));this.bigfloat = new BigDecimal(valeur);

24 }private final BigDecimal bigfloat;

public BigDecimal getValue () {61

return bigfloat;29 }

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocation.java

package fr.upmc.ilp.ilp1.eval;

3 import java.util.List;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;import fr.upmc.ilp.ilp1.runtime.EvaluationException;

8 import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;import fr.upmc.ilp.ilp1.runtime.Invokable;

/** La classe abstraite des invocations en general. */13

public abstract class EASTinvocation extends EASTimplements IASTinvocation {

protected EASTinvocation (final EAST fonction , final List<IAST> arguments) {18 this.fonction = fonction;

this.argument = arguments.toArray(new EAST[0]);}protected EAST fonction;protected EAST[] argument;

23

public IAST getFunction () {return this.fonction;

}

28 public IAST[] getArguments () {return this.argument;

}

public int getArgumentsLength () {33 return this.argument.length;

}

public IAST getArgument (final int i) {return this.argument[i];

38 }

@Overridepublic Object eval (final ILexicalEnvironment lexenv, final ICommon common)throws EvaluationException {

43 final Object fn = this.fonction.eval(lexenv, common);if ( fn instanceof Invokable ) {

Invokable invokable = (Invokable) fn;final Object[] args = new Object[argument.length];for ( int i = 0 ; i<argument.length ; i++ ) {

48 args[i] = argument[i].eval(lexenv, common);}return invokable.invoke(args);

} else {final String msg = "Not a function: " + fn;

53 throw new EvaluationException(msg);}

}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTinvocationPrimitive.java

package fr.upmc.ilp.ilp1.eval;2

import java.util.List;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.runtime.EvaluationException;

7 import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

62

Page 32:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** L’invocation des primitives. */

12 public class EASTinvocationPrimitiveextends EASTinvocation {

public EASTinvocationPrimitive (final String fonction,final List<IAST> arguments) {

17 super(new EASTvariable(fonction), arguments);}

@Overridepublic Object eval (final ILexicalEnvironment lexenv, final ICommon common)

22 throws EvaluationException {return super.eval(lexenv, common);

}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASToperation.java

package fr.upmc.ilp.ilp1.eval;

3 import fr.upmc.ilp.ilp1.interfaces.IASToperation;

/** La classe abstraite des operations.** NOTA: Notez que la méthode getOperands() manque alors qu’elle est

8 * présente dans l’interface (IASToperation) que cette classe* implante! Savez-vous pourquoi ?*/

public abstract class EASToperation13 extends EAST

implements IASToperation{

protected EASToperation (String operateur , int arity) {18 this.operateur = operateur;

this.arity = arity;}private final String operateur;private final int arity;

23

// et pourquoi les final ici ?public final String getOperatorName () {return this.operateur;

}28

public final int getArity () {return this.arity;

}

33 }

Java/src/fr/upmc/ilp/ilp1/eval/EASToperationBinaire.java

1 package fr.upmc.ilp.ilp1.eval;

import java.util.List;import java.util.Vector;

6 import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

11

/** Les operations binaires. */

public class EASToperationBinaireextends EASToperation

16 implements IASTbinaryOperation {

public EASToperationBinaire (String operateur ,63

IAST operandeGauche ,IAST operandeDroit)

21 {super(operateur , 2);this.operandeGauche = (EAST) operandeGauche;this.operandeDroit = (EAST) operandeDroit;

}26

protected EAST operandeGauche;protected EAST operandeDroit;

public IAST getLeftOperand () {31 return this.operandeGauche;

}public IAST getRightOperand () {return this.operandeDroit;

}36

public IAST[] getOperands () {// On calcule paresseusement car ce n’est pas une methode usuelle:if ( operands == null ) {

List<EAST> loperands = new Vector<EAST >();41 loperands.add(operandeGauche);

loperands.add(operandeDroit);operands = loperands.toArray(new EAST[0]);

}return operands;

46 }// NOTA: remarquer que ce mode paresseux interdit de qualifier ce// champ de « final » ce qui n’est pas sûr!private EAST[] operands;

51 @Overridepublic Object eval (ILexicalEnvironment lexenv, ICommon common)throws EvaluationException {Object r1 = operandeGauche.eval(lexenv, common);Object r2 = operandeDroit.eval(lexenv, common);

56 return common.applyOperator(this.getOperatorName(), r1, r2);}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASToperationUnaire.java

package fr.upmc.ilp.ilp1.eval;

import java.util.List;import java.util.Vector;

5

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;

10 import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

/** Les operations unaires. */

public class EASToperationUnaire15 extends EASToperation

implements IASTunaryOperation {

public EASToperationUnaire (String operateur , IAST operand) {super(operateur , 1);

20 this.operand = (EAST) operand;}protected EAST operand;

public IAST getOperand () {25 return this.operand;

}

public IAST[] getOperands () {// On calcule paresseusement car ce n’est pas une methode usuelle:

30 if ( operands == null ) {List<EAST> loperands = new Vector<EAST >();loperands.add(operand);operands = loperands.toArray(new EAST[0]);

64

Page 33:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

}35 return operands;

}private EAST[] operands;

@Override40 public Object eval (ILexicalEnvironment lexenv, ICommon common)

throws EvaluationException {return common.applyOperator(this.getOperatorName(),

operand.eval(lexenv, common));}

45

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTsequence.java

package fr.upmc.ilp.ilp1.eval;

3 import java.util.List;

import fr.upmc.ilp.annotation.OrNull;import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;

8 import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

/** Les sequences d’instructions. Les grammaires imposent normalement13 * qu’il y a au moins une instruction dans une sequence. */

public class EASTsequence extends EASTimplements IASTsequence {

18 public EASTsequence (List<IAST> instructions) {this.instruction = instructions.toArray(new EAST[0]);

}protected EAST[] instruction;

23 public IAST[] getInstructions () {return this.instruction;

}public @OrNull IAST getInstruction (int i) {

return this.instruction[i];28 }

public int getInstructionsLength () {return this.instruction.length;

}

33 /*** L’évaluation d’une séquence passe par celle, ordonnée, de toutes* les instructions qu’elle contient.** NOTA: inutile de se compliquer la vie, Java ne supporte pas la

38 * récursion terminale.* NOTA2: Le cas de la séquence vide est prévu.*/

@Override43 public Object eval (ILexicalEnvironment lexenv, ICommon common)

throws EvaluationException {Object last = EAST.voidConstantValue();for ( int i = 0 ; i < instruction.length ; i++ ) {

last = instruction[i].eval(lexenv, common);48 }

return last;}

}

Java/src/fr/upmc/ilp/ilp1/eval/EASTvariable.java

package fr.upmc.ilp.ilp1.eval;2

import fr.upmc.ilp.ilp1.interfaces.*;import fr.upmc.ilp.ilp1.runtime.*;

65

/** Une variable. */7

public class EASTvariableextends EASTimplements IASTvariable {

12 public EASTvariable (String name) {this.name = name;

}private final String name;

17 public String getName () {return name;

}

@Override22 public Object eval (ILexicalEnvironment lexenv, ICommon common)

throws EvaluationException {return lexenv.lookup(this);

}

27 }

Java/src/fr/upmc/ilp/ilp1/eval/IASTEvaluable.java

package fr.upmc.ilp.ilp1.eval;2

import fr.upmc.ilp.ilp1.runtime.EvaluationException;import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;

7 public interface IASTEvaluable {

/** La méthode qui évalue un IAST et retourne sa valeur. Attention:* les valeurs sont des objets JAVA (POJO comme l’on dit). */

12 Object eval (ILexicalEnvironment lexenv, ICommon common)throws EvaluationException;

}

Java/src/fr/upmc/ilp/ilp1/eval/IEASTFactory.java

package fr.upmc.ilp.ilp1.eval;import java.util.List;

import fr.upmc.ilp.ilp1.interfaces.IAST;5 import fr.upmc.ilp.ilp1.interfaces.IASTalternative;import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;import fr.upmc.ilp.ilp1.interfaces.IASTboolean;import fr.upmc.ilp.ilp1.interfaces.IASTfloat;import fr.upmc.ilp.ilp1.interfaces.IASTinteger;

10 import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;import fr.upmc.ilp.ilp1.interfaces.IASTstring;import fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock;import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;

15 import fr.upmc.ilp.ilp1.interfaces.IASTvariable;

/** Cette interface décrit une fabrique d’AST conforme aux IAST. Elle* est notamment utilisée par le convertisseur générique de DOM en* IAST (eval/EASTParser).

20 */

public interface IEASTFactory <Exc extends Exception > {

/** Créer une séquence d’AST. */25 IASTsequence newSequence (List<IAST> asts);

/** Créer une alternative binaire. */IASTalternative newAlternative (IAST condition ,

IAST consequent);30

/** Créer une alternative ternaire. */IASTalternative newAlternative (IAST condition ,

66

Page 34:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

IAST consequent ,IAST alternant);

35

/** Créer un bloc local unaire (avec une seule variable locale). */IASTunaryBlock newUnaryBlock (IASTvariable variable ,

IAST initialisation ,IASTsequence body);

40

/** Créer une variable. */IASTvariable newVariable (String name);

/** Créer une invocation (un appel à une fonction). */45 IASTinvocation newInvocation (String name, List<IAST> asts);

/** Créer une opération unaire. */IASTunaryOperation newUnaryOperation (String operatorName ,

IAST operand);50 /** Créer une opération binaire. */

IASTbinaryOperation newBinaryOperation (String operatorName ,IAST leftOperand ,IAST rightOperand);

55 /** Créer une constante littérale entière. */IASTinteger newIntegerConstant (String value);

/** Créer une constante littérale flottante. */IASTfloat newFloatConstant (String value);

60

/** Créer une constante littérale chaîne de caractères. */IASTstring newStringConstant (String value);

/** Créer une constante littérale booléenne. */65 IASTboolean newBooleanConstant (String value);

/** Signaler un problème avec un message. */IAST throwParseException (String message) throws Exc;

70 /** Signaler un problème avec une exception. */IAST throwParseException (Throwable cause) throws Exc;

/* NOTA: on ne peut exprimer en Java que ces deux dernières méthodes* signalent toujours une exception et ne renvoient donc jamais une

75 * valeur. Comme on ne peut écrire ni:* factory.throwParseException("blabla");* [car alors la méthode englobante manque d’un return]* ni:* return factory.throwParseException("blabla");

80 * [car on ne peut renvoyer void]* je change le type de retour pour IAST. */

}

Java/src/fr/upmc/ilp/ilp1/cgen/CgenEnvironment.java

1 package fr.upmc.ilp.ilp1.cgen;

import java.util.*;

import fr.upmc.ilp.ilp1.interfaces.*;6

/** La représentation de l’environnement des opérateurs prédéfinis. Il* définit comment les compiler. C’est un peu l’analogue de* runtime/Common pour le paquetage cgen. */

11 public class CgenEnvironmentimplements ICgenEnvironment {

private static final Map<String,String> MAP_OP1 = new HashMap<String,String >();private static final Map<String,String> MAP_OP2 = new HashMap<String,String >();

16 static {// Binaires:MAP_OP2.put("+", "Plus");MAP_OP2.put("-", "Minus");MAP_OP2.put("*", "Times");

21 MAP_OP2.put("/", "Divide");MAP_OP2.put("%", "Modulo");MAP_OP2.put("<", "LessThan");MAP_OP2.put("<=", "LessThanOrEqual");MAP_OP2.put("==", "Equal");

67

26 MAP_OP2.put(">=", "GreaterThanOrEqual");MAP_OP2.put(">", "GreaterThan");MAP_OP2.put("!=", "NotEqual");// Unaires:MAP_OP1.put("-", "Opposite");

31 MAP_OP1.put("!", "Not");}

/** Comment convertir un opérateur unaire en C. */

36 @Overridepublic String compileOperator1 (final String opName)

throws CgenerationException {return compileOperator(opName, MAP_OP1);

}41

/** Comment convertir un opérateur binaire en C. */

@Overridepublic String compileOperator2 (final String opName)

46 throws CgenerationException {return compileOperator(opName, MAP_OP2);

}

/** Méthode interne pour trouver le nom en C d’un opérateur. */51

private String compileOperator (final String opName, Map<String,String> map)throws CgenerationException {final String cName = map.get(opName);if ( cName != null ) {

56 return "ILP_" + cName;} else {final String msg = "No such operator: " + opName;throw new CgenerationException(msg);

}61 }

/** Compiler une référence à une variable. */

@Override66 public IASTvariable generateVariable () {

CgenEnvironment.counter++;return CgenEnvironment.createVariable("TEMP" + CgenEnvironment.counter);

}private transient static int counter = 0;

71

private static IASTvariable createVariable (final String name) {return new IASTvariable () {

@Overridepublic String getName () {

76 return name;}

};}

81 /** Enrichir un environnement lexical avec les primitives* d’impression (print et newline). */

@Overridepublic ICgenLexicalEnvironment extendWithPrintPrimitives (

86 final ICgenLexicalEnvironment lexenv) {final ICgenLexicalEnvironment lexenv2 =

lexenv.extend(CgenEnvironment.createVariable("print"),"ILP_print");

final ICgenLexicalEnvironment lexenv3 =91 lexenv2.extend(CgenEnvironment.createVariable("newline"),

"ILP_newline");return lexenv3;

}

96 @Overridepublic ICgenLexicalEnvironment extendWithPredefinedConstants (

final ICgenLexicalEnvironment lexenv) {final ICgenLexicalEnvironment lexenv2 =

lexenv.extend(CgenEnvironment.createVariable("pi"),101 "ILP_PI");

return lexenv2;}

68

Page 35:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

}

Java/src/fr/upmc/ilp/ilp1/cgen/CgenLexicalEnvironment.java

package fr.upmc.ilp.ilp1.cgen;

import fr.upmc.ilp.ilp1.interfaces.*;4

/** La représentation des environnements lexicaux de compilation vers* C. C’est l’analogue de runtime/LexicalEnvironement pour le* paquetage cgen. */

9 public class CgenLexicalEnvironmentimplements ICgenLexicalEnvironment {

public CgenLexicalEnvironment (final IASTvariable variable,final String compiledName ,

14 final ICgenLexicalEnvironment next) {this.variableName = variable.getName();this.compiledName = compiledName;this.next = next;

}19 private final String variableName;

private final String compiledName;private final ICgenLexicalEnvironment next;

@Override24 public String compile (final IASTvariable variable)

throws CgenerationException {if ( variableName.equals(variable.getName()) ) {return compiledName;

} else {29 return next.compile(variable);

}}

@Override34 public ICgenLexicalEnvironment extend (final IASTvariable variable,

final String compiledName) {return new CgenLexicalEnvironment(variable , compiledName , this);

}

39 @Overridepublic ICgenLexicalEnvironment extend (final IASTvariable variable) {

return new CgenLexicalEnvironment(variable , variable.getName(), this);}

44 // Classe interne:public static class Emptyextends CgenLexicalEnvironment {

// La technique du singleton:49 private Empty () {

super(new IASTvariable() {@Override

public String getName() { return null; }}, null, null);

54 }private static final Empty

EMPTY_LEXICAL_ENVIRONMENT;static {

EMPTY_LEXICAL_ENVIRONMENT = new Empty();59 }

public static ICgenLexicalEnvironment create () {return Empty.EMPTY_LEXICAL_ENVIRONMENT;

}64

@Overridepublic String compile (final IASTvariable variable)throws CgenerationException {final String msg = "Variable inaccessible: " + variable.getName();

69 throw new CgenerationException(msg);}

}

}69

Java/src/fr/upmc/ilp/ilp1/cgen/CgenerationException.java

1 package fr.upmc.ilp.ilp1.cgen;

/** Les exceptions préférentiellement signalées par la conversion en C. */

public class CgenerationException extends Exception {6

static final long serialVersionUID = +1234567890004000L;

public CgenerationException (Throwable cause) {super(cause);

11 }

public CgenerationException (String message) {super(message);

}16

}

Java/src/fr/upmc/ilp/ilp1/cgen/Cgenerator.java

package fr.upmc.ilp.ilp1.cgen;2

import java.math.BigInteger;

import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.ilp1.interfaces.IASTalternative;

7 import fr.upmc.ilp.ilp1.interfaces.IASTbinaryOperation;import fr.upmc.ilp.ilp1.interfaces.IASTboolean;import fr.upmc.ilp.ilp1.interfaces.IASTconstant;import fr.upmc.ilp.ilp1.interfaces.IASTfloat;import fr.upmc.ilp.ilp1.interfaces.IASTinteger;

12 import fr.upmc.ilp.ilp1.interfaces.IASTinvocation;import fr.upmc.ilp.ilp1.interfaces.IASToperation;import fr.upmc.ilp.ilp1.interfaces.IASTsequence;import fr.upmc.ilp.ilp1.interfaces.IASTstring;import fr.upmc.ilp.ilp1.interfaces.IASTunaryBlock;

17 import fr.upmc.ilp.ilp1.interfaces.IASTunaryOperation;import fr.upmc.ilp.ilp1.interfaces.IASTvariable;

/** La génération vers C. */

22 public class Cgenerator {

public Cgenerator (final ICgenEnvironment common) {this.common = common;

}27 protected final ICgenEnvironment common;

/** Convertir un AST en une chaîne de caractères C. */

public String compile (final IAST iast,32 final ICgenLexicalEnvironment lexenv,

final String destination)throws CgenerationException {this.buffer = new StringBuffer(1024);buffer.append("/* Fichier compilé vers C */\n");

37 analyze(iast, lexenv, this.common, destination);final String result = this.buffer.toString();return result;

}protected transient StringBuffer buffer;

42

/** Convertir une expression en C. */

protected void analyzeExpression (final IAST iast,final ICgenLexicalEnvironment lexenv,

47 final ICgenEnvironment common)throws CgenerationException {analyze(iast, lexenv, common, "");

}

52 /** Convertir une instruction en C.** La destination est soit "" (ou "(void)" pour indiquer que la

70

Page 36:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

* valeur obtenue est inutile, soit "return" pour indiquer que c’est* la valeur finale d’une fonction ou encore "variable =" pour

57 * ranger la valeur obtenue dans une variable.*/

protected void analyzeInstruction (final IAST iast,final ICgenLexicalEnvironment lexenv,

62 final ICgenEnvironment common,final String destination)

throws CgenerationException {analyze(iast, lexenv, common, destination);

}67

/** Cette méthode analyse la nature de l’AST à traiter et détermine* la bonne méthode à appliquer. C’est un envoi de message simulé à* la main, l’ordre de discrimination n’est pas le plus efficace,* mais utilise les marqueurs d’interface pour regrouper certains

72 * tests. Le code spécifique aux divers cas se trouve dans les* méthodes generate() surchargées.*/

protected void analyze (final IAST iast,77 final ICgenLexicalEnvironment lexenv,

final ICgenEnvironment common,final String destination)

throws CgenerationException {if ( iast instanceof IASTconstant ) {

82 if ( iast instanceof IASTboolean ) {generate((IASTboolean) iast, lexenv, common, destination);

} else if ( iast instanceof IASTfloat ) {generate((IASTfloat) iast, lexenv, common, destination);

} else if ( iast instanceof IASTinteger ) {87 generate((IASTinteger) iast, lexenv, common, destination);

} else if ( iast instanceof IASTstring ) {generate((IASTstring) iast, lexenv, common, destination);

} else {final String msg = "Unknown type of constant: " + iast;

92 throw new CgenerationException(msg);}

} else if ( iast instanceof IASTalternative ) {generate((IASTalternative) iast, lexenv, common, destination);

} else if ( iast instanceof IASTinvocation ) {97 generate((IASTinvocation) iast, lexenv, common, destination);

} else if ( iast instanceof IASToperation ) {if ( iast instanceof IASTunaryOperation ) {

generate((IASTunaryOperation) iast, lexenv, common, destination);} else if ( iast instanceof IASTbinaryOperation ) {

102 generate((IASTbinaryOperation) iast, lexenv, common, destination);} else {final String msg = "Unknown type of operation: " + iast;throw new CgenerationException(msg);

}107 } else if ( iast instanceof IASTsequence ) {

generate((IASTsequence) iast, lexenv, common, destination);} else if ( iast instanceof IASTunaryBlock ) {

generate((IASTunaryBlock) iast, lexenv, common, destination);} else if ( iast instanceof IASTvariable ) {

112 generate((IASTvariable) iast, lexenv, common, destination);} else {final String msg = "Unknown type of AST: " + iast;throw new CgenerationException(msg);

}117 }

/** Toutes les méthodes qui suivent remplissent le tampon courant* (buffer). Il y a une méthode generate par catégorie* syntaxique. */

122

protected void generate (final IASTalternative iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,final String destination)

127 throws CgenerationException {buffer.append(" if ( ILP_isEquivalentToTrue( ");analyzeExpression(iast.getCondition(), lexenv, common);buffer.append(" ) ) {\n");analyzeInstruction(iast.getConsequent(), lexenv, common, destination);

132 buffer.append(";\n}");71

if ( iast.isTernary() ) {buffer.append(" else {\n");try {

analyzeInstruction(iast.getAlternant(), lexenv, common, destination);137 buffer.append(";");

} catch (Exception e) {final String msg = "Should never occur!";assert false : msg;throw new CgenerationException(msg);

142 }buffer.append("\n}");

} else {buffer.append(" else {\n");buffer.append(destination);

147 buffer.append(" ILP_FALSE;");buffer.append("\n}");

}}

152 protected void generate (final IASTbinaryOperation iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,final String destination)

throws CgenerationException {157 buffer.append(destination);

buffer.append(" ");buffer.append(common.compileOperator2(iast.getOperatorName()));buffer.append("(");analyzeExpression(iast.getLeftOperand(), lexenv, common);

162 buffer.append(", ");analyzeExpression(iast.getRightOperand(), lexenv, common);buffer.append(") ");

}

167 protected void generate (final IASTboolean iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,final String destination)

throws CgenerationException {172 buffer.append(destination);

if ( iast.getValue() ) {buffer.append(" ILP_TRUE ");

} else {buffer.append(" ILP_FALSE ");

177 }}

protected void generate (final IASTfloat iast,final ICgenLexicalEnvironment lexenv,

182 final ICgenEnvironment common,final String destination)

throws CgenerationException {buffer.append(destination);buffer.append(" ILP_Float2ILP(");

187 buffer.append(iast.getValue());buffer.append(") ");

}

protected void generate (final IASTinteger iast,192 final ICgenLexicalEnvironment lexenv,

final ICgenEnvironment common,final String destination)

throws CgenerationException {final BigInteger bi = iast.getValue();

197 // && et non || comme l’a remarqué [email protected] ( bi.compareTo(BIMIN) > 0

&& bi.compareTo(BIMAX) < 0 ) {buffer.append(destination);buffer.append(" ILP_Integer2ILP(");

202 buffer.append(bi.intValue());buffer.append(") ");

} else {final String msg = "Too large integer " + bi;throw new CgenerationException(msg);

207 }}public static final BigInteger BIMIN;public static final BigInteger BIMAX;

72

Page 37:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

static {212 final Integer i = Integer.MIN_VALUE;

BIMIN = new BigInteger(i.toString());final Integer j = Integer.MAX_VALUE;BIMAX = new BigInteger(j.toString());

}217

protected void generate (final IASTinvocation iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,final String destination)

222 throws CgenerationException {buffer.append(destination);buffer.append(" ");analyzeExpression(iast.getFunction(), lexenv, common);buffer.append("(");

227 final int numberOfArguments = iast.getArgumentsLength();for ( int i=0 ; i<numberOfArguments ; i++ ) {

IAST iast2 = null;try {

iast2 = iast.getArgument(i);232 } catch (Exception e) {

final String msg = "Should never occur!";assert false : msg;throw new CgenerationException(msg);

}237 analyzeExpression(iast2, lexenv, common);

if ( i<numberOfArguments -1 ) {buffer.append(", ");

}}

242 buffer.append(")");}

protected void generate (final IASTsequence iast,final ICgenLexicalEnvironment lexenv,

247 final ICgenEnvironment common,final String destination)

throws CgenerationException {buffer.append("{\n");final IAST[] instrs = iast.getInstructions();

252 for ( int i = 0 ; i < instrs.length -1 ; i ++) {final IAST iast2 = instrs[i];analyzeInstruction(iast2, lexenv, common, "(void)");buffer.append(";\n");

}257 analyzeInstruction(instrs[instrs.length -1], lexenv, common, destination);

buffer.append(";\n}\n");}

protected void generate (final IASTstring iast,262 final ICgenLexicalEnvironment lexenv,

final ICgenEnvironment common,final String destination)

throws CgenerationException {buffer.append(destination);

267 buffer.append(" ILP_String2ILP(\"");final String s = iast.getValue();final int n = s.length();for ( int i = 0 ; i<n ; i++ ) {char c = s.charAt(i);

272 switch ( c ) {case ’\\’:case ’"’: {

buffer.append("\\");}

277 //$FALL-THROUGH$default: {

buffer.append(c);}}

282 }buffer.append("\") ");

}

protected void generate (final IASTunaryBlock iast,287 final ICgenLexicalEnvironment lexenv,

73

final ICgenEnvironment common,final String destination)

throws CgenerationException {final IASTvariable tmp = common.generateVariable();

292 final ICgenLexicalEnvironment lexenv2 =lexenv.extend(tmp, tmp.getName());

final ICgenLexicalEnvironment lexenv3 =lexenv2.extend(iast.getVariable());

297 buffer.append("{\n");buffer.append(" ILP_Object ");analyzeExpression(tmp, lexenv2, common);buffer.append(" = ");analyzeExpression(iast.getInitialization(), lexenv, common);

302 buffer.append(";\n");

buffer.append(" ILP_Object ");analyzeExpression(iast.getVariable(), lexenv3, common);buffer.append(" = ");

307 analyzeExpression(tmp, lexenv2, common);buffer.append(";\n");

analyzeInstruction(iast.getBody(), lexenv3, common, destination);buffer.append("}\n");

312 }

protected void generate (final IASTunaryOperation iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,

317 final String destination)throws CgenerationException {buffer.append(destination);buffer.append(" ");buffer.append(common.compileOperator1(iast.getOperatorName()));

322 buffer.append("(");analyzeExpression(iast.getOperand(), lexenv, common);buffer.append(") ");

}

327 protected void generate (final IASTvariable iast,final ICgenLexicalEnvironment lexenv,final ICgenEnvironment common,final String destination)

throws CgenerationException {332 buffer.append(destination);

buffer.append(" ");buffer.append(lexenv.compile(iast));buffer.append(" ");

}337

}

Java/src/fr/upmc/ilp/ilp1/cgen/CgeneratorTest.java

1 package fr.upmc.ilp.ilp1.cgen;

import java.io.File;import java.io.FilenameFilter;import java.io.IOException;

6 import java.util.List;import java.util.Vector;import java.util.regex.Matcher;import java.util.regex.Pattern;

11 import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;

import junit.framework.TestCase;16

import org.w3c.dom.Document;import org.xml.sax.SAXException;

import fr.upmc.ilp.ilp1.eval.EAST;21 import fr.upmc.ilp.ilp1.eval.EASTException;import fr.upmc.ilp.ilp1.eval.EASTFactory;import fr.upmc.ilp.ilp1.eval.EASTParser;import fr.upmc.ilp.ilp1.eval.EASTentier;

74

Page 38:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

import fr.upmc.ilp.ilp1.eval.EASTsequence;26 import fr.upmc.ilp.ilp1.interfaces.IAST;import fr.upmc.ilp.tool.FileTool;import fr.upmc.ilp.tool.ProgramCaller;

/** Tests (JUnit) pour la compilation vers C. Il faut etre dans le repertoire31 * qui contient Grammars et Java afin que ce code puisse trouver les fichiers

* de test a compiler. */

public class CgeneratorTest extends TestCase {

36 @Overridepublic void setUp () {final ICgenEnvironment common = new CgenEnvironment();compiler = new Cgenerator(common);factory = new EASTFactory();

41 lexenv = CgenLexicalEnvironment.Empty.create();lexenv = common.extendWithPrintPrimitives(lexenv);lexenv = common.extendWithPredefinedConstants(lexenv);

}private Cgenerator compiler;

46 private EASTFactory factory;private ICgenLexicalEnvironment lexenv;

/** Verifier que l’on ne peut compiler en C un tres grand entier. */

51 public void testBigInteger1 () {final List<IAST> args = new Vector<IAST >();args.add(new EASTentier("12345678909876543210123456789"));args.add(new EASTentier("1"));final EAST east = new EASTsequence(args);

56 // Compiler vers Ctry {

compiler.compile(east, lexenv, "return");} catch ( CgenerationException e) {

assertTrue(true);61 }

}

// La detection des grands entiers non compilable etait erronee// comme l’a remarqué [email protected]. Il faut donc tester

66 // aussi les grands entiers negatifs.

public void testBigInteger2 () {final List<IAST> args = new Vector<IAST >();args.add(new EASTentier(" -12345678909876543210123456789"));

71 args.add(new EASTentier("1"));final EAST east = new EASTsequence(args);// Compiler vers Ctry {

compiler.compile(east, lexenv, "return");76 } catch ( CgenerationException e) {

assertTrue(true);}

}/** Les caractéristiques des programmes XML à tester: */

81

private final File directory = new File("Grammars" + File.separator + "Samples" + File.separator );

private final Pattern p = Pattern.compile("^u\\d+-1.xml$");private final Pattern pfull =

86 Pattern.compile("(.*" + File.separator + "u\\d+-1).xml$");

/** Tester un programme c’est-à-dire le lire depuis XML, le* convertir en un EAST, le compiler en C, compiler ce code C avec* un patron standard et comparer le résultat avec ce qui était

91 * attendu. */

protected void handleFile (String basefilename)throws IOException , ParserConfigurationException , SAXException ,

EASTException , CgenerationException {96 // Imprimer le fichier scheme ?

File xmlFile = new File(basefilename + ".xml");DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();Document d = db.parse(xmlFile);

101 EASTParser parser = new EASTParser(factory);EAST east = (EAST) parser.parse(d);// Compiler vers CString ccode = compiler.compile(east, lexenv, "return");

75

FileTool.stuffFile(basefilename + ".c", ccode);106 // appeler indent, FUTURE

String program = "bash "+ "C/compileThenRun.sh "+ basefilename + ".c";

ProgramCaller pc = new ProgramCaller(program);111 pc.setVerbose();

pc.run();String expectedResult = FileTool.readExpectedResult(basefilename);String expectedPrinting = FileTool.readExpectedPrinting(basefilename);assertEquals(expectedPrinting + expectedResult , pc.getStdout().trim());

116 }

/** Rechercher tous les fichiers u*-1.xml et les tester. */

public void testUFiles ()121 throws IOException , ParserConfigurationException , SAXException ,

EASTException , CgenerationException {FilenameFilter ff = new FilenameFilter() {

@Overridepublic boolean accept (File dir, String name) {

126 final Matcher m = p.matcher(name);return m.matches();

}};

final File[] testFiles = directory.listFiles(ff);131 // Si cette assertion est fausse, on n’est probablement pas dans le

// bon repertoire.assertNotNull(testFiles);// Au moins 38 programmes de test:assertTrue(testFiles.length >= 38);

136 // Trier les noms de fichiers en place:java.util.Arrays.sort(testFiles , new java.util.Comparator <File>() {

@Overridepublic int compare (File f1, File f2) {return f1.getName().compareTo(f2.getName());

141 }@Overridepublic boolean equals (Object comparator) {return false;

}146 });

for ( int i = 0 ; i<testFiles.length ; i++ ) {final String filename = testFiles[i].getPath();System.err.println("Testing " + filename);final Matcher m = pfull.matcher(filename);

151 assertTrue(m.matches());handleFile(m.group(1));

}}

156 }

Java/src/fr/upmc/ilp/ilp1/cgen/ICgenEnvironment.java

package fr.upmc.ilp.ilp1.cgen;

3 import fr.upmc.ilp.ilp1.interfaces.*;

/** L’interface décrivant l’environnement des opérateurs prédéfinis du* langage à compiler vers C. Il est l’analogue de runtime/ICommon* pour le paquetage cgen. */

8

public interface ICgenEnvironment {

/** Comment convertir un opérateur unaire en C. */

13 String compileOperator1 (String opName)throws CgenerationException ;

/** Comment convertir un opérateur binaire en C. */

18 String compileOperator2 (String opName)throws CgenerationException ;

/** un générateur de variables temporaires. */

23 IASTvariable generateVariable ();76

Page 39:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** L’enrichisseur d’environnement lexical avec les primitives. */

ICgenLexicalEnvironment28 extendWithPrintPrimitives (ICgenLexicalEnvironment lexenv);

/** L’enrichisseur d’environnement lexical avec les constantes. */

ICgenLexicalEnvironment33 extendWithPredefinedConstants (ICgenLexicalEnvironment lexenv);

}

Java/src/fr/upmc/ilp/ilp1/cgen/ICgenLexicalEnvironment.java

package fr.upmc.ilp.ilp1.cgen;

import fr.upmc.ilp.ilp1.interfaces.*;4

/** L’interface décrivant l’environnement lexical de compilation vers* C. Il est l’analogue de runtime/ILexicalEnvironment pour le* paquetage cgen. */

9 public interface ICgenLexicalEnvironment {

/** Renvoie le code compilé d’accès à cette variable.** @throws CgenerationException si la variable est absente.

14 */

String compile (IASTvariable variable)throws CgenerationException;

19 /** Étend l’environnement avec une nouvelle variable et vers quel* nom la compiler. */

ICgenLexicalEnvironment extend (IASTvariable variable ,String compiledName );

24

/** Étend l’environnement avec une nouvelle variable qui sera* compilée par son propre nom. */

ICgenLexicalEnvironment extend (IASTvariable variable);29

}

Java/src/fr/upmc/ilp/ilp1/CoverageTest.java

package fr.upmc.ilp.ilp1;

import org.hansel.CoverageRunner;4 import org.junit.runner.RunWith;import org.junit.runners.Suite;

/** La mode est aux annotations!* La classe n’a plus de corps seulement des annotations indiquant

9 * comment construire une instance et agir.* Cette suite de tests realise egalement des tests de couverture* a l’aide d’Hansel @see{http://hansel.sourceforge.net/}.** Attention , pour tourner ce test, il faut passer les options

14 * <code>-javaagent hansel.jar</code> a la JVM sous-jacente.*/

@RunWith(CoverageRunner.class)@Suite.SuiteClasses({

19 fr.upmc.ilp.ilp1.eval.EASTFileTest.class,fr.upmc.ilp.ilp1.cgen.CgeneratorTest.class

})@CoverageRunner.CoverClasses({

fr.upmc.ilp.ilp1.eval.EAST.class,24 fr.upmc.ilp.ilp1.eval.EASTalternative.class,

fr.upmc.ilp.ilp1.eval.EASTblocUnaire.class,fr.upmc.ilp.ilp1.eval.EASTbooleen.class,fr.upmc.ilp.ilp1.eval.EASTchaine.class,fr.upmc.ilp.ilp1.eval.EASTConstant.class,

77

29 fr.upmc.ilp.ilp1.eval.EASTentier.class,fr.upmc.ilp.ilp1.eval.EASTException.class,fr.upmc.ilp.ilp1.eval.EASTFactory.class,fr.upmc.ilp.ilp1.eval.EASTflottant.class,fr.upmc.ilp.ilp1.eval.EASTinvocation.class,

34 fr.upmc.ilp.ilp1.eval.EASTinvocationPrimitive.class,fr.upmc.ilp.ilp1.eval.EASToperation.class,fr.upmc.ilp.ilp1.eval.EASToperationBinaire.class,fr.upmc.ilp.ilp1.eval.EASToperationUnaire.class,fr.upmc.ilp.ilp1.eval.EASTParser.class,

39 fr.upmc.ilp.ilp1.eval.EASTsequence.class,fr.upmc.ilp.ilp1.eval.EASTvariable.class,fr.upmc.ilp.ilp1.eval.EASTFactory.class,

})public class CoverageTest {}

Java/src/fr/upmc/ilp/ilp1/JDependTest.java

1 package fr.upmc.ilp.ilp1;

public class JDependTest {// FUTURE: verifier les dependances entre paquetages d’ilp1.

}6

// end of JDependTest.java

Java/src/fr/upmc/ilp/ilp1/Process.java

package fr.upmc.ilp.ilp1;

3 import java.io.IOException;

import org.w3c.dom.Document;

import fr.upmc.ilp.ilp1.cgen.CgenEnvironment;8 import fr.upmc.ilp.ilp1.cgen.CgenLexicalEnvironment.Empty;import fr.upmc.ilp.ilp1.cgen.Cgenerator;import fr.upmc.ilp.ilp1.cgen.ICgenEnvironment;import fr.upmc.ilp.ilp1.cgen.ICgenLexicalEnvironment;import fr.upmc.ilp.ilp1.eval.EAST;

13 import fr.upmc.ilp.ilp1.eval.EASTFactory;import fr.upmc.ilp.ilp1.eval.EASTParser;import fr.upmc.ilp.ilp1.runtime.CommonPlus;import fr.upmc.ilp.ilp1.runtime.ConstantsStuff;import fr.upmc.ilp.ilp1.runtime.EmptyLexicalEnvironment;

18 import fr.upmc.ilp.ilp1.runtime.ICommon;import fr.upmc.ilp.ilp1.runtime.ILexicalEnvironment;import fr.upmc.ilp.ilp1.runtime.PrintStuff;import fr.upmc.ilp.tool.AbstractProcess;import fr.upmc.ilp.tool.FileTool;

23 import fr.upmc.ilp.tool.IFinder;import fr.upmc.ilp.tool.ProgramCaller;

/** Cette classe précise comment est traité un programme d’ILP1. */

28 public class Process extends AbstractProcess {

public Process (IFinder finder) throws IOException {super(finder);

}33

/** Initialisation: @see fr.upmc.ilp.tool.AbstractProcess. */

/** Préparation. On analyse syntaxiquement le texte du programme ,* on effectue quelques analyses et on l’amène à un état où il

38 * pourra être interprété ou compilé. Toutes les analyses communes* à ces deux fins sont partagées ici.*/

@Override43 public void prepare() {

try {assert this.rngFile != null;final Document d = getDocument(this.rngFile);

48 final EASTFactory factory = new EASTFactory();78

Page 40:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

final EASTParser parser = new EASTParser(factory);this.east = (EAST) parser.parse(d);setIAST(this.east);

53 this.prepared = true;

} catch (Throwable e) {this.preparationFailure = e;if ( this.verbose ) {

58 System.err.println(e);}

}}protected EAST east; // Hack car IAST insuffisant pour eval().

63

/** Interprétation */

@Overridepublic void interpret() {

68 try {assert this.prepared;final ICommon intcommon = new CommonPlus();ILexicalEnvironment intlexenv = EmptyLexicalEnvironment.create();final PrintStuff intps = new PrintStuff();

73 intlexenv = intps.extendWithPrintPrimitives(intlexenv);final ConstantsStuff intcs = new ConstantsStuff();intlexenv = intcs.extendWithPredefinedConstants(intlexenv);

this.result = this.east.eval(intlexenv , intcommon);78 this.printing = intps.getPrintedOutput().trim();

this.interpreted = true;

} catch (Throwable e) {83 this.interpretationFailure = e;

if ( this.verbose ) {System.err.println(e);

}}

88 }

/** Compilation vers C. */

@Override93 public void compile() {

try {assert this.prepared;final ICgenEnvironment common = new CgenEnvironment();final Cgenerator compiler = new Cgenerator(common);

98 ICgenLexicalEnvironment lexenv = Empty.create();lexenv = common.extendWithPrintPrimitives(lexenv);lexenv = common.extendWithPredefinedConstants(lexenv);this.ccode = compiler.compile(this.east, lexenv, "return");

103 this.compiled = true;

} catch (Throwable e) {this.compilationFailure = e;if ( this.verbose ) {

108 System.err.println(e);}

}}

113 /** Exécution du programme compilé: */

@Overridepublic void runCompiled() {

try {118 assert this.compiled;

assert this.cFile != null;assert this.compileThenRunScript != null;FileTool.stuffFile(this.cFile, ccode);

123 // et le compiler:String program = "bash "

+ this.compileThenRunScript.getAbsolutePath() + " "+ this.cFile.getAbsolutePath();

79

ProgramCaller pc = new ProgramCaller(program);128 pc.setVerbose();

pc.run();this.executionPrinting = pc.getStdout().trim();

this.executed = ( pc.getExitValue() == 0 );133

} catch (Throwable e) {this.executionFailure = e;if ( this.verbose ) {

System.err.println(e);138 }

}}

}

Java/src/fr/upmc/ilp/ilp1/ProcessTest.java

package fr.upmc.ilp.ilp1;2

import java.io.IOException;

import org.junit.Before;

7 import fr.upmc.ilp.tool.AbstractProcessTest;import fr.upmc.ilp.tool.File;

/** Cette classe de test utilise JUnit4 ainsi qu’une extension permettant de* donner (fr.upmc.ilp.tool.Parameterized) de jolis noms aux divers tests.

12 ** NOTA: l’annotation RunWith sera héritée par les sous-classes.*/

public class ProcessTest extends AbstractProcessTest {17

/** Le constructeur du test sur un fichier. */

public ProcessTest (final File file) {super(file);

22 }

/*** Cette méthode initialise le Process à tester avec des valeurs par* défaut. Comme cette méthode est appelée après le constructeur , elle

27 * ne doit pas modifier les valeurs définies par le constructeur (notamment* la grammaire ou le patron).* @throws IOException*/

@Before32 public void setUp () throws IOException {

this.setProcess(new Process(finder));getProcess().setVerbose(options.verbose);getProcess().setGrammar(grammarFile);getProcess().setCFile(cFile);

37 getProcess().setCTemplateFile(cTemplateFile);getProcess().setCompileThenRunScript(scriptFile);

}

// La méthode effective de test est héritée d’AbstractProcessTest42 }

Java/src/fr/upmc/ilp/ilp1/WholeTestSuite.java

package fr.upmc.ilp.ilp1;

3 import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;

/** Regroupement de classes de tests d’evaluation et de compilation. */8

@RunWith(value=Suite.class)@SuiteClasses(value={

// ajout des tests de fabrication d’AST:fr.upmc.ilp.ilp1.fromxml.ASTParserTest.class,

80

Page 41:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

13 // ajout des tests d’evaluation:fr.upmc.ilp.ilp1.eval.EASTTest.class,fr.upmc.ilp.ilp1.eval.EASTPrimitiveTest.class,fr.upmc.ilp.ilp1.eval.EASTFileTest.class,// ajout des tests de compilation:

18 fr.upmc.ilp.ilp1.cgen.CgeneratorTest.class,// Un test de couverture://fr.upmc.ilp.ilp1.CoverageTest.class,// Et enfin tous les fichiers de tests un par un:fr.upmc.ilp.ilp1.ProcessTest.class

23 })public class WholeTestSuite {}

Java/src/fr/upmc/ilp/tool/AbstractEnvironment.java

package fr.upmc.ilp.tool;

/**5 * Une classe utilitaire pour les environnements: c’est une fonction

* des variables vers les valeurs representee par une liste chainee.** @param <V> la classe des variables* @param <W> la classe des valeurs

10 */

public abstract class AbstractEnvironment <V, W> {

public AbstractEnvironment(V variable, W value, AbstractEnvironment <V, W> next) {15 this.variable = variable;

this.value = value;this.next = next;

}private final V variable;

20 private W value;private final AbstractEnvironment <V, W> next;

public V getVariable () {return this.variable;

25 }public W getValue () {

return this.value;}public AbstractEnvironment <V, W> getNextEnvironment () {

30 return this.next;}

public W setValue (W newValue) {W oldValue = this.value;

35 this.value = newValue;return oldValue;

}

/** Renvoie la valeur d’une variable si prà c©sente dans40 * l’environnement. */

public W lookup (V variable) {// NOTA: la comparaison s’effectue par equals():if (this.variable.equals(variable)) {

return this.value;45 } else {

return this.next.lookup(variable);}

}

50 }

// fin d’AbstractEnvironment.java

Java/src/fr/upmc/ilp/tool/AbstractProcess.java

package fr.upmc.ilp.tool;2

//import javax.inject.Inject; // Utiliser Guice

81

import java.io.IOException;import java.io.StringReader;

7

import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;

12 import org.w3c.dom.Document;import org.xml.sax.InputSource;import org.xml.sax.SAXException;

import com.thaiopensource.validate.ValidationDriver;17

import fr.upmc.ilp.annotation.OrNull;import fr.upmc.ilp.ilp1.interfaces.IAST;

/** Cette classe abstraite est une implantation de IProcess avec quelques22 * methodes probablement utiles si l’on en herite. */

public abstract class AbstractProcessimplements IProcess {

27 protected AbstractProcess (IFinder finder) throws IOException {setFinder(finder);// Pour trouver les grammaires et les patrons par défaut:getFinder().addPossiblePath("Grammars");getFinder().addPossiblePath("C");

32 }

public void setVerbose (boolean verbose) {this.verbose = verbose;

}37 /** Ce booleen rend Process verbeux! */

protected boolean verbose = true;

/** Definir où chercher tous les fichiers nécessaires. */public void setFinder (IFinder finder) {

42 this.finder = finder;}public IFinder getFinder () {

assert(this.finder != null);return this.finder;

47 }//@Injectprivate IFinder finder;

/** Initialisation: On se contente de recuperer le texte du programme52 * dont on va s’occuper.

*/

public void initialize (IContent ic) {try {

57 this.programText = ic.getContent();this.initialized = true;

} catch (Throwable e) {this.initializationFailure = e;if ( this.verbose ) {

62 System.err.print(e);}

}}

67 public boolean isInitialized() {return this.initialized;

}

public @OrNull Throwable getInitializationFailure() {72 return this.initializationFailure;

}

public @OrNull String getProgramText() {assert this.initialized;

77 return this.programText;}

protected boolean initialized = false;protected Throwable initializationFailure = null;

82 protected String programText;

82

Page 42:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** Preparation */

public boolean isPrepared() {87 return this.prepared;

}protected boolean prepared = false;

public @OrNull Throwable getPreparationFailure() {92 return this.preparationFailure;

}protected Throwable preparationFailure = null;

public @OrNull IAST getIAST() {97 assert this.prepared;

return this.iast;}public void setIAST(IAST iast) {

this.iast = iast;102 }

//@Injectprotected IAST iast;

/** Un utilitaire pour la preparation.107 * Étant donné le nom d’une grammaire , il charge la grammaire et

* valide le texte du programme à traiter. */public Document getDocument (String rngBaseName)

throws IOException , SAXException , ParserConfigurationException {final java.io.File rngFile = getFinder().findFile(rngBaseName);

112 return getDocument(rngFile);}

public Document getDocument (java.io.File rngFile)throws IOException , SAXException , ParserConfigurationException {

117 final String rngFilePath = rngFile.getAbsolutePath();final InputSource isg = ValidationDriver.fileInputSource(rngFilePath);final ValidationDriver vd = new ValidationDriver();vd.loadSchema(isg);InputSource is =

122 new org.xml.sax.InputSource(new StringReader(this.programText));

// Manquait (comme signalé par [email protected]):if ( ! vd.validate(is) ) {

throw new SAXException("Invalid XML program!");127 }

final DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();

final DocumentBuilder db = dbf.newDocumentBuilder();132 // Le precedent flux est tari!

is = new org.xml.sax.InputSource(new StringReader(this.programText));

this.document = db.parse(is);return this.document;

137 }/** getDocument() sans argument retourne le DOM. */public Document getDocument () {

assert this.document != null;return this.document;

142 }private Document document = null;

/** Definir la grammaire a utiliser pour comprendre le programme XML */public void setGrammar (java.io.File rngFile) {

147 this.rngFile = rngFile;}/** Le fichier contenant la grammaire d’ILP a utiliser: *///@Injectprotected java.io.File rngFile;

152

/** Interpretation */

public boolean isInterpreted() {return this.interpreted;

157 }protected boolean interpreted = false;

public @OrNull Throwable getInterpretationFailure() {

83

return this.interpretationFailure;162 }

protected Throwable interpretationFailure = null;

public String getInterpretationPrinting() {assert(this.interpreted);

167 return this.printing;}protected String printing = "";

public Object getInterpretationValue() {172 assert(this.interpreted);

return this.result;}protected Object result = null;

177 /** Compilation vers C. */

public boolean isCompiled() {return this.compiled;

}182 protected boolean compiled = false;

public @OrNull Throwable getCompilationFailure() {return this.compilationFailure;

}187 protected Throwable compilationFailure = null;

public String getCompiledProgram() {assert(this.compiled);return this.ccode;

192 }protected String ccode;

/** Exécution du programme compilé: */

197 /** Set the name of the C file to generate. */public void setCFile (java.io.File cFile) {

this.cFile = cFile;}/** Le nom du fichier C qui sera engendré: */

202 //@Injectprotected java.io.File cFile;/** Set the name of the C template. */public void setCTemplateFile (java.io.File templateFile) {

this.templateFile= templateFile;207 }

/** Le nom du patron C à utiliser: *///@Injectprotected java.io.File templateFile;/** Le nom du script compilant et executant le programme C engendré: */

212 //@Injectprotected java.io.File compileThenRunScript;public void setCompileThenRunScript (java.io.File scriptFile) {

this.compileThenRunScript = scriptFile;}

217

public @OrNull Throwable getExecutionFailure() {return this.executionFailure;

}protected Throwable executionFailure = null;

222

public String getExecutionPrinting() {assert(this.executed);return this.executionPrinting;

}227 protected String executionPrinting;

public boolean isExecuted() {return this.executed;

}232 protected boolean executed = false;

}

Java/src/fr/upmc/ilp/tool/AbstractProcessTest.java

84

Page 43:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

package fr.upmc.ilp.tool;2

import static junit.framework.Assert.assertEquals;import static junit.framework.Assert.assertTrue;

import java.io.FilenameFilter;7 import java.io.IOException;import java.util.ArrayList;import java.util.Collection;import java.util.List;import java.util.Vector;

12 import java.util.regex.Matcher;import java.util.regex.Pattern;

import org.junit.Test;import org.junit.runner.Result;

17 import org.junit.runner.RunWith;

import com.beust.jcommander.JCommander;import com.beust.jcommander.Parameter;

22 import fr.upmc.ilp.tool.Parameterized.Parameters;

/** Cette classe de test utilise JUnit4 ainsi qu’une extension permettant de* donner (fr.upmc.ilp.tool.Parameterized) de jolis noms aux divers tests.* Elle concentre l’essentiel des methodes statiques qui permettent de tester

27 * l’interprete et le compilateur sur une serie de fichiers specifies par un* repertoire et une expression rationnelle. Elle est generique sur la classe* implantant IProcess a tester.*/

32 @RunWith(Parameterized.class)public abstract class AbstractProcessTest {

/** Le process à tester. */protected IProcess process;

37

/**Initialiser le repertoire et l’expression rationnelle indiquantou trouver les programmes ILP a tester.

*/42 public static void staticSetUp (java.io.File theDirectory ,

String thePattern ) {directory = theDirectory;pattern = thePattern;

}47 // Ces deux methodes pourraient être pratiques ?

//public static void staticSetUp (java.io.File theDirectory) {// directory = theDirectory;//}//public static void staticSetUp (String thePattern) {

52 // pattern = thePattern;//}

/** Le répertoire où trouver les exemples de programmes ILP à traiter.57 * C’est usuellement le répertoire Grammars/Samples. */

protected static java.io.File directory;/** Le motif (une regexp) indiquant les programmes ILP à traiter. */protected static String pattern;

62 /** Chercher tous les programmes à tester.** Comme c’est calculé au chargement de la classe, ce calcul doit être* statique afin de pouvoir instancier la classe avec chaque fichier* à tester. */

67

public static Collection <File[]> collectData() throws Exception {final Pattern p = Pattern.compile("^" + pattern + ".xml$");final FilenameFilter ff = new FilenameFilter() {

public boolean accept (java.io.File dir, String name) {72 final Matcher m = p.matcher(name);

return m.matches();}

};final java.io.File[] testFiles = directory.listFiles(ff);

77

// Vérifier qu’il y a au moins un programme à tester sinon on pourrait// avoir l’erreur bête que tout marche puisqu’aucune erreur n’a été vue!if ( testFiles.length == 0 ) {

final String msg = "ILP: Cannot find a single test like " + pattern;85

82 throw new RuntimeException(msg);}

// Trier les noms de fichiers en place:java.util.Arrays.sort(testFiles ,

87 new java.util.Comparator <java.io.File>() {public int compare (java.io.File f1, java.io.File f2) {

return f1.getName().compareTo(f2.getName());}@Override

92 public boolean equals (Object comparator) {return false;

}});

97 Collection <File[]> result = new Vector<File[]>();for ( final java.io.File f : testFiles ) {

result.add(new File[] { new File(f) });}return result;

102 }

/** Le constructeur d’un test concernant un programme ILP à tester. */107 //public AbstractProcessTest () {}

public AbstractProcessTest (final File file) {this.file = file;

}public void setFile (File file) {

112 this.file = file;}public IProcess getProcess () {

return this.process;}

117 public void setProcess (IProcess process) {this.process = process;

}// C’est un fichier avec un nom relatif comme "Grammars/Samples/u01-1.xml"// Attention , c’est un fr.upmc.ilp.tool1.File et non un java.io.File!

122 protected File file;

/** Tester le programme ILP. */

@Test //(timeout=5000)127 public void handleFile ()

throws Exception {System.err.println("Testing " + this.file.getAbsolutePath() + " ...");

final fr.upmc.ilp.tool.File xmlFile =132 new fr.upmc.ilp.tool.File(this.file);

assertTrue(xmlFile.exists());

this.getProcess().initialize(xmlFile);// Si erreur, voir this.process.initializationFailure

137 assertTrue(this.getProcess().isInitialized());

this.getProcess().prepare();// Si erreur, voir this.process.preparationFailureassertTrue(this.getProcess().isPrepared());

142

// Ces verifications sont individualisees dans des methodes pour// etre ainsi sous-classees au cas où.

prepareComparison();147

interpretFile();

compileFile();}

152

/** Preparation de l’examen des resultats.* Chercher les resultats attendus (pour interprete et compilateur). */public void prepareComparison () throws IOException {

expectedResult = FileTool.readExpectedResult(this.file);157 expectedPrinting = FileTool.readExpectedPrinting(this.file);

compareDouble = false;fExpectedResult = 0.0;

}86

Page 44:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

protected String expectedResult;162 protected String expectedPrinting;

protected boolean compareDouble = false;protected double fExpectedResult = 0.0;

/** Test de l’interprete */167 public void interpretFile () throws Exception {

this.process.interpret();// Si erreur, voir this.process.interpretationFailureassertTrue(this.process.isInterpreted());final Object result = this.process.getInterpretationValue();

172 if ( result instanceof Double ) {fExpectedResult = Double.parseDouble(expectedResult);assertEquals(fExpectedResult , (Double)result, 0.1);compareDouble = true;

} else {177 assertEquals(expectedResult , result.toString());

}String printing = this.process.getInterpretationPrinting();assertEquals(expectedPrinting , printing);

}182

/** Test du compilateur */public void compileFile () throws Exception {

this.process.compile();// Si erreur, voir this.process.compilationFailure

187 assertTrue(this.process.isCompiled());this.process.runCompiled();// Si erreur, voir this.process.executionFailureassertTrue(this.process.isExecuted());String printing = this.process.getExecutionPrinting();

192 if ( compareDouble ) {// On assume que rien d’autre n’est imprimé que le doubledouble fPrinting = Double.parseDouble(printing.trim());assertEquals(fExpectedResult , fPrinting , 0.1);

} else {197 // On retire les retours a la ligne internes

printing = printing.replaceAll("\n", "");String expected = expectedPrinting + expectedResult;expected = expected.replaceAll("\n", "");assertEquals(expected.trim(), printing.trim());

202 }}

/** Teste une serie de programmes ILP. Chaque fichier est testé avec* la meme instance de ProcessTest. Attention , ne pas oublier d’indiquer

207 * le Process a utiliser avec setProcess(). */

public boolean handleFiles (String[] fileNames) {try {

for ( String fileName : fileNames ) {212 this.setFile(new File(fileName));

this.handleFile();}return true;

} catch (Throwable t) {217 return false;

}}

/**222 * Cette méthode peut être raffinée si l’on souhaite restreindre

* les fichiers à tester. */

@Parameterspublic static Collection <File[]> data() throws Exception {

227 initializeFromOptions();AbstractProcessTest.staticSetUp(samplesDir , pattern);// Pour un (ou plusieurs) test(s) en particulier:// AbstractProcessTest.staticSetUp(samplesDir , "u0[13]*-1");return AbstractProcessTest.collectData();

232 }

/** La méthode main() ci-dessous permet d’utiliser ce test JUnit comme* une application à lancer avec des options indiquant où se trouvent* les différentes ressources nécessaires.

237 ** Les options possibles pour cette application.* -v pour que le processus soit plus verbeux

87

* -path repertoire un repertoire ou chercher des fichiers* [Comme l’on ne sait pas forcement bien quel est le

242 * repertoire courant, il est souvent sage d’utiliser des* repertoires en notation absolue.]* -grammar nom de la grammaire. Le nom peut etre relatif a l’un* des repertoires mentionnes dans -path.* -samples le repertoire ou se trouvent les programmes ILP a tourner

247 * -pattern la regexp identifiant les programmes ILP a tourner* -cfile nom du fichier ou sera ecrit le C engendré* -script nom du script compilant et executant le programme C engendré** Les valeurs par défaut stockent le fichier C engendré dans le

252 * repertoire courant et supposent que ce dernier contient les sous-* repertoires Grammars/, Grammars/Samples/ et C/. Ces defauts* permettent de tourner les tests JUnit depuis Eclipse.*/public static class Options {

257 @Parameter(names = { "-v", "-verbose" },description = "Level of verbosity")

public boolean verbose = false;

@Parameter(names = {"-I", "-path"},262 description = "Option multiple indiquant les répertoires "

+ "où chercher la grammaire , le script, etc.")public List<String> path = new ArrayList <String >();

@Parameter(names = {"-grammar"},267 description = "Le nom de la grammaire .rng à utiliser")

public String grammarFileName ="Grammars" + File.separator + "grammar1.rng";

@Parameter(names = {"-cfile"},272 description = "Le nom du fichier C à engendrer")

public String cFileName = "theProgram.c";

@Parameter(names = {"-ctemplate"})public String cTemplateFileName =

277 "C" + File.separator + "templateTest.c";

@Parameter(names = {"-samples"},description = "Le repertoire où trouver les programmes ILP à tester")

public String samplesDirName =282 "Grammars" + File.separator + "Samples";

@Parameter(names = {"-pattern"},description = "La regexp des noms des programmes ILP à tester")

public String patternName = "u\\d+-1";287

@Parameter(names = {"-script"},description = "Le nom du shell script compilant et exécutant "+ "le programme C engendré")

public String scriptName =292 "C" + File.separator + "compileThenRun.sh";

}

//@BeforeClass // Inutile cf. nota ci-dessus.public static void initializeFromOptions ()

297 throws Exception {// Valider les options -path pour creer le Finder:finder = new Finder();if ( options.path.size() == 0 ) {

options.path.add(".");302 }

for (String path : options.path) {java.io.File dir = new File(path);finder.addPath(dir);

}307 // Chercher les autres fichiers à l’aide du Finder:

grammarFile = finder.findFile(options.grammarFileName);cTemplateFile = finder.findFile(options.cTemplateFileName);scriptFile = finder.findFile(options.scriptName);// cFile n’a pas à être recherché: c’est là où sera écrit le C:

312 cFile = new java.io.File(options.cFileName);if ( ! cFile.isAbsolute() ) {

// Utiliser le tempDir de la machine, partagé entre tous les// utilisateurs est risqué. On utilise le répertoire courant// pour éviter des problèmes de droit.

317 //final File tempDir = new File(System.getProperty("java.io.tmpdir"));final File tempDir = new File(System.getProperty("user.dir"));cFile = new java.io.File(tempDir, options.cFileName);

88

Page 45:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

}

322 // Chercher le repertoire des programmes ILP a traiter:samplesDir = finder.findFile(options.samplesDirName);if ( ! samplesDir.isDirectory() ) {

final String msg = "SamplesDir not a directory!";throw new RuntimeException(msg);

327 }pattern = options.patternName;

}protected static Options options = new Options();protected static IFinder finder;

332 protected static java.io.File grammarFile;protected static java.io.File cFile;protected static java.io.File cTemplateFile;protected static java.io.File samplesDir;protected static java.io.File scriptFile;

337

/** Un point d’entree pour des tests depuis shell. Ce code ne sert que* d’exemple pour des main() dans des sous-classes de ProcessTest. */

@SuppressWarnings("unused")342 public static void main (final String[] arguments) throws Exception {

new JCommander(options, arguments); // Unused value!initializeFromOptions();

Class <?>[] classes = new Class[]{347 // ProcessTest.class

};Result r = org.junit.runner.JUnitCore.runClasses(classes);String msg = "[[[" + r.getRunCount() + " Tests, "

+ r.getFailureCount() + " Failures]]]\n";352 System.err.println(msg);

}}

Java/src/fr/upmc/ilp/tool/AbstractProcessTestTest.java

1 package fr.upmc.ilp.tool;

import static org.junit.Assert.*;

import org.junit.Before;6 import org.junit.Test;

public class AbstractProcessTestTest {

@Before11 public void setUp () {

this.finder = new Finder();}private IFinder finder;

16 @Testpublic void testSingleFile () throws Throwable {

final AbstractProcessTest apt =new fr.upmc.ilp.ilp1.ProcessTest(

new File("Grammars/Samples/u01-1.xml"));21 AbstractProcessTest.initializeFromOptions();

IProcess process = new fr.upmc.ilp.ilp1.Process(finder);apt.setProcess(process);process.setFinder(AbstractProcessTest.finder);process.setVerbose(AbstractProcessTest.options.verbose);

26 process.setGrammar(AbstractProcessTest.grammarFile);process.setCFile(AbstractProcessTest.cFile);process.setCTemplateFile(AbstractProcessTest.cTemplateFile);process.setCompileThenRunScript(AbstractProcessTest.scriptFile);apt.handleFile();

31 }

@Testpublic void testManyFiles () throws Throwable {

final AbstractProcessTest apt =36 new fr.upmc.ilp.ilp1.ProcessTest(

new File("Grammars/Samples/u01-1.xml"));AbstractProcessTest.initializeFromOptions();IProcess process = new fr.upmc.ilp.ilp1.Process(finder);apt.setProcess(process);

89

41 process.setFinder(AbstractProcessTest.finder);process.setVerbose(AbstractProcessTest.options.verbose);process.setGrammar(AbstractProcessTest.grammarFile);process.setCFile(AbstractProcessTest.cFile);process.setCTemplateFile(AbstractProcessTest.cTemplateFile);

46 process.setCompileThenRunScript(AbstractProcessTest.scriptFile);assertTrue(

apt.handleFiles(new String[] {

"Grammars/Samples/u01-1.xml",51 "Grammars/Samples/u02-1.xml",

"Grammars/Samples/u03-1.xml"}));

}}

Java/src/fr/upmc/ilp/tool/CStuff.java

package fr.upmc.ilp.tool;

/** Conversion de suites de lettres du monde ILP vers le monde C. */

5 public class CStuff {

/** Transformer un identificateur ILP en un identificateur C. */

public static String mangle (final String s) {10 assert(s != null);

final StringBuffer sb = new StringBuffer(s.length());for ( int i=0 ; i<s.length() ; i++ ) {final char c = s.charAt(i);if ( ( ’a’ <= c && c <= ’z’ )

15 || ( ’A’ <= c && c <= ’Z’ )|| ( ’0’ <= c && c <= ’9’ )|| ( ’_’ == c ) ) {

sb.append(c);} else {

20 sb.append("_");sb.append(Integer.toHexString(c));

}}return sb.toString();

25 }

/** Transformer une chaine ILP en une chaine C. */

public static String protect (String value) {30 final int n = value.length();

final StringBuffer result = new StringBuffer(n);for ( int i = 0 ; i<n ; i++ ) {char c = value.charAt(i);switch ( c ) {

35 case ’\\’:case ’"’: {

result.append("\\");}//$FALL-THROUGH$

40 default: {result.append(c);

}}

}45 return result.toString();

}

}

Java/src/fr/upmc/ilp/tool/CStuffTest.java

1 package fr.upmc.ilp.tool;

import junit.framework.TestCase;

public class CStuffTest extends TestCase {6

90

Page 46:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

public void testMangle () {assertEquals("", CStuff.mangle(""));assertEquals("a", CStuff.mangle("a"));assertEquals("AZ9b", CStuff.mangle("AZ9b"));

11 assertNotSame("az9b", CStuff.mangle("AZ9b"));assertNotSame("AZ9B", CStuff.mangle("AZ9b"));assertEquals("i_40Z", CStuff.mangle("i@Z"));assertEquals("_40Z", CStuff.mangle("@Z"));assertEquals("_40", CStuff.mangle("@"));

16 assertEquals("i_3c0Z", CStuff.mangle("i\u03c0Z")); // Pi}

public void testProtect () {assertEquals("", CStuff.protect(""));

21 assertEquals("a", CStuff.protect("a"));assertEquals("aB?", CStuff.protect("aB?"));assertEquals("a\\\"", CStuff.protect("a\""));assertEquals("a\\\\n", CStuff.protect("a\\n"));

}26

}

Java/src/fr/upmc/ilp/tool/File.java

package fr.upmc.ilp.tool;2

import java.io.*;

public class File extends java.io.Fileimplements IContent {

7

static final long serialVersionUID = +12345678900021000L;

public File (String filename) {super(filename);

12 }

public File (java.io.File file) {super(file.getAbsolutePath());

}17

/** Calculer le nom de base (sans repertoire ni suffixe). */

public String getBaseName () {String name = getName();

22 int dotIndex = name.lastIndexOf(’.’);if (dotIndex >= 0) {

return name.substring(0, dotIndex);} else {

return name;27 }

}

/** Calculer le nom complet du fichier hors son suffixe. */

32 public String getNameWithoutSuffix () {return getParent() + File.separator + getBaseName();

}

/** Fournir le contenu d’un fichier sous la forme d’une chaine de37 * caracteres. */

public String getContent() {try {return FileTool.slurpFile(this);

42 } catch (IOException e) {throw new RuntimeException(e);

}}

47 /** Cette methode statique est utile pour recuperer le contenu d’une* instance de java.io.File. */

public static String getContent (File file) {try {

52 return FileTool.slurpFile(file);} catch (IOException e) {throw new RuntimeException(e);

91

}}

57

}

Java/src/fr/upmc/ilp/tool/FileTool.java

package fr.upmc.ilp.tool;2

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.FileWriter;

7 import java.io.IOException;import java.io.Reader;

/** Utilitaire pour lire ou écrire des fichiers entiers. */

12 public final class FileTool {

public FileTool () {super();

}17

/** Convertir un fichier en une chaîne de caracteres.* @return le contenu du fichier lu* @param file le fichier a lire*/

22

public static String slurpFile (final File file)throws IOException {

final FileReader fr = new FileReader(file);final int length = (int) file.length();

27 final char[] buffer = new char[length];int offset = 0;while ( offset < length ) {

int read = fr.read(buffer, offset, length-offset);offset += read;

32 }fr.close();return new String(buffer);

}

37 public static String slurpFile (final Reader fr)throws IOException {

final StringBuffer sb = new StringBuffer();final BufferedReader br = new BufferedReader(fr);final char[] buffer = new char[4096];

42 while ( true ) {int count = br.read(buffer);if (count < 0) {

return sb.toString();}

47 sb.append(buffer, 0, count);}

}

/** Convertir un fichier en une chaîne de caracteres.52 * @return le contenu du fichier lu

* @param filename le nom du fichier a lire*/

public static String slurpFile (final String filename)57 throws IOException {

return FileTool.slurpFile(new File(filename));}

/** Lire un fichier correspondant au résultat attendu d’un programme ILP.62 * Cette methode est utile pour tester ILP car elle retire les

* separateurs (blancs et retours a la ligne) superflus ce qui permet* de compenser les differences d’impression entre Scheme, Java et C. */

public static String readExpectedResult (String basefilename)67 throws IOException {

File resultFile = new File(basefilename + ".result");return FileTool.slurpFile(resultFile).trim();

}92

Page 47:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

72 public static String readExpectedResult (fr.upmc.ilp.tool.File file)throws IOException {File resultFile = new File(file.getNameWithoutSuffix() + ".result");return FileTool.slurpFile(resultFile).trim();

}77

// TODO enlever les trim() en trop dans les CompilerTest

/** Lire le fichier correspondant aux impressions attendues d’un* programme ILP. Cette methode est utile pour tester ILP car elle

82 * retire les separateurs (blancs et retours a la ligne) superflus* ce qui permet de compenser les differences d’impression entre Scheme,* Java et C. */

public static String readExpectedPrinting (String basefilename)87 throws IOException {

File resultFile = new File(basefilename + ".print");return FileTool.slurpFile(resultFile).trim();

}

92 public static String readExpectedPrinting (fr.upmc.ilp.tool.File file)throws IOException {File resultFile = new File(file.getNameWithoutSuffix() + ".print");return FileTool.slurpFile(resultFile).trim();

}97

/** Écrire une chaîne dans un fichier.* @param filename le nom du fichier a ecrire* @param s le nouveau contenu du fichier*/

102

public static void stuffFile (final String filename, final String s)throws IOException {

FileTool.stuffFile(new File(filename), s);}

107

/** Écrire une chaîne dans un fichier.* @param file le fichier a ecrire* @param s le nouveau contenu du fichier*/

112

public static void stuffFile (final File file, final String s)throws IOException {

final FileWriter fw = new FileWriter(file);try {

117 fw.write(s, 0, s.length());} finally {

fw.close();}

}122

}

Java/src/fr/upmc/ilp/tool/FileToolTest.java

1 package fr.upmc.ilp.tool;

import java.io.File;import java.io.IOException;

6 import junit.framework.TestCase;

/** Tests (Junit) de FileTool. */

public class FileToolTest extends TestCase {11

// Ce test ne sert qu’a invoquer le constructeur de FileTool// pour verifier que le taux de couverture// est bien egal a 100% sinon Hansel declare que FileTool.<init>// n’est pas couvert! Il faut ruser un peu pour qu’Eclipse ne

16 // s’apercoive pas que ce code est totalement inutile.

public void testInstantiation () {FileTool ft = new FileTool();assertTrue(ft instanceof FileTool);

21 }93

/** VÃ c©rifier que slurpFile fonctionne sur un fichier. */

public void testSlurpFileOnEmptyFile ()26 throws IOException {

File tmpFile = File.createTempFile("tsf0", "txt");String fileName = tmpFile.getAbsolutePath();final String s = FileTool.slurpFile(fileName);assertTrue(s.length() == 0 );

31 }

/** VÃ c©rifier que stuffFile fonctionne. */

public void testStuffFile ()36 throws IOException {

File tmpFile = File.createTempFile("tsf1", "txt");String fileName = tmpFile.getAbsolutePath();String content = "coucou";FileTool.stuffFile(fileName , content);

41 final String s = FileTool.slurpFile(fileName);assertEquals(content, s);

}

public void testStuffFileChaineVide ()46 throws IOException {

File tmpFile = File.createTempFile("tsf2", "txt");String fileName = tmpFile.getAbsolutePath();String content = "";FileTool.stuffFile(fileName , content);

51 final String s = FileTool.slurpFile(fileName);assertEquals(content, s);

}

}

Java/src/fr/upmc/ilp/tool/Finder.java

package fr.upmc.ilp.tool;

import java.io.IOException;4 import java.util.Vector;import java.io.File;

public class Finder implements IFinder {

9 public Finder () {this.directories = new Vector<File >();

}private final boolean verbose = false; // DEBUG

14 private final Vector<File> directories;

public File findFile (final String baseFileName)throws IOException {

File file = new File(baseFileName);19 if ( file.isAbsolute() ) {

if ( file.exists() ) {if ( verbose ) {

System.err.println("Found " + file.getAbsolutePath());}

24 return file;}throw new IOException("Inexistent absolute file");

}for ( File dir : directories ) {

29 if ( verbose ) {System.err.println("Searching " + dir.getAbsolutePath());

}final String fileName = dir.getAbsolutePath()

+ File.separator + baseFileName;34 file = new File(fileName);

if ( file.exists() ) {if ( verbose ) {

System.err.println("Found " + file.getAbsolutePath());}

39 return file;94

Page 48:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

}}throw new IOException("Cannot find file " + baseFileName);

}44

public void addPath (final File directory)throws IOException {

if ( ! directory.isDirectory() ) {throw new IOException("Not a directory: "

49 + directory.getAbsolutePath()+ " !");

}directories.add(directory);

}54

public void addPath (String directoryName)throws IOException {

directoryName = directoryName.replaceAll("/", File.separator);final File directory = new File(directoryName);

59 addPath(directory);}

public void addPossiblePath (String directoryName) {try {

64 addPath(directoryName);} catch (IOException e) {

// Ce n’est pas grave!}

}69

public java.io.File[] getPaths () {return directories.toArray(new File[0]);

}

74 public void setPaths (final File[] paths) throws IOException {directories.removeAllElements();for ( File dir : paths ) {

addPath(dir);}

79 }}

Java/src/fr/upmc/ilp/tool/FinderTest.java

package fr.upmc.ilp.tool;

import static org.junit.Assert.*;

5 import java.io.IOException;

import org.junit.Test;

public class FinderTest {10

@Testpublic void testInstantiation() {

final IFinder finder = new Finder();assertTrue(finder != null);

15 }

@Test(expected = IOException.class)public void findNothing () throws IOException {

final IFinder finder = new Finder();20 finder.findFile("laksdjlajsd");

fail("Should not appear!");}

@Test25 public void addHomeDirectory () throws IOException {

final IFinder finder = new Finder();String homeDir = System.getProperty("user.dir");assertTrue(homeDir != null);java.io.File dir = new java.io.File(homeDir);

30 finder.addPath(dir);assertTrue(finder.getPaths().length == 1);

}

95

@Test(expected = IOException.class)35 public void addBadDirectory () throws IOException {

final IFinder finder = new Finder();String homeDir = System.getProperty("user.dir");assertTrue(homeDir != null);String unexistentDir = homeDir + File.separator + "lajdsla";

40 java.io.File dir = new java.io.File(unexistentDir);finder.addPath(dir);

}

@Test45 public void find1inTmp () throws IOException {

final IFinder finder = new Finder();String tmpDir = System.getProperty("java.io.tmpdir");assertTrue(tmpDir != null);java.io.File tmpdir = new java.io.File(tmpDir);

50 finder.addPath(tmpdir);assertTrue(finder.getPaths().length == 1);java.io.File tmpFile = new java.io.File(

tmpDir + File.separator + "ilpAA");tmpFile.delete();

55 assertTrue(tmpFile.createNewFile());java.io.File foundFile = finder.findFile(tmpFile.getName());assert(foundFile != null);assert(foundFile.getAbsolutePath().equals(tmpFile.getAbsolutePath()));

}60

@Testpublic void find1in2Tmp () throws IOException {

final IFinder finder = new Finder();String homeDir = System.getProperty("user.dir");

65 assertTrue(homeDir != null);java.io.File dir = new java.io.File(homeDir);finder.addPath(dir);String tmpDir = System.getProperty("java.io.tmpdir");assertTrue(tmpDir != null);

70 java.io.File tmpdir = new java.io.File(tmpDir);finder.addPath(tmpdir);assertTrue(finder.getPaths().length == 2);java.io.File tmpFile = new java.io.File(

tmpDir + File.separator + "ilpBB");75 tmpFile.delete();

assertTrue(tmpFile.createNewFile());java.io.File foundFile = finder.findFile(tmpFile.getName());assert(foundFile != null);assert(foundFile.getAbsolutePath().equals(tmpFile.getAbsolutePath()));

80 }

@Testpublic void addPaths () throws IOException {

final IFinder finder = new Finder();85 String homeDir = System.getProperty("user.dir");

String tmpDir = System.getProperty("java.io.tmpdir");finder.setPaths(new java.io.File[]{

new java.io.File(homeDir),new java.io.File(tmpDir)

90 });assertTrue(finder.getPaths().length == 2);java.io.File tmpFile = new java.io.File(

tmpDir + File.separator + "ilpBB");tmpFile.delete();

95 assertTrue(tmpFile.createNewFile());java.io.File foundFile = finder.findFile(tmpFile.getName());assert(foundFile != null);assert(foundFile.getAbsolutePath().equals(tmpFile.getAbsolutePath()));

}100

}

Java/src/fr/upmc/ilp/tool/IContent.java

package fr.upmc.ilp.tool;

import java.io.IOException;4

/** Une interface fournissant un contenu à savoir un programme ILP.* Cette interface sert le plus souvent à masquer un fichier mais ce* pourrait être également une chaîne, une URL ou un générateur de* tests. */

96

Page 49:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

9

public interface IContent {

/** Fournir la chaîne de caractères représentant le programme ILP* auquel on s’intéresse.

14 ** @return String*/

String getContent () throws IOException;

19 }

Java/src/fr/upmc/ilp/tool/IFinder.java

1 package fr.upmc.ilp.tool;

import java.io.File;import java.io.IOException;

6 /*** Cet utilitaire contient une liste de répertoires où chercher un* fichier. On peut dynamiquement changer la liste des répertoires où* chercher. En cas d’anomalie, il signale des exceptions.*

11 * D’abord, on crée un Finder, on l’enrichit avec des répertoires (un* par un ou en bloc) puis on recherche des fichiers avec ce Finder.*/

public interface IFinder {16

/** Chercher un fichier par son petit nom dans les répertoires* associés à ce Finder. Signale une exception si l’on ne le trouve* nulle part. */public File findFile (String baseFileName) throws IOException;

21

/** Ajouter un répertoire à la fin de la liste des répertoires* où chercher. Le répertoire doit être un vrai répertoire sinon* une exception est signalée. */public void addPath (File directory) throws IOException;

26 /** Ajouter un répertoire à la fin de la liste des répertoires* où chercher. Le répertoire doit être un vrai répertoire sinon* une exception est signalée. Le répertoire est ici spécifié par* une chaîne de caractères en convention URL (avec des slashes). */public void addPath (String directory) throws IOException;

31 /** AJouter un répertoire mais seulement si c’est bien un répertoire. */public void addPossiblePath (String directory);

/** Renvoyer la liste des répertoires où chercher. */public java.io.File[] getPaths ();

36

/** Imposer la liste des répertoires où chercher. Tous doivent être* des vrais répertoires autrement une exception est signalée. */public void setPaths (File[] paths) throws IOException;

}

Java/src/fr/upmc/ilp/tool/IProcess.java

package fr.upmc.ilp.tool;

import org.w3c.dom.Document;

5 import fr.upmc.ilp.ilp1.interfaces.IAST;

/** Cette interface décrit un java.bean pour l’évaluation d’un* programme ILP.*/

10

public interface IProcess {

// Rendre le processus plus verbeux:void setVerbose (boolean verbose);

15

// Indiquer où chercher tous les fichiers utiles:IFinder getFinder ();void setFinder (IFinder finder);

97

20 // Cycle de vie

/** Initialiser le processus d’évaluation avec un contenu (le plus* souvent un fichier) c’est-à-dire le texte du programme. */void initialize (IContent ic);

25 boolean isInitialized ();Throwable getInitializationFailure ();String getProgramText ();

/** Préparer le processus d’évaluation jusqu’à choisir entre30 * interprétation ou compilation. Toutes les phases d’analyse communes

* sont effectuées ici. */void prepare ();boolean isPrepared ();Throwable getPreparationFailure ();

35 Document getDocument ();void setGrammar(java.io.File rngFile);IAST getIAST();void setIAST(IAST iast);// getParser()

40 // setParser(IParser iparser)

/** Évaluer par interprétation. */void interpret ();boolean isInterpreted ();

45 Throwable getInterpretationFailure ();Object getInterpretationValue ();String getInterpretationPrinting ();

/** Compiler vers un fichier. */50 void compile ();

boolean isCompiled ();Throwable getCompilationFailure ();String getCompiledProgram ();void setCFile(java.io.File cFile);

55 void setCTemplateFile(java.io.File templateFile);void setCompileThenRunScript (java.io.File scriptFile);// File getCompiledFile();

/** Exécuter le fichier compilé. */60 void runCompiled ();

boolean isExecuted ();Throwable getExecutionFailure ();String getExecutionPrinting ();

}

Java/src/fr/upmc/ilp/tool/IProcessListener.java

1 package fr.upmc.ilp.tool;

/** L’interface de l’observateur d’un IProcess. Un tel observateur peut* écrire ou visualiser à l’écran les progrès du processus observé. Le* processus est divisé en les phases suivantes:

6 * <ol> <li> Initialisation </li>* <li> Préparation </li>* <li> Interprétation </li>* <li> Compilation (vers C) </li>* <li> Exécution du programme compilé </li></ol>

11 * */

public interface IProcessListener {

/** Obtenir l’unique IProcess observé pour obtenir des informations16 * additionnelles sur les résultats des phases d’évaluation.

** @return IProcess*/

IProcess getProcess ();21

/** Par cette méthode, un IProcess indique qu’il a terminé son* initialisation. Les informations produites sont à demander* à l’IProcess observé. */void notifyInitialized ();

26

/** Par cette méthode, un IProcess indique qu’il a terminé sa* preparation. Les informations produites sont à demander* à l’IProcess observé. */void notifyPrepared ();

3198

Page 50:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** Par cette méthode, un IProcess indique qu’il a terminé son* interpretation. Les informations produites sont à demander* à l’IProcess observé. */void notifyInterpreted ();

36

/** Par cette méthode, un IProcess indique qu’il a terminé sa* compilation. Les informations produites sont à demander* à l’IProcess observé. */void notifyCompiled ();

41

/** Par cette méthode, un IProcess indique qu’il a terminé l’execution* du programme compile en C. Les informations produites sont à demander* à l’IProcess observé. */void notifyExecuted ();

46

}

Java/src/fr/upmc/ilp/tool/Parameterized.java

// $Id$package fr.upmc.ilp.tool;

3

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;

8 import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.Collections;import java.util.List;

13 import org.junit.runner.Runner;import org.junit.runner.notification.RunNotifier;import org.junit.runners.BlockJUnit4ClassRunner;import org.junit.runners.Suite;import org.junit.runners.model.FrameworkMethod;

18 import org.junit.runners.model.InitializationError;import org.junit.runners.model.Statement;import org.junit.runners.model.TestClass;

/** This class is a cloned version of the org.junit.runners.Parameterized23 * class. It modifies a single method, the getName method, that is used

* by Eclipse to display the name of the JUnit4 test.* */

public class Parameterized extends Suite {28

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public static @interface Parameters {}

33 private class TestClassRunnerForParametersextends BlockJUnit4ClassRunner {private final int fParameterSetNumber;

private final List<Object[]> fParameterList;38

TestClassRunnerForParameters(Class<?> type,List<Object[]> parameterList , int i) throws InitializationError {

super(type);fParameterList= parameterList;

43 fParameterSetNumber= i;}

@Overridepublic Object createTest() throws Exception {

48 return getTestClass().getOnlyConstructor().newInstance(computeParams());

}

private Object[] computeParams() throws Exception {53 try {

return fParameterList.get(fParameterSetNumber);} catch (ClassCastException e) {

throw new Exception(String.format("%s.%s() must return a Collection of arrays.",

58 getTestClass().getName(), getParametersMethod(getTestClass()).getName()));

99

}}

63 /* This method prints the name of the file currently processed. */@Overrideprotected String getName() {

File file = (File) fParameterList.get(fParameterSetNumber)[0];return String.format("[%s : %s]",

68 fParameterSetNumber ,file.getBaseName() );

}

@Override73 protected String testName(final FrameworkMethod method) {

return String.format("%s[%s]", method.getName(),fParameterSetNumber);

}

78 @Overrideprotected void validateZeroArgConstructor(List<Throwable > errors) {

// constructor can, nay, should have args.}

83 @Overrideprotected Statement classBlock(RunNotifier notifier) {

return childrenInvoker(notifier);}

}88

private final ArrayList <Runner> runners= new ArrayList <Runner >();

/*** Only called reflectively. Do not use programmatically.

93 */public Parameterized(Class<?> klass) throws Throwable {

super(klass, Collections.<Runner>emptyList());List<Object[]> parametersList= getParametersList(getTestClass());for (int i= 0; i < parametersList.size(); i++)

98 runners.add(new TestClassRunnerForParameters(getTestClass().getJavaClass(),parametersList , i));

}

@Override103 protected List<Runner> getChildren() {

return runners;}

@SuppressWarnings("unchecked")108 private List<Object[]> getParametersList(TestClass klass)

throws Throwable {return (List<Object[]>) getParametersMethod(klass).invokeExplosively(

null);}

113

private FrameworkMethod getParametersMethod(TestClass testClass)throws Exception {

List<FrameworkMethod > methods= testClass.getAnnotatedMethods(Parameters.class);

118 for (FrameworkMethod each : methods) {int modifiers= each.getMethod().getModifiers();if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))

return each;}

123

throw new Exception("No public static parameters method on class "+ testClass.getName());

}

128 }

Java/src/fr/upmc/ilp/tool/ProgramCaller.java

package fr.upmc.ilp.tool;2

import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.util.concurrent.CountDownLatch;

7100

Page 51:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/** Une classe pour invoquer un programme externe (gcc par exemple) et* récupérer le contenu de son flux de sortie. */

public class ProgramCaller {12

/** Construire une instance de ProgramCaller qui permettra d’exécuter* une commande via le système d’exploitation.** @param program

17 * la commande (programme et arguments) à exécuter.*/

public ProgramCaller (final String program) {this.program = program;

22 this.stdout = new StringBuffer(1023);this.stderr = new StringBuffer(1023);this.countDownLatch = new CountDownLatch(2);this.running = false;this.verbose = 0;

27 }private final String program;private static final Runtime RUNTIME = Runtime.getRuntime();private Process process;private final StringBuffer stdout;

32 private final StringBuffer stderr;private CountDownLatch countDownLatch;private boolean running;private int verbose = 0;

37 /** Verbaliser les traces d’exécution de la commande. */

public void setVerbose () {this.verbose++;

}42

private void verbalize (final String message) {this.verbalize(message, 0);

}

47 private void verbalize (final String message, final int level) {if ( this.verbose > level ) {

System.err.println(message);}

}52

/** Récupérer le flux de sortie produit par la commande.** @return la sortie standard de la commande*/

57

public String getStdout () {return stdout.toString();

}

62 /** Récupérer le flux de sortie d’erreur produit par la commande.** @return la sortie d’erreur de la commande*/

67 public String getStderr () {return stderr.toString();

}

/** Recuperer le code de retour de la commande.72 * Bloque quand celle-ci n’est pas terminee.

** @return le code de retour*/

77 public int getExitValue () {this.verbalize("-getExitValue -", 10);try {

this.countDownLatch.await();} catch (InterruptedException e) {

82 this.verbalize("-getExitValue Exception -", 10);throw new RuntimeException(); // MOCHE

}return this.exitValue;

101

}87 private transient int exitValue = 199;

/** Lancer la commande et stocker ses flux de sortie (normale et* d’erreur) dans un tampon pour pouvoir les analyser apres-coup. */

92 public void run () {// Au plus, une seule invocation:synchronized (this) {

if ( running ) {return;

97 } else {running = true;

}}// Exécuter la commande:

102 verbalize("[Running: " + program + "...");try {

this.process = RUNTIME.exec(program);} catch (java.io.IOException e) {

// Exception signalee quand le programme n’existe pas:107 this.stderr.append(e.getMessage());

// On ne fait pas partir les deux taches slurpStd*():this.countDownLatch.countDown();this.countDownLatch.countDown();verbalize("...not started]");

112 return;} catch (Throwable t) {

this.stderr.append(t.getMessage());// On ne fait pas partir les deux taches slurpStd*():this.countDownLatch.countDown();

117 this.countDownLatch.countDown();verbalize("...not started]");return;

}

122 // NOTA: documentation tells that, on Windows, one should read// asap the results or deadlocks may occur.slurpStdOut();slurpStdErr();

127 try {this.process.waitFor();this.countDownLatch.await();

} catch (InterruptedException e) {this.verbalize("!run Exception!", 10);

132 throw new RuntimeException(); // MOCHE}this.exitValue = this.process.exitValue();verbalize("...finished]");

}137

private void slurpStdOut () {final InputStream istdout = process.getInputStream();final BufferedInputStream bstdout = new BufferedInputStream(istdout);final Thread tstdout = new Thread () {

142

@Overridepublic void run () {

final int size = 4096;final byte[] buffer = new byte[size];

147 READ:while ( true ) {

int count = 0;try {

count = bstdout.read(buffer, 0, size);152 } catch (IOException exc) {

continue READ;}if ( count > 0 ) {

final String s = new String(buffer, 0, count);157 stdout.append(s);

ProgramCaller.this.verbalize("[stdout Reading: " + s + "]");} else if ( count == -1 ) {

ProgramCaller.this.verbalize("[stdout Dried!]", 10);ProgramCaller.this.countDownLatch.countDown();

162 return;}

102

Page 52:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

}}

};167 tstdout.start();

}

// La meme chose sur le flux d’erreur:private void slurpStdErr () {

172 final InputStream istderr = process.getErrorStream();final BufferedInputStream bstderr = new BufferedInputStream(istderr);final Thread tstderr = new Thread () {

@Override177 public void run () {

final int size = 4096;final byte[] buffer = new byte[size];READ:

while ( true ) {182 int count = 0;

try {count = bstderr.read(buffer, 0, size);

} catch (IOException exc) {continue READ;

187 }if ( count > 0 ) {

final String s = new String(buffer, 0, count);stderr.append(s);ProgramCaller.this.verbalize("[stderr Reading: " + s + "]");

192 } else if ( count == -1 ) {ProgramCaller.this.verbalize("[stderr Dried!]", 10);ProgramCaller.this.countDownLatch.countDown();return;

}197 }

}};tstderr.start();

}202

}

Java/src/fr/upmc/ilp/tool/ProgramCallerTest.java

1 package fr.upmc.ilp.tool;

import java.util.regex.Matcher;import java.util.regex.Pattern;

6 import junit.framework.TestCase;

/** Tests (Junit) de ProgramCaller. */

public class ProgramCallerTest extends TestCase {11

public void testProgramCallerInexistentVerbose () {final String programName = "lasdljsdfousadfl lsjd";ProgramCaller pc = new ProgramCaller(programName);assertNotNull(pc);

16 pc.setVerbose();pc.run();assertTrue(pc.getExitValue() != 0);

}

21 public void testProgramCallerInexistent () {final String programName = "lasdljsdfousadfl lsjd";ProgramCaller pc = new ProgramCaller(programName);pc.run();final String result = pc.getStderr();

26 System.err.println("Result: " + result); // DEBUGPattern p = Pattern.compile(".*(not found|Cannot run).*");Matcher m = p.matcher(result);assertTrue(m.matches());assertTrue(pc.getExitValue() != 0);

31 }

public void testProgramCallerEchoVerbose () {final ProgramCaller pc = new ProgramCaller("echo cou cou cou");

103

assertNotNull(pc);36 assertTrue(pc instanceof ProgramCaller);

pc.setVerbose();pc.run();assertTrue(pc.getExitValue() == 0);final String result = pc.getStdout();

41 System.err.println("Result: " + result); // DEBUGassertNotNull(result);assertTrue(result.length() > 0);assertEquals(result.trim(), "cou cou cou");

}46

public void testProgramCallerEcho () {final ProgramCaller pc = new ProgramCaller("echo cou cou cou");assertNotNull(pc);assertTrue(pc instanceof ProgramCaller);

51 pc.run();assertTrue(pc.getExitValue() == 0);final String result = pc.getStdout();System.err.println("Result: " + result); // DEBUGassertNotNull(result);

56 assertTrue(result.length() > 0);assertEquals(result.trim(), "cou cou cou");

}

public void testProgramCallerGccOnStdout () {61 final ProgramCaller pc = new ProgramCaller("gcc -v");

assertNotNull(pc);assertTrue(pc instanceof ProgramCaller);pc.run();assertTrue(pc.getExitValue() == 0);

66 final String result = pc.getStdout();System.err.println("Result: " + result); // DEBUGassertNotNull(result);assertTrue(result.length() == 0);assertEquals(result.trim(), "");

71 }

public void testProgramCallerGccOnStderr () {final ProgramCaller pc = new ProgramCaller("gcc -c unexistent.c");assertNotNull(pc);

76 assertTrue(pc instanceof ProgramCaller);pc.run();assertTrue(pc.getExitValue() != 0);final String errors = pc.getStderr();System.err.println("Errors: " + errors); // DEBUG

81 assertNotNull(errors);assertTrue(errors.length() > 0);Pattern p = Pattern.compile(".*gcc.*", Pattern.DOTALL);Matcher m = p.matcher(errors);assertTrue(m.matches());

86 }

public void testProgramCallerGccOnStderrVerbose () {final ProgramCaller pc = new ProgramCaller("gcc -c unexistent.c");assertNotNull(pc);

91 assertTrue(pc instanceof ProgramCaller);pc.setVerbose();pc.run();assertTrue(pc.getExitValue() != 0);final String errors = pc.getStderr();

96 System.err.println("Errors: " + errors); // DEBUGassertNotNull(errors);assertTrue(errors.length() > 0);Pattern p = Pattern.compile(".*gcc.*", Pattern.DOTALL);Matcher m = p.matcher(errors);

101 assertTrue(m.matches());}

public void testProgramCallerVerbose () {final ProgramCaller pc = new ProgramCaller("echo Voir ce qui se passe");

106 assertNotNull(pc);assertTrue(pc instanceof ProgramCaller);pc.setVerbose();pc.run();assertTrue(pc.getExitValue() == 0);

111 final String result = pc.getStdout();System.err.println("Result: " + result); // DEBUGassertNotNull(result);

104

Page 53:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

assertTrue(result.length() > 0);Pattern p1 = Pattern.compile(".*Voir ce qui se passe.*");

116 Matcher m1 = p1.matcher(result.trim());assertTrue(m1.matches());// verifier verbosite sur stderr FUTUREfinal String errors = pc.getStderr();System.err.println("Errors: " + errors); // DEBUG

121 assertNotNull(errors);assertTrue(errors.length() == 0);

}

// test de 8 taches en parallele:126

public void testMultipleProgramCallers () {final int max = 8;final ProgramCaller[] pcs = new ProgramCaller[max];for ( int i = max ; i>0 ; i-- ) {

131 pcs[i-1] = new ProgramCaller("sleep " + i);pcs[i-1].run();

}for ( int i = 0 ; i<max ; i++ ) {

assertTrue(pcs[i].getExitValue() == 0);136 }

}

}

Java/src/fr/upmc/ilp/tool/ToolTestSuite.java

package fr.upmc.ilp.tool;

import junit.framework.Test;import junit.framework.TestSuite;

5 import org.hansel.CoverageDecorator;

/** Regroupement de classes de tests pour le paquetage fr.upmc.ilp.tool.* Si tourne directement a partir d’Eclipse, le repertoire doit etre* Java/src/

10 */

public final class ToolTestSuite extends TestSuite {

public static FileTool ft;15

/*** Tester les classes de test. Realiser* egalement une analyse du taux de couverture des tests*

20 * @return Test - la suite de tests a effectuer*/

public static Test suite () {final TestSuite suite = new TestSuite();

25 suite.addTest(new CoverageDecorator(

FileToolTest.class,new Class[] {fr.upmc.ilp.tool.FileTool.class}));

suite.addTest(30 new CoverageDecorator(

CStuffTest.class,new Class[] {fr.upmc.ilp.tool.CStuff.class}));

suite.addTestSuite(ProgramCallerTest.class);return suite;

35 }

}

Java/src/fr/upmc/ilp/annotation/ILPexpression.java

package fr.upmc.ilp.annotation;2

import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;

7 import java.lang.annotation.RetentionPolicy;105

import java.lang.annotation.Target;

/** Cette annotation , presente a l’execution , indique qu’une methode mene* a une expression ILP. Divers sous-attributs caracterisent mieux cette

12 * annotation.** Cas particuliers: <ul>* <li> getOperands() n’est pas annoté (ce serait redondant* avec get*Operand()) </li>

17 * </ul> */

@Documented@Retention(RetentionPolicy.RUNTIME)@Inherited

22 @Target(ElementType.METHOD)public @interface ILPexpression {

/** Indique si la valeur obtenue par la methode peut etre null. */

27 boolean neverNull () default true;

/** Indique si la valeur obtenue est en fait un vecteur d’expressions. */

boolean isArray () default false;32 }

Java/src/fr/upmc/ilp/annotation/ILPforParsing.java

package fr.upmc.ilp.annotation;

3 import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Target;

8 /*** Cette annotation marque les methodes d’une fabrique qui* conduisent a des AST qui seront raffines par normalisation* en des AST plus precis.*/

13

@Documented@Inherited@Target({ElementType.METHOD})public @interface ILPforParsing {}

Java/src/fr/upmc/ilp/annotation/ILPvariable.java

package fr.upmc.ilp.annotation;

3 import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;

8 import java.lang.annotation.Target;

/** Cette annotation , presente a l’execution , indique qu’une methode mene* a une variable ILP (ou a un tableau de variables) lue ou ecrite. Les* variables introduites par de nouvelles liaisons ne sont pas annotees.

13 */

@Documented@Retention(RetentionPolicy.RUNTIME)@Inherited

18 @Target(ElementType.METHOD)public @interface ILPvariable {

/** Indique si la valeur obtenue par la methode peut etre null. */

23 boolean neverNull () default true;

/** Indique si la valeur obtenue est en fait un vecteur de variables. */

boolean isArray() default false;28 }

106

Page 54:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

Java/src/fr/upmc/ilp/annotation/OrNull.java

package fr.upmc.ilp.annotation;2

import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Target;

7

/** Cette annotation precise que la valeur attendue peut aussi etre null.* Attention null instanceof AnyClass est toujours vrai!* Cette annotation pourrait servir a des outils d’analyse statique de code.*/

12

@Documented@Inherited@Target({ElementType.METHOD,

ElementType.PARAMETER ,17 ElementType.FIELD})public @interface OrNull {}

C/C.readme

Ce répertoire contient la bibliothèque d’exécution des différentes2 versions d’ILP. Le Makefile contient les règles de reconstruction. La

commande ’make’ sans argument devrait suffire. Si vous souhaitezutiliser un GC (glaneur de cellule ou garbage collector), il fautinstaller le gc de Boehm présent dans gc6.8.tgz et, pour cela,tourner:

7

make gc6.8/gc.a

Si les tests du GC passent, vous pouvez utiliser l’option +gc danscompileThenRun.sh. Cette option est utile à partir d’ILP6.

C/Makefile

# On efface les resultats de compilation pour faciliter le changement# de machine (et d’architecture (Intel*86 vers powerpc par exemple)).

3 # En fait, il serait mieux de stocker les .o et .a dans un# sous-repertoire mais comment automatiser (de facon portable) cela# sous un OS non Unix ?

work : clean libilp.a8 -make compile.gc

uname -s -r -v -m -o > HOSTTYPE

# Effacer les resultats de compilation

13 clean :-rm -f *.o libilp.a HOSTTYPE gc6.8/gc.a

# Les bibliotheques d’execution sont compilees en mode debug, c’est# plus utile pour les exercices.

18

CC = gcc

# Pas de glibc pour MacOSX, on suppose que l’existence de /Library indique# que c’est un Mac.

23 CFLAGS = -Wall -std=c99 -pedantic \-g \

‘if [ -d /Library ] ; then : ; else if pkg-config --exists glib -2.0 ; then pkg-config --cflags --libs glib -2.0 ; fi ; fi‘

# On compile tout ce qui est en C (sauf ilpHash.c non porte sur MacOSX)28 # et sauf les template*.c qui sont bien sur incomplets.

CFILES = $(shell ls ilp*.c)

# On place ilpBasicError dans l’archive et non ilpError (afin de33 # pouvoir en changer s’il le faut).

ARFILES = ilp.o ilpAlloc.o ilpBasicError.o ilpException.o

# Ne pas oublier ranlib, c’est utile sur MacOSX.38

libilp.a : ${CFILES:.c=.o}107

ar cvr libilp.a ${ARFILES}-ranlib libilp.a

43 # Autres dependances:

ilp.o : ilp.c ilp.hilpAlloc.o : ilpAlloc.c ilpAlloc.h ilp.hilpBasicError.o : ilpBasicError.c ilpBasicError.h ilp.h

48 ilpException.o : ilpException.c ilpException.h ilp.hilpError.o : ilpError.c ilpBasicError.h ilp.hilpObj.o : ilpObj.c ilpObj.h

# L’option +gc de compileThenRun.sh utilise le GC de Boehm qu’il faut53 # aussi installer (cf. C.readme):

compile.gc : gc6.8/gc.agc6.8/gc.a : gc6.8.tgz

[ -d gc6.8 ] || tar xzf gc6.8.tgz58 cd gc6.8/ && make test

# QNC 2010oct: OK sur amd64 (ubuntu 9.10)# QNC 2010oct: ne compile pas sur MacOSX 10.6.4

# end of Imakefile

C/compileThenRun.sh

#! /bin/bash#* ******************************************************************

3 #* ILP -- Implantation d’un langage de programmation.#* Copyright (C) 2004 <[email protected]>#* $Id: compileThenRun.sh 1056 2011-08-19 12:06:28Z queinnec $#* GPL version >=2#* ******************************************************************

8 # Compiler le fichier templateTest.c dûment instancié avec le fichier# passé en argument.

USAGE="Usage: $0 [ -template.c ] [ +gc ] [ +v ] foo.c [bar.o hux.h baz.c -Dq=3 ...]Compile les fichiers C, cree puis lance l’executable /tmp/templateTest$USER

13

template.c est le fichier devant inclure foo.c[Il y en a un par version d’ILP]

+gc est une option incluant le GC de Boehm (si utilisable)+v montre sans l’executer la commande gcc synthetisee

18 foo.c est le resultat de la compilation d’ILPbar.o sont des modules compiles a utiliser plutot que ceux de libilp.a

[libilp.a contient les modules par defaut d’ILP1. Pour certainesversions d’ILP, il faut des modules plus appropries.]

hux.h est un fichier d’entete a inclure pour la compilation de foo.c23 baz.c est un fichier C a compiler en meme temps que foo.c

-Dvar=val variable cpp supplementaire a passer a gcc

EXEMPLES:pour ILP1:

28 $0 foo.cpour ILP2:

$0 -templateTest2.c foo.cpour ILP3 ou ILP4:

$0 -templateTest3.c foo.c ilpError.o33 pour ILP6:

$0 -templateTest6.c foo.c ilpObj.o

Ce script est egalement sensible aux variables d’environnement:OTHER_LIBS ajout de bibliotheques supplementaires

38 TEMPLATE definition du patron a utiliser"

# Les variables contrôlant si l’on utilise le GC de Boehm:# Chemin relatif vers la bibliotheque statique:

43 LIB_GC=gc6.8/gc.a# Incorpore -t-on un GC ou pas ?WITH_GC=false# Montre-t-on la commande gcc synthetiseeVERBOSE=false

48

# Le fichier servant de réceptacle au code C produit:# Par defaut, on utilise celui a cote de ce script.TEMPLATE=${TEMPLATE:-‘dirname $0‘/templateTest.c}

53 case "$1" in-*.c)

108

Page 55:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

TEMPLATE=${1#-}shiftcase "$TEMPLATE" in

58 /*):;;

*)TEMPLATE=‘pwd‘/$TEMPLATE

63 ;;esac;;

-*)echo "Unknown option: $1" >&2

68 exit 11;;

esac

while [ $# -gt 0 ]73 do

case "$1" in+gc)

WITH_GC=trueshift

78 ;;+v)

VERBOSE=trueshift;;

83 *)break;;

esacdone

88

# Le fichier de code C produit par ILP à compiler avec gcc:FILE=$1shift

93 CFLAGS=’-Wall -Wno-unused-variable -Wno-unused-label -std=c99 -pedantic -g ’# NOTE: Il y a des tests avec des variables inutilisees , ne pas# attirer l’attention dessus.

# if [ -n "${Apple_PubSub_Socket_Render}" ]98 # then

# # Sur MacOSX (il y a surement mieux comme test!)# :# else# if pkg-config --exists glib -2.0 2>/dev/null

103 # then# CFLAGS="$CFLAGS"‘pkg-config --cflags --libs glib-2.0‘# fi# fi

108 if [ -r "$FILE" ]then

# Rendre FILE absolu:case "$FILE" in

/*)113 true

;;*)

FILE=‘pwd‘/$FILE;;

118 esacelse

echo Fichier inexistant: $FILE >&2exit 1

fi123

COMMAND_DIR=‘dirname $0‘case "$COMMAND_DIR" in

# rendre le repertoire qui contient compileThenRun.sh absolu:/*)

128 true;;

*)COMMAND_DIR=‘pwd‘/$COMMAND_DIR;;

133 esac

# Si les .c ne sont pas compilés pour l’architecture courante, on les109

# recompile à la volée.( cd $COMMAND_DIR/

138 RECOMPILE=trueif [ -r ./HOSTTYPE ]then if [ "$(< ./HOSTTYPE)" = "‘uname -s -r -v -m -o‘" ]

then RECOMPILE=falsefi

143 fiif $RECOMPILEthen

echo "Compilation de la bibliotheque d’execution d’ILP..." >&2make clean

148 if make workthen :else

echo "GC non compilable: option +gc non possible!" >&2exit 13

153 fifi 1>&2

)

if [ ! -r $COMMAND_DIR/libilp.a ]158 then

echo Bibliotheque introuvable: $COMMAND_DIR/libilp.a >&2exit 3

fi

163 if [ ! -r $TEMPLATE ]then

echo Patron introuvable: $TEMPLATE >&2exit 5

fi168

if $WITH_GCthen

if [ -r $COMMAND_DIR/$LIB_GC ]then

173 CFLAGS="-DWITH_GC $CFLAGS"else

echo "GC introuvable (consulter Makefile): $COMMAND_DIR/$LIB_GC" >&2# On continue sans GC puisque non compilé!WITH_GC=false

178 fifi

HFILE=/tmp/templateTest$USER.hif [ -r $HFILE ]

183 then rm -f $HFILEfi

# Collecter les fichiers (.o, .a .h ou .c) à incorporer et les rendre absolus:OFILES=${OFILES:-}

188 for filedocase "$file" in

-D*)CFLAGS="$CFLAGS $file"

193 ;;*)

case "$file" in/*.[coa])

OFILES="$OFILES $file"198 ;;

*.[coa])file=$COMMAND_DIR/$fileOFILES="$OFILES $file";;

203 /*.h)echo "#include \"$file\" " >>$HFILE;;

*.h)file=$COMMAND_DIR/$file

208 echo "#include \"$file\" " >>$HFILE;;

esacif [ ! -r $file ]then

110

Page 56:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

213 echo Fichier introuvable: $file >&2exit 7

fi;;

esac218 done

if [ -s $HFILE ]then CFLAGS="$CFLAGS -DFICHIER_H=\"$HFILE\" "fi

223

OTHER_LIBS=${OTHER_LIBS:- -lm}if $WITH_GCthen OTHER_LIBS="$OTHER_LIBS $COMMAND_DIR/$LIB_GC"fi

228

AOUT=/tmp/templateTest$USERif [ -r $AOUT ]then rm -f $AOUTfi

233

if $VERBOSEthen

echo gcc ${CFLAGS} -o $AOUT -DFICHIER_C="\"$FILE\"" \-I. -I$COMMAND_DIR \

238 $TEMPLATE \$OFILES $COMMAND_DIR/libilp.a $OTHER_LIBS ’&&’ $AOUT

fi

#echo Trying to compile $FILE ... >&2243 gcc ${CFLAGS} -o $AOUT -DFICHIER_C="\"$FILE\"" \

-I. -I$COMMAND_DIR \$TEMPLATE \$OFILES $COMMAND_DIR/libilp.a $OTHER_LIBS && \

$AOUT248

# end of compileThenRun.sh

C/ilp.c

1 /** Ce fichier constitue la bibliothèque d’exécution d’ILP. */#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>

6 #include <ctype.h>#include "ilp.h"#include "ilpAlloc.h"#include "ilpBasicError.h"

11 /** Booléens.** On alloue statiquement les deux booléens.* Pas possible encore en C d’allouer le flottant pi statiquement.* On l’alloue donc dynamiquement mais comme un singleton (cf. ilp_pi).

16 */

struct ILP_Object ILP_object_true = {ILP_BOOLEAN_KIND ,{ ILP_BOOLEAN_TRUE_VALUE }

21 };

struct ILP_Object ILP_object_false = {ILP_BOOLEAN_KIND ,{ ILP_BOOLEAN_FALSE_VALUE }

26 };

/** Une fonction pour stopper abruptement l’application. */

ILP_Object31 ILP_die (char *message)

{fputs(message, stderr);fputc(’\n’, stderr);fflush(stderr);

36 exit(EXIT_FAILURE);}

111

/** Ce n’est pas une vraie allocation mais une simple conversion. */

41 ILP_ObjectILP_make_boolean (int b){

if ( b ) {return ILP_TRUE;

46 } else {return ILP_FALSE;

}}

51 ILP_ObjectILP_make_integer (int d){

ILP_Object result = ILP_AllocateInteger();result->_content.asInteger = d;

56 return result;}

ILP_ObjectILP_make_float (double d)

61 {ILP_Object result = ILP_AllocateFloat();result->_content.asFloat = d;return result;

}66

ILP_ObjectILP_pi (){

static ILP_Object object_pi = NULL;71 if ( object_pi == NULL ) {

object_pi = ILP_make_float(ILP_PI_VALUE);}return object_pi;

}76

ILP_ObjectILP_make_string (char *s){

81 int size = strlen(s);ILP_Object result = ILP_AllocateString(size);result->_content.asString._size = size;memmove(result->_content.asString.asCharacter , s, size);return result;

86 }

/** String primitives */

ILP_Object91 ILP_concatenate_strings (ILP_Object o1, ILP_Object o2)

{int size1 = o1->_content.asString._size;int total_size = size1 + o2->_content.asString._size;ILP_Object result = ILP_AllocateString(total_size);

96 memmove(&(result->_content.asString.asCharacter[0]),o1->_content.asString.asCharacter ,o1->_content.asString._size);

memmove(&(result->_content.asString.asCharacter[size1]),o2->_content.asString.asCharacter ,

101 o2->_content.asString._size);return result;

}

/** Opérateurs unaires. */106

ILP_ObjectILP_make_opposite (ILP_Object o){

ILP_CheckIfInteger(o);111 {

ILP_Object result = ILP_AllocateInteger();result->_content.asInteger = (- o->_content.asInteger);return result;

}116 }

ILP_ObjectILP_make_negation (ILP_Object o)

112

Page 57:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

{121 /* Opere sur toutes les representations possibles de Vrai */

if ( ILP_isEquivalentToTrue(o) ) {return ILP_FALSE;

} else {return ILP_TRUE;

126 }}

/** Opérateurs binaires. */

131 /* DefineOperator(addition , +) est incorrect car + représente également* la concaténation des chaînes de caractères. */

ILP_ObjectILP_make_addition (ILP_Object o1, ILP_Object o2)

136 {if ( ILP_isInteger(o1) ) {if ( ILP_isInteger(o2) ) {

ILP_Object result = ILP_AllocateInteger();result->_content.asInteger = o1->_content.asInteger + o2->_content.asInteger;

141 return result;} else if ( ILP_isFloat(o2) ) {

ILP_Object result = ILP_AllocateFloat();result->_content.asFloat = o1->_content.asInteger + o2->_content.asFloat;return result;

146 } else {return ILP_domain_error("Not a number", o2);

}} else if ( ILP_isFloat(o1) ) {if ( ILP_isInteger(o2) ) {

151 ILP_Object result = ILP_AllocateFloat();result->_content.asFloat = o1->_content.asFloat + o2->_content.asInteger;return result;

} else if ( ILP_isFloat(o2) ) {ILP_Object result = ILP_AllocateFloat();

156 result->_content.asFloat = o1->_content.asFloat + o2->_content.asFloat;return result;

} else {return ILP_domain_error("Not a number", o2);

}161

} else if ( ILP_isString(o1) ) {if ( ILP_isString(o2) ) {return ILP_concatenate_strings(o1, o2);

} else {166 return ILP_domain_error("Not a string", o2);

}} else {return ILP_domain_error("Not addable", o1);

}171 }

#define DefineOperator(name,op) \ILP_Object \ILP_make_##name (ILP_Object o1, ILP_Object o2) \

176 { \if ( ILP_isInteger(o1) ) { \

if ( ILP_isInteger(o2) ) { \ILP_Object result = ILP_AllocateInteger(); \result->_content.asInteger = \

181 o1->_content.asInteger op o2->_content.asInteger; \return result; \

} else if ( ILP_isFloat(o2) ) { \ILP_Object result = ILP_AllocateFloat(); \result->_content.asFloat = \

186 o1->_content.asInteger op o2->_content.asFloat; \return result; \

} else { \return ILP_domain_error("Not a number", o2); \

} \191 } else if ( ILP_isFloat(o1) ) { \

if ( ILP_isInteger(o2) ) { \ILP_Object result = ILP_AllocateFloat(); \result->_content.asFloat = \

o1->_content.asFloat op o2->_content.asInteger; \196 return result; \

} else if ( ILP_isFloat(o2) ) { \ILP_Object result = ILP_AllocateFloat(); \result->_content.asFloat = \

113

o1->_content.asFloat op o2->_content.asFloat; \201 return result; \

} else { \return ILP_domain_error("Not a number", o2); \

} \} else { \

206 return ILP_domain_error("Not a number", o1); \} \

}

DefineOperator(subtraction , -)211 DefineOperator(multiplication , *)

DefineOperator(division , /)

/* DefineOperator(modulo, %) est incorrect car le modulo ne se prend* que sur de entiers. */

216

ILP_ObjectILP_make_modulo (ILP_Object o1, ILP_Object o2){

if ( ILP_isInteger(o1) ) {221 if ( ILP_isInteger(o2) ) {

ILP_Object result = ILP_AllocateInteger();result->_content.asInteger =

o1->_content.asInteger % o2->_content.asInteger;return result;

226 } else {return ILP_domain_error("Not an integer", o2);

}} else {

return ILP_domain_error("Not an integer", o1);231 }

}

#define DefineComparator(name,op) \ILP_Object \

236 ILP_compare_##name (ILP_Object o1, ILP_Object o2) \{ \

if ( ILP_isInteger(o1) ) { \if ( ILP_isInteger(o2) ) { \

return ILP_make_boolean( \241 o1->_content.asInteger op o2->_content.asInteger); \

} else if ( ILP_isFloat(o2) ) { \return ILP_make_boolean( \

o1->_content.asInteger op o2->_content.asFloat); \} else { \

246 return ILP_domain_error("Not a number", o2); \} \

} else if ( ILP_isFloat(o1) ) { \if ( ILP_isInteger(o2) ) { \

return ILP_make_boolean( \251 o1->_content.asFloat op o2->_content.asInteger); \

} else if ( ILP_isFloat(o2) ) { \return ILP_make_boolean( \

o1->_content.asFloat op o2->_content.asFloat); \} else { \

256 return ILP_domain_error("Not a number", o2); \} \

} else { \return ILP_domain_error("Not a number", o1); \

} \261 }

DefineComparator(less_than , <)DefineComparator(less_than_or_equal , <=)DefineComparator(equal, ==)

266 DefineComparator(greater_than , >)DefineComparator(greater_than_or_equal , >=)DefineComparator(not_equal , !=)

/** Primitives */271

ILP_ObjectILP_newline (){

fputc(’\n’, stdout);276 return ILP_FALSE;

}

ILP_ObjectILP_print (ILP_Object o)

114

Page 58:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

281 {switch (o->_kind) {case ILP_INTEGER_KIND: {

fprintf(stdout, "%d", o->_content.asInteger);break;

286 }case ILP_FLOAT_KIND: {

/* Supprimer les blancs du debut */char buffer[15];char *p = &buffer[0];

291 sprintf(buffer, "%12.5g", o->_content.asFloat);while ( isspace(*p) ) {

p++;}fprintf(stdout, "%s", p);

296 break;}case ILP_BOOLEAN_KIND: {

fprintf(stdout, "%s", (ILP_isTrue(o) ? "true" : "false"));break;

301 }case ILP_STRING_KIND: {

fprintf(stdout, "%s", o->_content.asString.asCharacter);break;

}306 default: {

fprintf(stdout, "<0x%x:0x%p>", o->_kind, (void*) o);break;

}}

311 return ILP_FALSE;}

/* end of ilp.c */

C/ilp.h

1

#ifndef ILP_H#define ILP_H

#include <stdlib.h>6 #include <stdio.h>

/** Definition d’ILP_Object si non deja definie */

#ifndef ILP_STRUCT_H11 #define ILP_STRUCT_H

/** Le type général des fonctions d’ILP (d’arité quelconque). */

typedef struct ILP_Object* (*ILP_general_function)();16

/** Il y a cinq types de valeurs pour l’instant repérées par ces* constantes (elles figureront dans le champ _kind d’ILP_Object.*/

21 enum ILP_Kind {ILP_BOOLEAN_KIND = 0xab010ba,ILP_INTEGER_KIND = 0xab020ba,ILP_FLOAT_KIND = 0xab030ba ,ILP_STRING_KIND = 0xab040ba,

26 ILP_PRIMITIVE_KIND = 0xab050ba};

/** Toutes les valeurs manipulées ont cette forme.*

31 * Un premier champ indique leur nature ce qui permet de décoder le* champ qui suit. Les chaînes de caractères sont préfixées par leur* longueur.

* NOTE: asBoolean est la première possibilité ce qui est nécessaire pour36 * l’allocation statiques des booléens (cf. ilp.c). Ce ne l’était pas

* auparavant ce qui créait une bogue pour MacOSX (ILP_TRUE valait faux!).*/

typedef struct ILP_Object {41 enum ILP_Kind _kind;

115

union {unsigned char asBoolean;int asInteger;double asFloat;

46 struct asString {int _size;char asCharacter[1];

} asString;struct asPrimitive {

51 ILP_general_function _code;} asPrimitive;

} _content;} *ILP_Object;

56 #endif /* ILP_STRUCT_H */

/** -------------------------------------------* Des macros pour manipuler toutes ces valeurs.*/

61

/** Booléens. */

/** Il y a deux sortes de booléens et ces deux constantes les repèrent. */

66 enum ILP_BOOLEAN_VALUE {ILP_BOOLEAN_FALSE_VALUE = 0,ILP_BOOLEAN_TRUE_VALUE = 1

};

71 #define ILP_Boolean2ILP(b) \ILP_make_boolean(b)

#define ILP_isBoolean(o) \((o)->_kind == ILP_BOOLEAN_KIND)

76

#define ILP_isTrue(o) \(((o)->_kind == ILP_BOOLEAN_KIND) && \((o)->_content.asBoolean))

81 #define ILP_TRUE (&ILP_object_true)#define ILP_FALSE (&ILP_object_false)

#define ILP_isEquivalentToTrue(o) \((o) != ILP_FALSE)

86

#define ILP_CheckIfBoolean(o) \if ( ! ILP_isBoolean(o) ) { \

ILP_domain_error("Not a boolean", o); \};

91

/** Entiers */

#define ILP_Integer2ILP(i) \ILP_make_integer(i)

96

#define ILP_AllocateInteger() \ILP_malloc(sizeof(struct ILP_Object), ILP_INTEGER_KIND)

#define ILP_isInteger(o) \101 ((o)->_kind == ILP_INTEGER_KIND)

#define ILP_CheckIfInteger(o) \if ( ! ILP_isInteger(o) ) { \

ILP_domain_error("Not an integer", o); \106 };

/** Flottants */

#define ILP_Float2ILP(f) \111 ILP_make_float(f)

#define ILP_AllocateFloat() \ILP_malloc(sizeof(struct ILP_Object), ILP_FLOAT_KIND)

116 #define ILP_isFloat(o) \((o)->_kind == ILP_FLOAT_KIND)

#define ILP_CheckIfFloat(o) \if ( ! ILP_isFloat(o) ) { \

116

Page 59:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

121 ILP_domain_error("Not a float", o); \};

#define ILP_PI_VALUE 3.1415926535#define ILP_PI (ILP_pi())

126

/** Chaînes de caractères */

#define ILP_String2ILP(s) \ILP_make_string(s)

131

#define ILP_AllocateString(length) \ILP_malloc(sizeof(struct ILP_Object) \

+ (sizeof(char) * (length)), ILP_STRING_KIND)

136 #define ILP_isString(o) \((o)->_kind == ILP_STRING_KIND)

#define ILP_CheckIfString(o) \if ( ! ILP_isString(o) ) { \

141 ILP_domain_error("Not a string", o); \};

/** Opérateurs unaires */

146 #define ILP_Opposite(o) \ILP_make_opposite(o)

#define ILP_Not(o) \ILP_make_negation(o)

151

/** Opérateurs binaires */

#define ILP_Plus(o1,o2) \ILP_make_addition(o1, o2)

156

#define ILP_Minus(o1,o2) \ILP_make_subtraction(o1, o2)

#define ILP_Times(o1,o2) \161 ILP_make_multiplication(o1, o2)

#define ILP_Divide(o1,o2) \ILP_make_division(o1, o2)

166 #define ILP_Modulo(o1,o2) \ILP_make_modulo(o1, o2)

/** modulo a faire */

171 #define ILP_LessThan(o1,o2) \ILP_compare_less_than(o1,o2)

#define ILP_LessThanOrEqual(o1,o2) \ILP_compare_less_than_or_equal(o1,o2)

176

#define ILP_GreaterThan(o1,o2) \ILP_compare_greater_than(o1,o2)

#define ILP_GreaterThanOrEqual(o1,o2) \181 ILP_compare_greater_than_or_equal(o1,o2)

#define ILP_Equal(o1,o2) \ILP_compare_equal(o1,o2)

186 #define ILP_NotEqual(o1,o2) \ILP_compare_not_equal(o1,o2)

/** Primitives:* Les fonctions ILP_print() et ILP_newline() sont définies dans ilp.c

191 */

#define ILP_globalIfInitialized(n) \(((n)!=NULL)?(n):(ILP_error("Uninitialized " #n " variable!")))

196 typedef ILP_Object (*ILP_Primitive) ();

extern struct ILP_Object ILP_object_true;extern struct ILP_Object ILP_object_false;

117

extern struct ILP_Object ILP_object_pi;201 extern ILP_Object ILP_die (char *message);

extern ILP_Object ILP_make_boolean (int b);extern ILP_Object ILP_make_integer (int d);extern ILP_Object ILP_make_float (double d);extern ILP_Object ILP_pi ();

206 extern ILP_Object ILP_make_string (char *s);extern ILP_Object ILP_make_opposite (ILP_Object o);extern ILP_Object ILP_make_negation (ILP_Object o);extern ILP_Object ILP_make_addition (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_concatenate_strings (ILP_Object o1, ILP_Object o2);

211 extern ILP_Object ILP_make_subtraction (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_make_multiplication (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_make_division (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_make_modulo (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_compare_less_than (ILP_Object o1, ILP_Object o2);

216 extern ILP_Object ILP_compare_less_than_or_equal (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_compare_equal (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_compare_greater_than (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_compare_greater_than_or_equal (ILP_Object o1, ILP_Object o2);extern ILP_Object ILP_compare_not_equal (ILP_Object o1, ILP_Object o2);

221 extern ILP_Object ILP_newline ();extern ILP_Object ILP_print (ILP_Object o);

#endif /* ILP_H */

226 /* end of ilp.h */

C/ilpAlloc.c

/** Ce fichier constitue la bibliothèque d’exécution d’ILP. */

#include <stdlib.h>4 #include "ilp.h"#include "ilpAlloc.h"#include "ilpBasicError.h"

char *ilpAlloc_Id = "$Id: ilpAlloc.c 768 2008-11-02 15:56:00Z queinnec $";9

/** Allouer un objet d’ILP avec une taille et une étiquette. */

ILP_ObjectILP_malloc (int size, enum ILP_Kind kind)

14 {ILP_Object result = malloc(size);if ( result == NULL ) {

return ILP_error("Memory exhaustion");};

19 result->_kind = kind;return result;

}

/* end of ilpAlloc.c */

C/ilpAlloc.h

#ifndef ILP_ALLOC_H2 #define ILP_ALLOC_H

extern ILP_Object ILP_malloc (int size, enum ILP_Kind kind);

#endif /* ILP_ALLOC_H */7 /* end of ilpAlloc.h */

C/ilpBasicError.c

/** Ce fichier constitue la bibliothèque d’exécution d’ILP. */

3 #include <stdlib.h>#include <stdio.h>#include "ilp.h"#include "ilpBasicError.h"

8 char *ilpBasicError_Id = "$Id: ilpBasicError.c 822 2009-10-07 08:04:40Z queinnec $";118

Page 60:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/*** Signalement de problèmes.*

13 * Cette fonction ne renvoit rien mais le typage est meilleur si on* l’utilise après un return (cf. exemples plus bas).*/

ILP_Object18 ILP_error (char *message)

{ILP_die(message);/** NOT REACHED */return NULL;

23 }

#define BUFFER_LENGTH 1000

/** Une fonction pour signaler qu’un argument n’est pas du type attendu. */28

ILP_ObjectILP_domain_error (char *message, ILP_Object o){

char buffer[BUFFER_LENGTH];33 snprintf(buffer, BUFFER_LENGTH , "%s\nCulprit: 0x%p\n",

message, (void*) o);ILP_die(buffer);/** NOT REACHED */return NULL;

38 }

/* end of ilpBasicError.c */

C/ilpBasicError.h

#ifndef ILP_BASIC_ERROR_H#define ILP_BASIC_ERROR_H

extern ILP_Object ILP_error (char *message);5 extern ILP_Object ILP_domain_error (char *message, ILP_Object o);

#endif /* ILP_BASIC_ERROR_H *//* end of ilpBasicError.h */

C/ilpException.c

/** Ce fichier constitue un complément à la bibliothèque d’exécution2 * d’ILP notamment les primitives manipulant les exceptions. */

#include <stdlib.h>#include <stdio.h>#include "ilpException.h"

7

/** Ces variables globales contiennent:* -- le rattrapeur d’erreur courant* -- l’exception courante (lorsque signalée)*/

12

static struct ILP_catcher ILP_the_original_catcher = {NULL

};struct ILP_catcher *ILP_current_catcher = &ILP_the_original_catcher;

17

ILP_Object ILP_current_exception = NULL;

/** Signaler une exception. */

22 ILP_ObjectILP_throw (ILP_Object exception){

ILP_current_exception = exception;if ( ILP_current_catcher == &ILP_the_original_catcher ) {

27 ILP_die("No current catcher!");};longjmp(ILP_current_catcher ->_jmp_buf , 1);/** UNREACHABLE */

119

return NULL;32 }

/** Chaîner le nouveau rattrapeur courant avec l’ancien. */

void37 ILP_establish_catcher (struct ILP_catcher *new_catcher)

{new_catcher ->previous = ILP_current_catcher;ILP_current_catcher = new_catcher;

}42

/** Remettre en place un rattrapeur. */

voidILP_reset_catcher (struct ILP_catcher *catcher)

47 {ILP_current_catcher = catcher;

}

/* end of ilpException.c */

C/ilpException.h

#ifndef ILP_EXCEPTION_H#define ILP_EXCEPTION_H

4 /** Les entêtes des ressources manipulant les exceptions.* Voici comment utiliser cette bibliothèque:** À tout instant, ILP_current_catcher contient le rattrapeur* d’exceptions. Lorsqu’une exception est signalée par ILP_throw , elle

9 * est envoyée au rattrapeur courant. Pour établir un nouveau* rattrapeur d’erreur, utilisez le motif suivant:** { struct ILP_catcher *current_catcher = ILP_current_catcher;* struct ILP_catcher new_catcher;

14 * if ( 0 == setjmp(new_catcher ->_jmpbuf) ) {* ILP_establish_catcher(&new_catcher);* ...* ILP_current_exception = NULL;* };

19 * ILP_reset_catcher(current_catcher);* if ( NULL != ILP_current_exception ) {* if ( 0 == setjmp(new_catcher ->_jmpbuf) ) {* ILP_establish_catcher(&new_catcher);* ... = ILP_current_exception;

24 * ILP_current_exception = NULL;* ...* };* };* ILP_reset_catcher(current_catcher);

29 * ...* if ( NULL != ILP_current_exception ) {* ILP_throw(ILP_current_exception);* };* }

34 */

#include <setjmp.h>#include "ilp.h"

39 struct ILP_catcher {struct ILP_catcher *previous;jmp_buf _jmp_buf;

};

44 extern struct ILP_catcher *ILP_current_catcher;extern ILP_Object ILP_current_exception;extern ILP_Object ILP_throw (ILP_Object exception);extern void ILP_establish_catcher (struct ILP_catcher *new_catcher);extern void ILP_reset_catcher (struct ILP_catcher *catcher);

49

#endif /* ILP_EXCEPTION_H */

/* end of ilpException.h */

C/templateTest.c120

Page 61:  · Code ILP1 Christian.Queinnec@lip6.fr 28 septembre 2011 Ces chiers sont diffusés pour l'enseignement ILP (Implantation d'un langage de programmation) dis-pensé depuis l'automne

/* $Id: templateTest.c 942 2010-08-24 17:09:58Z queinnec $*

3 * Ce patron nécessite que la variable FICHIER_C soit définie avec le* nom du fichier à intégrer ici. On intègre le fragment dans une* fonction qui est invoquée depuis main(), son résultat est alors* imprimé grâce à la fonction print() de la bibliothèque d’exécution.*

8 * Pour être compilé, le fichier ilp.h doit être accessible.* Pour être exécuté, la bibliothèque libilp.a doit être accessible.*/

#include <stdio.h>13 #include <stdlib.h>

#if defined(FICHIER_H)# include FICHIER_H#else

18 # include "ilp.h"#endif

char *ilpTemplate_Id = "$Id: templateTest.c 942 2010-08-24 17:09:58Z queinnec $";

23 ILP_Objectprogram ()# include FICHIER_C

int28 main (int argc, char *argv[])

{ILP_print(program());ILP_newline();return EXIT_SUCCESS;

33 }

/* end of templateTest.c */

121