rapport.tex (40393B)
1 \documentclass{article} 2 3 \usepackage[T1]{fontenc} 4 \usepackage[utf8]{inputenc} 5 \usepackage[frenchb]{babel} 6 7 \usepackage{hyperref} 8 \hypersetup{% 9 colorlinks,% 10 citecolor=black,% 11 filecolor=black,% 12 linkcolor=black,% 13 urlcolor=black% 14 } 15 16 \newenvironment{void}{}{} 17 18 \usepackage{graphicx} 19 \graphicspath{{images/}} 20 \usepackage{calc} 21 22 \usepackage[center]{caption} 23 24 \usepackage{epigraph} 25 26 \usepackage{pgffor} 27 \usepackage{ifthen} 28 \usepackage{tikz} 29 \usetikzlibrary{matrix,fit,calc} 30 31 \usepackage{amsmath} 32 \usepackage[nottoc, notlof, notlot]{tocbibind} 33 34 \usepackage{rapport} 35 36 \author{Georges Dupéron} 37 \title{Langage de programmation} 38 39 \begin{document} 40 41 \maketitle 42 \tableofcontents 43 \newpage 44 45 \part{Objectif} 46 47 \section[Sujet]{Sujet: Etude d'un paradigme de programmation : les langages graphiques à Dataflow} 48 Il y a environ 20 ans, le langage et le système d'exploitation FORTH avaient été mis au point, avec pour but de créer un environnement 49 totalement personnalisé pour chaque utilisateur. La particularité de FORTH était qu'il ne possédait pas de mots-clés, ou instructions 50 figées, et que chaque utilisateur était en mesure de définir lui-même ses propres primitives, voire redéfinir ses primitives... à 51 l'infini. 52 53 L'échec de FORTH est venu, entre autres de la nécessité d'échanger des programmes entre utilisateurs, et des conflits dus à l'homonymie 54 (même nom, fonction différente) et à la synonymie (même fonction, noms différents). %Également, l'évolution des besoins et 55 Les fonctions n'étaient pas toujours documentées, ce qui fait qu'un même programmeur ne pouvait pas faire exécuter, à un intervalle de 56 temps relativement court, 2 fois le même programme... 57 58 Pour autant, le côté adaptatif et souple de FORTH aurait été largement plébiscité s'il n'y avait eu cette difficulté. Une manière de 59 contourner ce genre de conflit, dû à une représentation symbolique textuelle trop fortement contrainte par la syntaxe, est de se pencher 60 vers une programmation qui privilégie les flux de données sur les actions à réaliser, et vers des bases graphiques plutôt que textuelles, 61 laissant donc à chaque utilisateur la liberté de définir ses actions, et préservant en revanche les flux. 62 63 L'idée de ce projet est de proposer une première architecture de compilateur ou d'interpréteur de premier niveau pour illustrer ce 64 paradigme, et tenter d'en évaluer les propriétés. Ce projet nécessite un excellent niveau en programmation et un goût prononcé pour 65 l'écriture de compilateurs. 66 67 \section{But du projet} 68 Le but de ce projet sera donc dans un premier temps de définir un langage de programmation visuel utilisant le paradigme du 69 dataflow\footnote{\url{http://en.wikipedia.org/wiki/Dataflow}}, et n'ayant pas de primitives fixes. Dans un second temps, nous 70 implémenterons un EDI\footnote{Environnement de Développement Intégré} permettant de créer des programmes dans ce langage, et de les 71 interpréter. 72 73 \part{Définition du langage} 74 75 \section{Étude de l'existant} 76 77 \subsection{FORTH}\footnote{Les bibliothèques universitaires de Montpellier n'ont aucun ouvrage concernant FORTH. Il faudrait peut-être suggérer quelques achats aux bibliothécaires.} 78 Le langage FORTH est basé sur le principe de l'expansion de macros~: lorsqu'on «appelle» une macro, elle s'expanse, ses sous-macros 79 s'expansent, et ainsi de suite, jusqu'à ce que des macros de bas niveau lisent des valeurs sur la pile (pop), et en écrivent d'autres à la 80 place. 81 82 Mon expérience personnelle, lorsque j'ai essayé par le passé d'implémenter des algorithmes un peu complexes en \TeX (le langage sur 83 lequel est construit \LaTeX), m'a montré que cette approche a un défaut fondamental~: il est impossible de délimiter le rayon d'action d'une 84 macro. Étant donné qu'elle travaille sur la pile (ou dans le cas de \TeX, sur les jetons qui suivent l'appel de macro), et qu'elle peut 85 enlever ou ajouter autant d'éléments qu'elle veut sur la pile, il y a un risque assez grand pour qu'une macro dont on ne connaît pas bien le 86 fonctionnement soit mal utilisée, et abîme la portion de pile qui appartient à d'autres macros. 87 88 Vu que les macros peuvent être imbriquées autant qu'on veut, il est possible qu'une macro située très bas dans l'arbre fasse ce genre 89 d'erreur. Le débogage nécessite alors de parcourir tout l'arbre d'appels de macros à la recherche de l'erreur. 90 91 Une représentation graphique permet d'indiquer explicitement quelles sont les données fournies à une fonction ou une macro, et il devient 92 alors possible de mettre en place des mécanismes de contrôle de l'utilisation de la pile, au moins pour le débogage. Sans cette approche, il 93 n'y a aucun moyen de savoir quels sont les données passées en paramètre et quelles données doivent rester sur la pile, du point de vue de la 94 macro appellante. 95 96 Dans le cas de FORTH, il n'y a pas de primitives dans le langage. Cela signifie que si on regarde récursivement le code des macros, il n'y a 97 pas un moment où on va tomber sur une macro qui n'a pas de définition, mais est implémentée par le compilateur ou l'interpréteur (définition 98 dans un autre langage, et probablement inaccessible pour peu qu'on n'ait pas le code source du compilateur). À la place, aux feuilles de 99 l'arbre d'expansion des macros, on trouvera des instructions du langage machine. 100 101 Ce comportement est fortement souhaitable de la part d'un langage généraliste, du point de vue éducatif~: les curieux peuvent farfouiller 102 jusqu'aux racines du langage et ainsi comprendre comment fonctionne les programmes, à tous les niveaux. Certains programmeurs pensent que 103 c'est important de comprendre en profondeur comment fonctionne la machine et les programmes qui l'utilisent\cite{coders-at-work}. 104 105 Cela confère aussi au langage une grande portabilité~: FORTH a été porté sur plus d'une vingtaine de processeurs\cite{forth-history}. En définissant un ensemble 106 de fonctions de haut niveau que chaque implémentation doit fournir, on peut s'assurer qu'un programme fonctionnant sur une implémentation du 107 langage fonctionnera aussi sur une autre. 108 109 \subsection{Dataflow} 110 111 \begin{figure}[h!] 112 \centering 113 \pgfdeclarelayer{background layer} 114 \pgfsetlayers{background layer,main} 115 \begin{tikzpicture} 116 \bloc[t]{mul/a*b}{ab}{c} 117 \node[coordinate] (between-a-b) at ($ .5*(mul-in-a) + .5*(mul-in-b) $) {}; 118 119 \node at (mul.north) [above=.25em,color=green!50!black,inner sep=0pt] (nom) {$x^2$}; 120 \node at (nom.north) [above=.25em,coordinate] (nom-plus) {}; 121 122 \tikzset{ex/.style={fill=white,left of=between-a-b,matrix anchor=ex-out-val.center,input-bloc}} 123 \bloc[t]{ex/x}{}{{val/}} 124 \node[coordinate] (connect-ex-a-b) at ($ .5*(between-a-b) + .5*(ex-out-val) $) {}; 125 126 \tikzset{ox2/.style={fill=white,right of=mul-out-c,matrix anchor=ox2-in-val.center,input-bloc}} 127 \bloc[t]{ox2/x^2}{{val/}}{} 128 129 \draw (ex-out-val) -- (connect-ex-a-b); 130 \draw (connect-ex-a-b) |- (mul-in-a); 131 \draw (connect-ex-a-b) |- (mul-in-b); 132 \draw (mul-out-c) |- (ox2-in-val); 133 \node[coordinate] (rightmost) at (ox2-label) {}; 134 \node[coordinate] (leftmost) at (ex-label) {}; 135 136 \shorthandoff{:} 137 \draw[->] (ox2) -- ++(1,0) node[coordinate,label=above:\tiny$x^2$] {}; 138 \shorthandon{:} 139 \begin{pgfonlayer}{background layer} 140 \node[bloc,fit=(rightmost)(mul)(nom-plus)(leftmost),inner xsep=0pt,inner ysep=.333em] (bloc) {}; 141 \end{pgfonlayer} 142 143 144 \path[<-,thick,draw=gray] (bloc.north east) -- ++(1,1) node[fill=white] (LB) {Bloc}; 145 \path[<-,thick,draw=gray] (nom.north) -- (nom.north |- LB) node[fill=white] (LNB) {Nom du bloc}; 146 \path[<-,thick,draw=gray] (ex.south west) -- ++(-1,-1) node[fill=white] (LPE) {Port d'entrée}; 147 \path[<-,thick,draw=gray] (ox2.south east) -- ++(1,-1) node[fill=white] (LPS) {Port de sortie}; 148 \path[<-,thick,draw=gray] (connect-ex-a-b |- mul-in-a) ++ (-.04,.04) -- (LPE |- LB) node[fill=white] (LC) {Connexion}; 149 \end{tikzpicture} 150 \caption{Les parties d'un programme en dataflow.} 151 \label{fig:parties-dataflow} 152 \end{figure} 153 154 Le paradigme du dataflow\cite{vanroy-paradigms} (flux de données) est connu des concepteurs de langages de programmation depuis longtemps. Il a été utilisé avec 155 succès dans certains domaines, principalement des domaines intéressant les non-programmeurs. 156 157 \subsubsection{Graphisme} 158 159 Le logiciel Quartz Composer sous MacOS permet la création d'images vectorielles animées et interactives sous MacOS de manière graphique~: On 160 applique des filtres graphiques, représentés par des boîtes, aux résultats d'autres filtres, en connectant les boîtes entre elles. Dans 161 World Machine, ces filtres sont des actions physiques (érosion, soulèvement) et permettent de générer des cartes de hauteur (heightmaps), 162 qui sont utilisées pour modéliser des terrains en 3D. 163 164 \subsubsection{Musique} 165 166 L'interface de certains logiciels de musique s'inspirent de l'architecture des synthétiseurs modulaires\cite{modular-synth} (ces grosses 167 boîtes avec pleins de prises jack qu'on relie avec des câbles : chaque prise jack est une entrée ou une sortie d'un module, les câbles sont 168 les connexions). Un des premiers synthétiseurs virtuels, Max/MSP, utilisait cette analogie. D'autres logiciels similaires lui ont succédé : 169 PureData (qui est aussi un langage de programmation généraliste), Alsa Modular Synth, ansi qu'une série de logiciels créé par une équipe de 170 recherche de l'ICAM\cite{musique-ircam}. 171 172 \subsubsection{Mesures scientifiques} 173 174 LabView permet aux scientifiques de procéder à des traitements sur les signaux et les données acquises depuis un ordinateur, grâce à un 175 langage de programmation graphique utilisant le paradigme du dataflow. 176 177 \begin{figure}[ht] 178 \setbox1=\hbox{\includegraphics[width=5cm]{alsa-modular-synth}}% The smaller image 179 \setbox2=\hbox{\includegraphics[width=5cm]{world-machine}}% The larger image 180 {\,} 181 \hfill 182 \begin{minipage}{5cm} 183 \centering 184 % http://cafcom.free.fr/ams/ams1.png 185 \raisebox{0.5\ht2-0.5\ht1}{\includegraphics[width=5cm]{alsa-modular-synth}} 186 \end{minipage} 187 \hfill 188 \begin{minipage}{5cm} 189 \centering 190 % http://www.world-machine.com/images/ui1.jpg 191 \includegraphics[width=5cm]{world-machine} 192 \end{minipage} 193 \hfill 194 {\,} 195 196 %%%%%%%%%% 197 198 {\,} 199 \hfill 200 \begin{minipage}{5cm} 201 \centering 202 \caption{Alsa Modular Synth\cite{alsa-modular-synth}} 203 \label{fig:alsa-modular-synth} 204 \end{minipage} 205 \hfill 206 \begin{minipage}{5cm} 207 \centering 208 \caption{World Machine\cite{world-machine}} 209 \label{fig:world-machine} 210 \end{minipage} 211 \hfill 212 {\,} 213 214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 215 216 \setbox1=\hbox{\includegraphics[width=5cm]{alsa-modular-synth}}% The smaller image 217 \setbox2=\hbox{\includegraphics[width=5cm]{world-machine}}% The larger image 218 {\,} 219 \hfill 220 \begin{minipage}{5cm} 221 \centering 222 % http://upload.wikimedia.org/wikipedia/en/thumb/b/bc/QuartzComposerSnowLeopard.png/800px-QuartzComposerSnowLeopard.png 223 \raisebox{0.5\ht2-0.5\ht1}{\includegraphics[width=5cm]{quartz-composer}} 224 \end{minipage} 225 \hfill 226 \begin{minipage}{5cm} 227 \centering 228 % http://zone.ni.com/cms/images/devzone/tut/binary_tree2.png 229 \includegraphics[width=5cm]{labview} 230 \end{minipage} 231 \hfill 232 {\,} 233 234 %%%%%%%%%% 235 236 {\,} 237 \hfill 238 \begin{minipage}{5cm} 239 \centering 240 \caption{Quartz Composer\cite{quartz-composer}} 241 \label{fig:quartz-composer} 242 \end{minipage} 243 \hfill 244 \begin{minipage}{5cm} 245 \centering 246 \caption{LabView\cite{labview}} 247 \end{minipage} 248 \hfill 249 {\,} 250 251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 252 253 {\,} 254 \hfill 255 \begin{minipage}{10cm} 256 \caption{Captues d'écrans de quelques langages de programmation utilisant le paradigme du dataflow.} 257 \end{minipage} 258 \hfill 259 {\,} 260 \label{fig:screenshots} 261 \end{figure} 262 263 \subsubsection{Traitement de signaux} 264 265 Force est de constater que tous les exemples cités ci-dessus sont des cas particuliers de traitement de signal (image, son, signaux 266 provenant d'appareils de mesure). Le paradigme du dataflow devrait être tout aussi efficace pour construire des programmes conventionnels~: 267 les signaux d'entrée sont les évènements provoqués par l'utilisateur (clic de souris, appui sur le clavier), ceux de sortie sont les retours 268 (écran, haut-parleurs, \dots). 269 270 \subsection{Langages visuels} 271 272 \subsubsection[Acceptation par les programmeurs]{Acceptation des langages visuels par les programmeurs} 273 Les langages visuels n'ont eu que peu de succès auprès de la communauté des programmeurs, et les raisons de ce rejet méritent d'être 274 étudiées\footnote{Peut-être que c'est simplement que les langages textuels, c'est pour les programmeurs avec du poil sur le torse, et les 275 langages graphiques sont pour les mauviettes…}. 276 277 Récemment, un chercheur a mis en place un sondage auprès des programmeurs qui devrait à terme permettre de savoir quels langages 278 correspondent le mieux à quelles affirmations, selon les programmeurs\cite{the-right-tool}. Ces affirmations sont du type «Ce langage est 279 facile à utiliser» ou «Ce langage a une bonne communauté». Les affirmations qui obtiennent les moins bons scores pour un langage donné 280 indiquent en général les défauts de ce langage. J'ai donc contacté l'auteur de ce sondage pour lui demander d'ajouter des langages de 281 programmation visuels pendant que le sondage est encore ouvert, afin de pouvoir étudier par la suite ces résultats. 282 283 \subsubsection{Historique} 284 On a toutefois de noubreux cas d'utilisation de représentations visuelles dans la programmation~: Les langages suivant le paradigme du 285 dataflow, dont nous avons parlé ci-dessus, mais aussi l'utilisation d'un formalisme graphique pour la représentation principale des 286 diagrammes UML\footnote{Il existe aussi une représentation textuelle d'UML\cite{htun-spec}}. Les organigrammes de programmation (control 287 flow diagram) sont aussi utilisés depuis longtemps. 288 289 D'autres représentations visuelles sont utilisées dans certains systèmes. La figure \ref{fig:lisp-class-graph} montre un graphe d'héritage 290 des classes en Lisp avec l'environnement McCLIM. On trouve aussi des graphes d'appels de fonctions\cite{lisp-func-graph}, qui relient deux fonctions si l'une 291 appelle (ou peut appeler) l'autre. 292 293 \begin{figure}[h!] 294 \centering 295 \includegraphics[height=5cm]{lisp-class-graph} 296 \caption{Graphe d'héritage des classes en Lisp avec McCLIM\cite{lisp-class-graph}} 297 \label{fig:lisp-class-graph} 298 \end{figure} 299 300 \subsection{Langages spécifiques à un domaine} 301 \label{sec:dsl} 302 303 Il est fréquent que des programmeurs créent des «langages spécifiques à un domaine» (DSL, Domain Specific Language) pour répondre au besoin 304 d'exprimer facilement des instructions et notions très fortement liées à un certain domaine, sans être encombrés par la syntaxe rigide, le 305 vocabulaire limité et le manque d'expressivité de leur langage habituel. Les fichiers de configuration sont en général écrits dans un DSL 306 par exemple. Mais les DSL ont de grosses limitations : bien qu'ils soient adaptés à l'expression d'idées dans ce domaine, ces langages ne 307 possèdent pas l'expressivité nécessaire à des opérations plus complexes~: souvent, ces DSL ne sont complets au sens de Turing et n'ont pas 308 accès aux bibliothèques de fonctions des autres langages. 309 310 C'est pour ces raisons que les DSL sont de plus en plus laissés un peu de côté~: La configuration de GRUB 2 est toujours dans un DSL, mais 311 elle est générée dynamiquement par des scripts shell\cite{config-grub}, la configuration du gestionnaire de fenêtres awesome est écrite en 312 Lua\cite{config-awesome}, beaucoup de logiciels utilisent python comme langage de script, plutôt que de créer un langage de script 313 spécifique à l'application. 314 315 D'un autre côté, le problème des langages de programmation généralistes est qu'ils permettent d'augmenter le vocabulaire disponible, par 316 l'ajout de fonctions et la création de variables, mais ils ne permettent pas de modifier la grammaire utilisé (la structure du code). En 317 réalité, de nombreux langages permettent cela par le biais de macros, mais cette approche est assez limitée~: l'écriture de macros est en 318 général fastidieuse -- beaucoup plus difficile que l'écriture de fonctions -- et l'utilisation de macros est néanmoins soumise à un grand 319 nombre de contraintes syntaxiques du langage hôte (parenthèses, accolades, \dots). De plus le système de macros de certains langages, comme 320 le C, n'a pas la puissance d'un vrai langage : pas de récursivité des macros, pas de structures conditionnelles à l'intérieur d'une macro. 321 322 Il y a donc des avantages dans les deux approches, mais aucune ne permet de satisfaire complètement les besoins de facilité d'expression et 323 de puissance du langage. Nous proposons une solution alternative~: permettre l'écriture d'un programme sous n'importe quelle forme visuelle 324 (grammaire libre), dans un langage graphique orienté dataflow. Nous imposons quelques contraintes, afin de garder une certaine cohérence~: 325 \begin{itemize} 326 \item Les sous-programmes sont représentés par des éléments graphiques (blocs) ; 327 \item Les paramètres d'entrées de ces sous-programmes sont des entités visuelles qu'on peut connecter entre elles (ports) ; 328 \item Les valeurs de ces paramètres sont fournies à travers des liens qui relient les ports ; 329 \end{itemize} 330 Ces règles laissent toutefois une très grande liberté, les blocs peuvent être rectangulaires, ronds ou de n'importe quelle forme. Ils 331 pourraient par exemple afficher les calculs mathémathiques qu'ils contiennent non pas sous l'apparence d'instructions mais d'une formule 332 mathémathique. On peut aussi faire en sorte que dans un outil de conception d'interfaces utilisateur, les composants graphiques (fenêtre, 333 bouton, etc.) ne soient pas de simples images, mais \emph{soient} les blocs correspondants. Dans le logiciel LabView, les «blocs» peuvent 334 revêtir différentes apparences. 335 \begin{figure}[h!] 336 \centering 337 \begin{tikzpicture} 338 \bloc[t]{mul/c = \left(\frac{a*b}{2}\right)^2}{ab}{c} 339 \end{tikzpicture} 340 \caption{Avec affichage choisi par le bloc} 341 \label{fig:affichage-math-oui} 342 \end{figure} 343 \begin{figure}[h!] 344 \centering 345 \begin{tikzpicture} 346 \bloc[t]{mul/a*b}{ab}{c} 347 348 \tikzset{deux/.style={below of=mul-out-c,matrix anchor=deux-out-val.center}} 349 \bloc[t]{deux/2}{}{{val/}} 350 351 \tikzset{div/.style={right of=mul-out-c,matrix anchor=div-in-a.center}} 352 \bloc[t]{div/\frac{a}{b}}{ab}{c} 353 354 \tikzset{sqr/.style={right of=div-out-c,matrix anchor=sqr-in-a.center}} 355 \bloc[t]{sqr/a^2}{a}{b} 356 357 \node[coordinate] (between-deux-div) at ($ .5*(deux-out-val) + .5*(div-in-b) $) {}; 358 359 \draw (deux-out-val) -| (between-deux-div); 360 \draw (between-deux-div) |- (div-in-b); 361 \draw (mul-out-c) |- (div-in-a); 362 \draw (div-out-c) |- (sqr-in-a); 363 364 \shorthandoff{:} 365 \draw[->] (sqr-out-b) -- ++(1,0) node[coordinate,label=above:\tiny$\left(\frac{a*b}{2}\right)^2$] {}; 366 \shorthandon{:} 367 \end{tikzpicture} 368 \caption{Sans affichage choisi par le bloc} 369 \label{fig:affichage-math-non} 370 \end{figure} 371 372 Il est même possible que certains blocs aient une apparence invisible. Par exemple les opérations de conversion de types (cast) pourraient 373 être masquées, et ne s'afficher que sur le lien entre la source du transtypage et sa destination. 374 375 Avec ces règles, les ports n'ont pas besoin d'être affichés en permanence. Ils peuvent par exemple être dans une boîte de dialogue de 376 configuration dui apparaît lorsqu'on double-clique sur le bloc correspondant (World Machine utilise cette approche, et laisse aussi les 377 ports visibles en mode «réduit»). 378 379 Les liens peuvent être annotés, regroupés en bus, etc. Comme on peut l'imaginer, avec un minimum d'effort de cohérence, ces libertés sont 380 susceptibles de rendre les programmes plus lisibles (non-affichage des éléments qui ne sont pas importants à la comprhéension du programme) 381 et plus faciles à écrire (les instructions (blocs) spécialisées ont une interface d'utilisation adaptée). 382 383 \subsection{Environnement de développement intégré} 384 385 { 386 \setlength{\epigraphwidth}{0.85\linewidth} 387 \renewcommand{\textflush}{void} 388 \renewcommand{\epigraphflush}{center} 389 \epigraph{ 390 Clearly good design is as important for visual languages as for textual ones. Furthermore, the effectiveness of a visual language indeed 391 any precise language for specifying structures, depends to a large extent on the quality of the editor, browser, interpreter, debugger and 392 other tools supplied by the language implementation 393 }{Christopher C. Risley and Trevor J. Smedley \cite{the-editor-is-as-important-as-the-language}} 394 } 395 396 Les environnements de développement intégré jouent un rôle crucial pour les langages de programmation visuels. En effet, sans la possibilité 397 de construire un programme par une séquence (obscure) de caractères, la convivialité du langage est directement liée aux outils que propose 398 l'EDI. Ces EDI n'ont en général que peu en commun avec les ceux destinés aux langages textuels, et se présentent plus comme des logiciels de 399 dessin vectoriel que comme des éditeurs de texte. 400 401 Certaines questions sont récurrentes dans la conception d'EDI pour des langages visuels. Une des plus importante est la gestion de l'espace 402 à l'écran~: les primitives graphiques sont décorées de bordures, et d'autres éléments visuels, qui occupent beaucoup d'espace à l'écran, 403 réduisant ainsi la quantité d'informations affichées. Ce problème est plus communément connu sous le nom de «Deutsch 404 Limit»\cite{deutsch-limit}~: 405 \begin{quotation} 406 Well, this is all fine and well, but the problem with visual programming languages is that you can’t have more than 50 visual primitives 407 on the screen at the same time. How are you going to write an operating system? 408 \end{quotation} 409 410 Cependant, dans le cas d'un affichage textuel, le cerveau humain n'est pas capable d'ingurgiter en temps réel toute l'information à 411 l'écran\footnote{Sur mon écran, on peut loger plus de 60 lignes de texte verticalement, et ce sur 2 colonnes. Allez donc analyser 120 lignes 412 de C d'un seul coup.}. L'affichage sous forme graphique permet au contraire de clarifier et de nettoyer les informations à l'écran, on 413 peut donc supposer que le cerveau est capable d'analyser plus rapidement du «code» graphique que son équivalent textuel (un dessin vaut 414 mille mots, dit-on). 415 416 De plus les programmeurs passent beaucoup de temps à chercher tel ou tel morceau de code ou fonction. L'EDI Code Bubbles\cite{code-bubbles} 417 apporte une solution à ce problème pour les langages textuels, en fournissant une interface dans laquelle le programmeur manipule un gand 418 nombre de fragments de code assez court, et a la possibilité d'en ouvrir facilement de nouveaux de manière contextuelle (ouvrir la 419 définition de cette fonction, ouvrir la documentation de celle-là). Nous avons repris ce principe pour les langages visuels~: Dans la 420 définition d'un bloc, il est possible d'ouvrir sur place ou à côté les définitions des sous-blocs. 421 422 Une autre solution consiste à utiliser une interface «fish-eye»~: les objets au centre de l'écran ont une taille normale, et sont de plus en 423 plus petits à mesure qu'ils approchent du bord. Une variante est l'interface «zoom», utilisée notamment dans certains jeux 424 vidéos\cite{mutant-storm} pour permettre au joueur de focaliser son attention sur les ennemis les plus proches, ou bien avoir une vue 425 d'ensemble, et dans le logiciel de prises de notes Project Cecily\cite{project-cecily}. 426 427 Plusieurs recherches ont été menées concernant l'utilisation de l'espace à l'écran par les langages visuels, une bibliographie référencant 428 plusieurs papiers sur ce sujet est disponible à \cite{biblio-vpl-a-screen-real-estate}. 429 430 431 \subsection[Manque d'expressivité]{Manque d'expressivité des langages de programmation existants} 432 433 L'utilisation fréquente de «design patterns» ou partons de conception dans les langages de programmation existants peut être considérée 434 comme un indicateur de défauts dans ces langages\cite{design-patterns-failure}~: s'il y a besoin d'utiliser le design pattern $x$, c'est 435 que le langage ne permet pas d'utiliser les concepts vehiculés par $x$ de manière plus élégante, c'est donc un manque d'expressivité sur ce 436 point. En général, la manière la plus élégante d'utiliser un concept, c'est quand il est de «première classe». 437 438 La solution que nous proposons pour un autre problème d'expressivité, celui des Langages Spécifiques à un Domaine (Section \ref{sec:dsl}, 439 page \pageref{sec:dsl}), qui était de permettre aux blocs de revêtir n'importe quelle apparence, est aussi une solution aux problèmes 440 soulignés par les Design Patterns. En effet, pour peu que le langage propose de l'introspection et que les éléments de base du langage 441 soient (réellement) de première classe, à savoir les blocs, les ports et les connexions, il est possible de transformer un grand nombre de 442 concepts en concepts de (pseudo-)première classe. 443 444 Par exemple, si l'on souhaite implémenter le concept des singletons, on rajoutera par introspection à chaque bloc utilisant ce concept un 445 faux port d'entrée qui représentera directement le singleton. Ou bien on encapsulera tous les blocs représentant des variables qui doivent 446 être uniques, avec une structure qui s'assurera que tout accès à ces blocs se fera sur une unique instance. 447 448 \subsection{Réutilisabilité} 449 450 \subsubsection{Programmation par composants} 451 452 Le paradigme du dataflow partage de nombreux points communs avec le paradigme de la programmation orientée composants. Cette approche vise à 453 augmenter la ré-utilisabilité du code en le structurant sous forme de composants qui communiquent entre eux. Dans le paradigme du dataflow, 454 les composants sont clairement visibles~: ce sont les blocs, et ils communiquent entre eux à travers leurs ports, par le biais de 455 connexions. 456 457 \subsubsection{Commandes Unix} 458 459 Ce principe de composants isolés communiquant au travers d'interfaces pré-définies se retrouve aussi dans l'architecture Unix. Un des 460 principes de la philosophie unix est «Do one thing, and do it well», ainsi sous Unix, plein de petis programmes différents font chacun une 461 action bien précise, simple. Des actions plus complexes sont réalisées en connectant la sortie de certains programmes à l'entrée d'autres, 462 en général avec un «pipe» (tuyau). 463 464 Ce principe a même été poussé jusqu'à faire un navigateur modulaire, suivant la philosophie Unix, dont la partie chargée d'afficher les 465 pages web est complètement dissociée de la partie qui gère les autres fonctionnalités (historique, boutons de navigation, \dots). 466 467 Cependant, cette approche est très limitée, car le seul type de données que des programmes peuvent échanger au travers de pipes ou de 468 sockets, c'est un flux d'octets augmenté d'un marqueur de fin (EOF). Il n'y a pas de communication hors-bande, pas de structuration des 469 données. Cela pose des problèmes d'encapsulation (au sens des protocoles de communication~: comment envoyer plusieurs flux en parallèle?), 470 d'échappement, et généralement de sérialisation des données -- alors qu'on transfère des données d'un programme à l'autre, sur le même 471 système. 472 473 Le paradigme du dataflow résoud ces problèmes en permettant de faire transiter à travers les connexions entre blocs des flux typés, plutôt 474 que de simples octets. De plus, chaque bloc possède plusieurs ports de sortie, ce qui permet de sélectionner la donnée voulue. Sous Unix, 475 pour récupérer la date de modification d'un fichier, il faut découper la sortie de la commande \texttt{ls -l} avec d'autres outils, comme 476 \texttt{cut}. En dataflow, il suffit de faire une connexion uniquement avec le port de sortie intitulé «taille du fichier». 477 478 %\begin{itemize} 479 %\item Héritage partiel (cf. tiddlywiki) 480 %\end{itemize} 481 482 %\begin{figure}[htbp] 483 % \centering 484 % \includegraphics[height=7cm]{dark-tower-of-meta-levels} 485 % \caption{Aziz faces the Dark Tower of Meta-levels}%\footnote{http://www.phyast.pitt.edu/~micheles/scheme/scheme22.html} 486 % % On http://www.phyast.pitt.edu/~micheles/scheme/scheme22.html 487 %\label{fig:dark-tower-meta-levels} 488 %\end{figure} 489 490 \subsubsection{Conflits de nommage} 491 Les conflits de nommage sont une grosse source de souci dans les langages de programmation textuels conventionnels. Certains utilisent des 492 espaces de nommage pour réduire les risques de conflits, d'autres utilisent les clôtures pour limiter la portée des noms (c'est ce qui est 493 couramment utilisé en JavaScript, par exemple). 494 495 Nous proposons une approche différente, qui consiste à stocker avec chaque fonction définie un identifiant unique, comme si le code était 496 stocké dans une base de données. Les appels de fonction font alors référence (de manière cachée) à l'identifiant unique, et non pas au «nom 497 usuel» de la fonction. Cela rend le langage insensible aux conflits de nommage, et robuste aux changements des noms de variables ou de 498 fonction. D'autres personnes ont proposé de stocker du code Java dans une base de données\cite{scid}. 499 500 \section{Formalisation du langage} 501 502 Dans cette section, nous allons essayer de trouver quelle est la nature, l'essence d'un programme, de manière à pouvoir définir plus 503 formellement quelle est la nature mathémathique des programmes de notre langage, qui sont composés de blocs polymorphes à l'affichage, de 504 ports appartennant à ces blocs, et de liens entre ces blocs. 505 506 \subsection{Programme en dataflow} 507 508 Examinons un programme simple exprimé dans le paradigme du dataflow~: 509 510 \begin{figure}[h] 511 \centering 512 \begin{tikzpicture} 513 \bloc[t]{+1/a+b}{ab}{c} 514 \tikzset{+2/.style={below of=+1,matrix anchor=north}} 515 \bloc[t]{+2/a+b}{ab}{c} 516 % \tikzset{b2/.style={right of=b1-out-d,matrix anchor=b2-in-x.center}} 517 % \bloc[t]{b2/\frac{x\times y}{z}}{{x}{y}{z}}{{t}} 518 519 \tikzset{e1/.style={left of=+1-in-a,matrix anchor=e1-out-val.center,input-bloc}} 520 \bloc[t]{e1/e_1}{}{{val/}} 521 \draw (e1-out-val) -- (+1-in-a); 522 523 \tikzset{e3/.style={left of=+2-in-b,matrix anchor=e3-out-val.center,input-bloc}} 524 \bloc[t]{e3/e_3}{}{{val/}} 525 \draw (e3-out-val) -- (+2-in-b); 526 527 \tikzset{e2/.style={at=($ .5*(e1-out-val) + .5*(e3-out-val) $),matrix anchor=e2-out-val.center,input-bloc}} 528 \bloc[t]{e2/e_2}{}{{val/}} 529 530 \node[coordinate] (between-+1-+2) at ($ .5*(+1-in-b) + .5*(+2-in-a) $) {}; 531 \node[coordinate] (connect-e2-+1-+2) at ($ .5*(between-+1-+2) + .5*(e2-out-val) $) {}; 532 533 \draw (e2-out-val) -- (connect-e2-+1-+2); 534 \draw (connect-e2-+1-+2) |- (+1-in-b); 535 \draw (connect-e2-+1-+2) |- (+2-in-a); 536 537 538 \shorthandoff{:} 539 \draw[->] (+1-out-c) -- ++(1,0) node[coordinate,label=above:\tiny$e_1+e_2$] {}; 540 \draw[->] (+2-out-c) -- ++(1,0) node[coordinate,label=below:\tiny$e_2+e_3$] {}; 541 \shorthandon{:} 542 \end{tikzpicture} 543 \caption{Un programme simple en dataflow.} 544 \label{fig:simple-dataflow} 545 \end{figure} 546 547 Ce programme a trois entrées ($e_1$, $e_2$, $e_3$), et deux sorties ($e_1+e_2$ et $e_2+e_3$). 548 549 \subsection{Caractéristiques du programme} 550 La question à se poser maintenant est ~: 551 \begin{figure}[h!] 552 \centering 553 Qu'est-ce qui définit ce programme ? 554 \end{figure} 555 556 Ou, comme le disait un des collègues de Joe~Armstrong~\cite{what-are-the-inputs}\nocite{coders-at-work}~: 557 558 \begin{figure}[h!] 559 \centering 560 \begin{quotation} 561 «~A program is a black box. It has inputs and it has outputs. And there is a functional relationship between the inputs and the outputs. What are the inputs to your problem ? What are the outputs to your problem ? What is the functional relationship between the two ?~» 562 \end{quotation} 563 \end{figure} 564 565 Ce programme est constitué 566 \begin{itemize} 567 \item d'entrées, 568 \item de sorties, 569 \item d'un graphe étiqueté exprimant la relation entre les sorties et les entrées grâce à des fonctions ($+$) qu'on suppose déjà définies, 570 \item d'une sémantique d'évaluation, qui donne une signification au graphe, 571 \item d'une représentation graphique, 572 \item Et pour l'exécuter pour de bon, il faut une machine réelle vers laquelle on peut compiler le programme (ou un interpréteur fonctionnant sur cette machine). 573 \end{itemize} 574 575 \subsection{Généralisation} 576 Si on généralise ce résultat, on peut dire qu'un programme est défini par une structure de données abstraite (on n'a pas besoin de connaître la représentation en mémoire de cette structure), qui peut contenir des entrées, des sorties, un arbre (ou graphe) syntaxique, etc. Cette structure peut être représentée sous forme d'un programme dont l'entrée est la désignation d'une partie de la structure que l'on souhite accéder, et dont la sortie est la partie en question. 577 578 La représentation graphique ou textuelle du programme peut être assurée par un autre programme. 579 580 Sa sémantique d'évaluation peut être définie par une machine abstraite, dont les (méta-)entrées sont le programme, ainsi que des entrées pour le programme, et dont les (méta-)sorties sont les sorties que le programme devrait avoir. Tiens ? Entrées, sorties, une relation fonctionnelle (les sorties sont celles du programme pour ses entrées), \dots\ Eh oui, notre machine abstraite, c'est-à-dire notre sémantique d'évaluation est bel et bien un programme elle aussi. 581 582 De même, la machine réelle vers laquelle on éspère pouvoir compiler le programme, peut être modélisée par un programme. Pendant que nous y sommes, rien ne justifie la présence de la machine réelle, car la machine abstraite pourrait très bien être la même que celle qui exécute le programme. C'est le cas par exemple si notre langage est le code machine d'un certain processeur : L'octet 0x12345678 a pour signification «diviser l'accumulateur par 2», c'est une définition de la sémantique du langage, et à la fois une définition de la machine qui exécute le programme. 583 584 La machine abstraite n'a donc pas besoin d'être si abstraite que ça, et pourrait être n'importe quelle machine, et il pourrait même y avoir plusieurs machines qui spécifient la sémantique du langage (de manière redondante, pour avoir le choix, et pour que ces définitions se vérifient mutuellement). 585 586 Et, pour continuer sur cette voie, il peut aussi y avoir plusieurs représentations syntaxiques (textuelle, avec ou sans coloration, graphique, \dots). 587 588 On a donc les équations suivantes dans le cas simple (une seule machine, une seule représentation) : 589 590 \begin{align} 591 \text{Programme} &= \left\lbrace 592 \begin{array}{rl} 593 &\text{Type de données abstrait (ADT)}\\ 594 + &\text{Machine abstraite (sémantique)}\\ 595 + &\text{Représentation} 596 \end{array} 597 \right\rbrace\\ 598 \text{Programme} &= \text{Programme} + \mathrm{Programme} + \mathrm{Programme}\\ 599 \text{Programme} &= 3 \times \text{Programme} 600 \end{align} 601 602 \subsection{Base} 603 604 Nous voilà bien avancés\dots\ Un programme est un programme. C'est donc une définition récursive. Et toute définition récursive doit avoir une base, et des règles pour générer de nouveaux éléments. Nous venons de définir les règles, cherchons les bases possibles~: 605 \begin{itemize} 606 \item Machine de Turing 607 \item Lambda-calcul 608 \item Langage mathémathique 609 \end{itemize} 610 611 Le lambda-calcul et la machine de Turing sont 612 équivalents\cite{lambda-calculus-wikipedia}$\vphantom{X}^{,}$\footnote{Bien qu'ils ne 613 semblent pas être totalement équivalents\cite{lambda-turing-equivalence}~: \quote{However, [Lambda Calculus] is not a model of computation for we 614 cannot calculate an upper bound on resource consumption of its reduction steps without resorting to another model of computation, such 615 as [Turing Machines] (according to Yuri Gurevich).}}, 616 % http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm/#comment-35342 617 % A lambda calculus program does describe a computable function. However, LC is not a model of computation for we cannot calculate an upper 618 % bound on resource consumption of its reduction steps without resorting to another model of computation, such as TMs (according to Yuri 619 % Gurevich). But, models of computation don’t end there, either. 620 par contre le langage mathémathique permet d'exprimer des fonctions non-calculables, des ensembles infinis, et tout un tas de choses 621 obscures. Comme nos machines physiques actuelles sont une version bâtarde des machines de Turing (qui n'ont pas de limite sur la quantité de 622 mémoire disponible, contrairement aux nôtres), il semble sage de laisser de côté le langage mathémathique (pour l'instant, lorsque le 623 langage aura gagné en maturité, peut-être qu'il sera temps de l'ajouter). 624 625 L'équivalence $\lambda$-calcul vs. Turing nous laisse le choix pour l'implémentation de notre première machine à partir de laquelle les autres seront définies, directement ou indirectement. Explorons donc la suite du problème avant de prendre une décision. À terme, le meilleur sera probablement d'implémenter les deux, comme base, et de les définir mutuellement l'une à partir de l'autre, pour avoir une vérification. 626 627 \subsection{Graphe} 628 Du point de vue de notre langage, on peut dire qu'un programme est un graphe dont les noeuds sont étiquetés (les noms ou identifiants des blocs), et dont les arcs sont étiquetés à chaque extrémité (les noms des deux ports auxquels le lien est connecté). Les programmes sont donc des graphes généralisés. 629 630 % TODO !!!!!!!!!!!! 631 % Schéma PGF (Quel schéma ???) 632 633 % Preuve de complétude de Turing : un graphe = des noeuds connectés par des arcs, un noeud = l'arc NULL ou qqch du genre. <=> $\lambda(\lambda(\dots))$. 634 635 636 637 \appendix 638 639 \nocite{*} 640 \bibliographystyle{unsrt} 641 \bibliography{biblio} 642 643 %%%%%%%%%% 644 645 \long\def\commentaire#1{} 646 647 \commentaire{ 648 \part{Implémentation} 649 %Pour l'implémentation, nous nous limiterons à un sous-ensemble purement fonctionnel du langage défini dans les sections précédentes. 650 651 \section{Spécification fonctionnelle} 652 653 \part{Annexes} 654 %\section{Notes} 655 %\subsection{notes} 656 %\begin{itemize} 657 %\item gruntnetwork.com 658 %\item La thèse sur la programmation par l'exemple 659 %\item vidéo alan kay 660 %\end{itemize} 661 662 %\section{Étude de l'existant} 663 %Preuves 664 665 % Taxonomie (vltax.pdf): étudier l'utilité des différentes catégories. 666 667 668 \subsection{Notes pour la suite\dots} 669 670 Cette section est à supprimer 671 672 % Suite 673 %Partir d'un plus haut niveau pour se faciliter la tâche : une VM simple en JahvaScript 674 %Définir une api de base (?), c'est une machine virtuelle sur laquelle s'exécuteront les programmes 675 % - Structures de données 676 % - Dataflow 677 678 679 %%% 680 %X Définir le langage grunt par rapport à une VM simple (et cette VM à partir d'une machine de Turing) 681 % Prendre un programme grunt, et l'expanser au maximum (FORTH). Descendre jusqu'au niveau des transistors ou au moins des bascules. 682 683 Nous allons prendre un programme en dataflow, et le déconstruire le plus possible, afin de voir quelles sont les «primitives» sémantiques nécessaires à notre langage. Bien que FORTH n'ait pas à proprement parler de primitives, il a lui aussi une sémantique (chaque mot est expansé en la suite de mots le définissant, jusqu'à arriver au code machine). 684 685 686 Il faut définir un bloc eager-evaluation, qui prend en paramètre un graphe, et 687 \begin{itemize} 688 \item Soit le réécrit (compilation) 689 \item Soit l'évalue (interprétation) 690 \end{itemize} 691 Dans le cas où on compile, on aura une "instruction" call-bloc 692 693 call-bloc prend en paramètre des fonctions permettant de calculer ses paramètres, ainsi que les paramètres eux-mêmes. 694 \begin{itemize} 695 \item En évaluation paresseuse, on n'évalue les paramètres que s'ils sont nécessaires. 696 \item En évaluation «eager», on évalue les paramètres au début de l'appel du bloc, et on stocke leur valeur pour une future utilisation (ou non). 697 \item Pour une macro, on stocke juste les paramètres eux-mêmes (avec leur fonction d'évaluation, s'il y en a une). 698 \end{itemize} 699 700 TODO première ligne de \section{Formalisation du langage} 701 } 702 703 \end{document}