Quine (informatique)

Un article de Wikipédia, l'encyclopédie libre.
Aller à : navigation, rechercher
Page d'aide sur l'homonymie Pour les articles homonymes, voir Quine.
Un quine écrit est un programme qui écrit son code source.

Un quine est un programme informatique (non vide) qui imprime son propre code source. L'opération qui consiste à ouvrir le fichier source et à l'afficher est considérée comme une tricherie. Plus généralement, un programme qui utilise une quelconque entrée de données ne peut être considéré comme un quine valide. Dans beaucoup de langages de programmation, un quine est une variante de la commande suivante :

Recopier puis recopier entre guillemets la phrase « Recopier puis recopier entre guillemets la phrase »

À titre de défi ou d'amusement[réf. nécessaire], certains programmeurs essaient d'écrire le plus court quine dans un langage de programmation donné.

Étymologie[modifier | modifier le code]

Les quines tirent leur nom du philosophe et logicien américain W. V. Quine (1908 – 2000), qui a étudié en profondeur l'autoréférence indirecte : il a entre autres forgé l'expression paradoxale (et difficilement traduisible)

« 'Yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation. »
c'est-à-dire : « [La citation] 'est fausse lorsque précédée par sa propre citation' est fausse lorsque précédée par sa propre citation ».

Démonstration de l'existence[modifier | modifier le code]

Schéma de la machine QUINE. Le rectangle bleu est la procédure B qui prend en entrée la description d'une machine M (symbolisée par une feuille verte).
Vue d'artiste d'une machine de Turing. Une tête se déplace sur le ruban pour lire et écrire des caractères.

Dans cette section, nous allons démontrer qu'il existe une machine de Turing QUINE qui écrit sa propre description[1]. Une machine de Turing est un modèle de calcul abstrait. Elle lit et écrit des caractères sur un ruban. Tout d'abord, pour tout mot w, on construit la machine printw qui ne tient pas compte de son entrée, efface son ruban et y écrit le mot w. Pour toute machine M, la description de M est notée <M>. Ensuite, on considère la machine descrPrint, qui, pour toute entrée w, retourne <printw>, la description de la machine de Turing printw Maintenant, on construit QUINE :

QUINE(u)
    1. lancer print<B>
    2. lancer B

où B est la machine suivante :

B(<M>)
       2a. lancer descrPrint(<M>)
       2b. concaténer le résultat avec <M>

En exécutant, QUINE(u), l'étape 1 écrit <B> sur le ruban. L'étape 2 lance B(<B>). L'étape 2a lance descrPrint(<B>) et écrit <print<B>> sur le ruban. L'étape 2b finit avec <print<B>B> sur le ruban. Il s'agit de la description de QUINE.

On démontre le théorème de récursion de Kleene en remplaçant l'instruction 2b par <MR> où R la suite du programme. D'autre part, le théorème de récursion de Kleene implique l'existence d'un quine pour tout langage de programmation Turing-complet.

Exemples[modifier | modifier le code]

Langages de programmation[modifier | modifier le code]

Ada[modifier | modifier le code]

Remarque : des sauts de ligne et des espaces ont été ajoutés pour faciliter la lecture.

with Ada.Text_Io;
procedure Quine is 
  S:String:="with Ada.Text_Io;procedure Quine is S:String:=X;G:Character:=Character'Val(34);
             function F return String is begin for I in S'Range loop 
             if S(I)='X' then return S(S'First..I-1)&G&S&G&S(I+1..S'Last);end if;
             end loop;end;begin Ada.Text_Io.Put_Line(F);end;";
  G:Character:=Character'Val(34);
  function F return String is 
  begin 
    for I in S'Range loop 
      if S(I)='X' then return S(S'First..I-1)&G&S&G&S(I+1..S'Last);end if;
    end loop;
  end;
begin 
  Ada.Text_Io.Put_Line(F);
end;

BASIC[modifier | modifier le code]

10 C=": PRINT CHR(49)+CHR(48)+CHR(32)+CHR(67)+CHR(61)+CHR(34)+C+CHR(34)+C":
   PRINT CHR(49)+CHR(48)+CHR(32)+CHR(67)+CHR(61)+CHR(34)+C+CHR(34)+C

Batch (MS-DOS)[modifier | modifier le code]

  @echo off
  %1 %2
  call %0 goto e %%
  call %0 goto e %%3 echo.%%4
  echo :f
  goto f
  :e
  echo.%4@echo off
  echo.%4%31 %32
  echo.%4call %30 goto e %3%3
  echo.%4call %30 goto e %3%33 echo.%3%34
  echo.%4echo :f
  echo.%4goto f
  echo.%4:e
  :f

Bourne shell (sh)[modifier | modifier le code]

  #!/bin/sh
  quine () {
  echo -e "#!/bin/sh\n$1"
  echo "quine '$1'"
  }
  
  quine 'quine () {
  echo -e "#!/bin/sh\\n$1"
  echo "quine \047$1\047"
  }
  '

Brainfuck[modifier | modifier le code]

Remarque : il devrait s'agir d'une ligne de code continue, mais des retours à la ligne ont été ajoutés pour "faciliter" la lecture.

 ->+>+++>>+>++>+>+++>>+>++>>>+>+>+>++>+>>>>+++>+>>++>+>+++>>++>++>>+>>+>++>++>
 +>>>>+++>+>>>>++>++>>>>+>>++>+>+++>>>++>>++++++>>+>>++>+>>>>+++>>+++++>>+>+++
 >>>++>>++>>+>>++>+>+++>>>++>>+++++++++++++>>+>>++>+>+++>+>+++>>>++>>++++>>+>>
 ++>+>>>>+++>>+++++>>>>++>>>>+>+>++>>+++>+>>>>+++>+>>>>+++>+>>>>+++>>++>++>+>+
 ++>+>++>++>>>>>>++>+>+++>>>>>+++>>>++>+>+++>+>+>++>>>>>>++>>>+>>>++>+>>>>+++>
 +>>>+>>++>+>++++++++++++++++++>>>>+>+>>>+>>++>+>+++>>>++>>++++++++>>+>>++>+>>
 >>+++>>++++++>>>+>++>>+++>+>+>++>+>+++>>>>>+++>>>+>+>>++>+>+++>>>++>>++++++++
 >>+>>++>+>>>>+++>>++++>>+>+++>>>>>>++>+>+++>>+>++>>>>+>+>++>+>>>>+++>>+++>>>+
 [[->>+<<]<+]+++++[->+++++++++<]>.[+]>>[<<+++++++[->+++++++++<]>-
 .------------------->-[-<.<+>>]<[+]<+>>>]<<<[-[-[-[>>+<++++++[->+++++<]]>++++
 ++++++++++<]>+++<]++++++[->+++++++<]>+<<<-[->>>++<<<]>[->>.<<]<<]

C[modifier | modifier le code]

#include<stdio.h>
int main(){char*a="#include<stdio.h>%cint main(){char*a=%c%s%c;printf(a,10,34,a,34);}";printf(a,10,34,a,34);}

C++[modifier | modifier le code]

Remarque : des sauts de ligne ont été ajoutés pour faciliter la lecture. Tout ce qui se trouve en dessous de #include <iostream> s'écrit en une seule ligne.

 #include <iostream>
 int main(){int i;char t[2];t[0]=0x00;char *v,*w;v=(char*)malloc(10);w=(char*)malloc(9);
 t[1]=v[0]=v[9]=w[0]=0x22;v[1]=v[2]=v[7]=v[8]=w[1]=w[2]=0x3C;v[3]=0x75;w[4]=v[4]=0x5B;
 w[5]=v[5]=0x69;v[6]=w[6]=0x5D;w[3]=0x78;w[7]=0x3B;w[8]=0x7D;std::string u[2],x[2];
 u[0]=0x0A;u[1]=v;x[0]=t[0];x[1]=w;for(i=0;i<2;i++)std::cout<<t[i]<<"#include <iostream>"
 <<u[i]<<"main(){int i;char t[2];t[0]=0x00;char *v,*w;v=(char*)malloc(10);w=(char*)malloc(9);
 t[1]=v[0]=v[9]=w[0]=0x22;v[1]=v[2]=v[7]=v[8]=w[1]=w[2]=0x3C;v[3]=0x75;w[4]=v[4]=0x5B;w[5]=v[5]=0x69;
 v[6]=w[6]=0x5D;w[3]=0x78;w[7]=0x3B;w[8]=0x7D;std::string u[2],x[2];u[0]=0x0A;u[1]=v;x[0]=t[0];
 x[1]=w;for(i=0;i<2;i++){std::cout<<t[i]<<"<<x[i];}

C#[modifier | modifier le code]

Remarque : des sauts de ligne ont été ajoutés pour faciliter la lecture.

 using System;
 namespace quine
 {
   class Program
   {
     [STAThread]
     static void Main(string[] args)
     {
       string s = "using System;{0}namespace quine{0}{2}{0}{1}class Program{0}
 {1}{2}{0}{1}{1}[STAThread]{0}{1}{1}static void Main(string[] args){0}{1}{1}{2}{0}{1}{1}{1}
 string s = {4}{6}{4};{0}{1}{1}{1}Console.Write(s, Environment.NewLine, {4}{5}t{4}, {4}{2}
 {4}, {4}{3}{4}, {4}{5}{4}{4}, {4}{5}{5}{4}, s);{0}{1}{1}{3}{0}{1}{3}{0}{3}";
       Console.Write(s, Environment.NewLine, "\t", "{", "}", "\"", "\\", s);
     }
   }
 }

Caml Light[modifier | modifier le code]

let quine programme =
  let guillemet = make_string 1 (char_of_int 34) and
      pnt_virgule = make_string 1 (char_of_int 59) in
    print_endline (programme ^ guillemet ^ programme ^ guillemet ^ pnt_virgule ^ pnt_virgule);
    () in quine "let quine programme =
  let guillemet = make_string 1 (char_of_int 34) and
      pnt_virgule = make_string 1 (char_of_int 59) in
    print_endline (programme ^ guillemet ^ programme ^ guillemet ^ pnt_virgule ^ pnt_virgule);
    () in quine ";;

Common Lisp[modifier | modifier le code]

    (funcall (lambda (x) 
               (append x (list (list 'quote x))))
             '(funcall (lambda (x) 
                          (append x (list (list 'quote x))))))

Forth[modifier | modifier le code]

Remarque : cette quine fonctionne sur tous les systèmes forth.

: q s" 2dup cr 115 emit 34 emit space type 34 emit space type cr"
 2dup cr 115 emit 34 emit space type 34 emit space type cr ;

Haskell[modifier | modifier le code]

 s="main=putStr (['s', '='] ++ show s ++ [';'] ++ s)";main=putStr (['s', '='] ++ show s ++ [';'] ++ s)

Java[modifier | modifier le code]

Remarque : des sauts de ligne ont été ajoutés pour faciliter la lecture.

public class r {public static void main(String[] args) {String p="public class r {
public static void main(String[] args) {",g="\"",n ="System.out.println(p+a+g+p+g+z
+c+g+s+g+g+z+b+g+n+g+z+d+g+s+s+g+z+e+g+z+g+z+'a'+'='+g+a+g+z+'b'+'='+g+b+g+z+'c'+'='
+g+c+g+z+'d'+'='+g+d+g+z+'e'+'='+g+e+g+z+'f'+'='+g+f+g+z+'v'+'='+g+v+g+v+n);}}",s="\\",
z=",",a="String p=",b="n =",c="g=",d="s=",e="z=",f="v=",v=";";System.out.println(
p+a+g+p+g+z+c+g+s+g+g+z+b+g+n+g+z+d+g+s+s+g+z+e+g+z+g+z+'a'+'='+g+a+g+z+'b'+'='+g+b+g+z
+'c'+'='+g+c+g+z+'d'+'='+g+d+g+z+'e'+'='+g+e+g+z+'f'+'='+g+f+g+z+'v'+'='+g+v+g+v+n);}}

Ou encore (la variable 'n' peut être remplacée par 'System.getProperty("line.separator")' pour plus de portabilité):

class Quine{public static void main(String[] args){char n=10;char b='"';String a="class Quine{public static void main(String[] args){char n=10;char b='%c';String a=%c%s%c;System.out.format(a,b,b,a,b,n);}}%c";System.out.format(a,b,b,a,b,n);}}

JavaScript[modifier | modifier le code]

 unescape(q="unescape(q=%22*%22).replace('*',q)").replace('*',q)

Les fonctionnalités du JavaScript permettent cependant de le faire directement :

(function a(){
    return "("+a.toString()+")()";
})()

À partir de la version ES6 :

const f = () => "const f = " + f

LaTeX[modifier | modifier le code]

\documentclass{book}\pagestyle
{empty}\def\a{\ensuremath{\backslash}}\def\f
{\def\b{\a}\def\c{\{}\def\d{\}}\def
\e{\\}\noindent\g\b def\b g\c\def\b{\a b
}\def\c{\a c }\def\d{\a d}\def\e{\a e
\\}\g\}\a begin\{document\}\a f\a end
\{document\}}\def\g{ \b documentclass\c book\d\b pagestyle\e
\c empty\d\b def\b a\c \b ensuremath\c \b backslash\d\d\b def\b f\e
\c \b def\b b\c \b a\d\b def\b c\c \b \c \d\b def\b d\c \b \d\d\b def\e
\b e\c \b \b \d\b noindent\b g\b b def\b b g\b c\b def\b b\c \b a b\e
\d\b def\b c\c \b a c \d\b def\b d\c \b a d\d\b def\b e\c \b a e\e
\b \b \d\b g\b \d\b a begin\b \c document\b \d\b a f\b a end\e
\b \c document\b \d\d}\begin{document}\f\end{document}

OCaml[modifier | modifier le code]

(fun s -> Printf.printf "%s %S;;" s s) "(fun s -> Printf.printf \"%s %S;;\" s s)";;

Pascal[modifier | modifier le code]

 const a='const a=';b='begin write(a,#39,a,#39#59#98#61#39,b,#39#59#10,b) end.';
 begin write(a,#39,a,#39#59#98#61#39,b,#39#59#10,b) end.

En FreePascal :

PROCEDURE q(s:string);BEGIN write(s,#39,s,#39,#59,#69,#78,#68,#46);readln;END;BEGIN q('PROCEDURE q(s:string);BEGIN write(s,#39,s,#39,#59,#69,#78,#68,#46);readln;END;BEGIN q(');END.

Perl[modifier | modifier le code]

 $_=q{$_=q{Q};s/Q/$_/;print};s/Q/$_/;print

Et un mélange shell/Perl :

perl -le '$n=q{perl -le a$n=q{$x};($_=$n)=~s/\141/\47/g;s/\$x/$n/;printa};($_=$n)=~s/\141/\47/g;s/\$x/$n/;print'

PHP[modifier | modifier le code]

<?
$a='chr(60).chr(63).chr(10).chr(36).chr(97).chr(61).chr(39).$a.chr(39).chr(59).chr(10)."echo $a;".chr(10).chr(63).chr(62)';
echo chr(60).chr(63).chr(10).chr(36).chr(97).chr(61).chr(39).$a.chr(39).chr(59).chr(10)."echo $a;".chr(10).chr(63).chr(62);
?>

<?
$a='<?
$a=2;
echo str_replace(1+1,chr(39).$a.chr(39),$a);
?>';
echo str_replace(1+1,chr(39).$a.chr(39),$a);
?>

Ou encore :

<?php
function Esc($s) { return (str_replace(chr(0x27), chr(0x5c).chr(0x27), $s)); }
$aSrc = array(
		'echo("<?php\r\n");',
		'echo(\' function Esc($s) { return (str_replace(chr(0x27), chr(0x5c).chr(0x27), $s)); }\'); echo("\r\n");',
		'echo(\' $aSrc = array(\'); echo("\r\n");',
		'foreach ($aSrc as $x) {',
		' echo(chr(0x09).chr(0x09)."\'".Esc($x)."\',".chr(0x0d).chr(0x0a));',
		'}',
		'echo("\t);\r\n");',
		'foreach ($aSrc as $x) {',
		' echo(chr(0x09).$x.chr(0x0d).chr(0x0a));',
		'}',
		'echo("?>\r\n");',
	);
	echo("<?php\r\n");
	echo(' function Esc($s) { return (str_replace(chr(0x27), chr(0x5c).chr(0x27), $s)); }'); echo("\r\n");
	echo(' $aSrc = array('); echo("\r\n");
	foreach ($aSrc as $x) {
	 echo(chr(0x09).chr(0x09)."'".Esc($x)."',".chr(0x0d).chr(0x0a));
	}
	echo("\t);\r\n");
	foreach ($aSrc as $x) {
	 echo(chr(0x09).$x.chr(0x0d).chr(0x0a));
	}
	echo("?>\r\n");
?>

PL1[modifier | modifier le code]

Remarque : ce plus court[réf. souhaitée] quine écrit en PL/I compilera en utilisant la version OS PL/I V2.3.0 du compilateur, mais nécessite une marge à gauche de 1 et l'option COMPILE pour éviter un certain nombre d'erreurs ou d'avertissements.

  %dcl z%z='put edit';proc options(main;q=''''put list(m;do i=1,2;z(q)skip;do j=
  1to 78c=substr(m(i),j;if c=q z(c;z(c;end;z(q',';dcl(c,q)char,m(2)char(99)init(
  '%dcl z%z=''put edit'';proc options(main;q=''''''''put list(m;do i=1,2;z(q)skip;do j=',
  '1to 78c=substr(m(i),j;if c=q z(c;z(c;end;z(q'','';dcl(c,q)char,m(2)char(99)init(',

PostScript[modifier | modifier le code]

 (dup == {dup cvx exec} pop 8 12 getinterval =)
 dup cvx exec

Python[modifier | modifier le code]

En Python 2 :

a='a=%s;print a%%`a`';print a%`a`

En Python 3, print est une fonction :

a='a=%r;print(a%%a)';print(a%a)

Un autre exemple :

 b='\\';g='"';p='%';s="b='%s%s';g='%s';p='%s';s=%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)

Un autre exemple dont les 61 derniers caractères sont communs avec le précédent :

 b,g,p,s='\\','"','%',"b,g,p,s='%s%s','%s','%s',%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)

Ruby[modifier | modifier le code]

 puts <<2*2,2
 puts <<2*2,2
 2

Fonctionnement[2] :

  • puts <<2 : affiche tout le texte suivant jusqu'au 2 final ;
  • *2 : fait ceci deux fois ;
  • ,2 : et imprime la valeur 2 ;
  • le second puts <<2*2,2 est juste du texte, et le 2 final est le délimiteur.

Rust[modifier | modifier le code]

fn main() {
    let p:&[i8] = &[32, 0, 0, 0, 80, 2, -9, 5, 6, -83, 7, -6, 68, 8, -78, 77, -12, 8, 5, -70, 1, -9, 91, 0, -31, 18, -78, 0, 0, 0, 76, -7, 15, -84, 80, -54, -20, 53, 14, -49, 37, -61, 29, -29, 6, 85, -65, 5, 62, -66, 33, 18, -76, 10, -12, 80, -71, 18, -49, 22, 0, 0, 0, 76, -7, 15, -84, 77, 8, -1, -84, 67, -67, 29, -29, 16, 11, -49, 22, 0, 0, 0, 70, 9, 3, -82, 88, -88, 73, 5, -78, 80, -66, 59, 11, -15, 13, -74, 1, -9, 91, -113, 22, 0, 0, 0, 0, 0, 0, 0, 67, -67, 11, 18, -29, 10, 78, -61, -49, 22, 0, 0, 0, 0, 0, 0, 0, 80, 2, -9, 5, 6, -83, 7, -6, 89, 2, -91, 10, -12, 8, 59, -67, 65, 18, -83, 85, -61, -15, -9, 65, 18, -83, 67, 5, -7, 17, -73, 18, -49, 22, 0, 0, 0, 93, -115, 115, -115];
    print!("fn main() {{\n    let p:&[i8] = &{:?};\n", p);
    let mut c = 0;
    for x in p.iter() {
        c += *x;
        print!("{}", (c as u8) as char);
    }
}

Source: [1]

Scheme[modifier | modifier le code]

    ((lambda (x)
            (list x (list (quote quote) x)))
        (quote
            (lambda (x)
                (list x (list (quote quote) x)))))

Tcl[modifier | modifier le code]

  proc Quine {} {
    set n [lindex [info level 0] 0]
    append s [list proc $n [info args $n] [info body $n]] \n [list $n]
    puts $s
  }
  Quine

Unlambda[modifier | modifier le code]

À écrire sur une seule ligne. Il est masqué car contient 12 538 caractères.

Vala[modifier | modifier le code]

using GLib; 
public class Quine { 
    public static void main() { 
        string s = """using GLib; 
            public class Quine { 
                public static void main() { 
                    string s = %c%s%c;
                    stdout.printf(s, 34, s, 34);
                } 
            }"""; 
        stdout.printf(s, 34, s, 34);
    } 
}

Visual FoxPro[modifier | modifier le code]

  CLEAR
  SET TALK OFF
  SET TEXTMERGE ON
  \CLEAR
  \SET TALK OFF
  \SET TEXTMERGE ON

XProc[modifier | modifier le code]

<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="1.0">
 <p:documentation>
   <p>(c) Innovimax 2011 - The first XProc Quine</p>
 </p:documentation>
 <p:output port="result"/>
 <p:identity>
   <p:input port="source">
     <p:inline>
       <p:declare-step version="1.0">
         <p:documentation>
           <p>(c) Innovimax 2011 - The first XProc Quine</p>
         </p:documentation>
         <p:output port="result"/>
         <p:identity>
           <p:input port="source">
             <p:inline/>
           </p:input>
         </p:identity>
         <p:insert match="p:inline" position="first-child">
           <p:input port="source"/>
           <p:input port="insertion"/>
         </p:insert>
       </p:declare-step>
     </p:inline>
   </p:input>
 </p:identity>
 <p:insert match="p:inline" position="first-child">
   <p:input port="source"/>
   <p:input port="insertion"/>
 </p:insert>
</p:declare-step>

XSLT[modifier | modifier le code]

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0">
  <!-- (c) Innovimax 2011 - XSLT 2.0 Quine without DOE -->
  <xsl:variable name="code">
    <xsl:element name="xsl:stylesheet">
      <xsl:attribute name="version" select="'2.0'"/>
      <xsl:comment> (c) Innovimax 2011 - XSLT 2.0 Quine without DOE
</xsl:comment>
      <xsl:element name="xsl:variable">
        <xsl:attribute name="name" select="'code'"/>
        <xsl:element name="foo"/>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'/'"/>
        <xsl:element name="xsl:apply-templates">
          <xsl:attribute name="select" select="'$code'"/>
          <xsl:attribute name="mode" select="'copy'"/>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'@*|node()'"/>
        <xsl:attribute name="mode" select="'copy'"/>
        <xsl:element name="xsl:copy">
          <xsl:element name="xsl:apply-templates">
            <xsl:attribute name="select" select="'@*|node()'"/>
            <xsl:attribute name="mode" select="'copy'"/>
          </xsl:element>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'foo'"/>
        <xsl:attribute name="mode" select="'copy'"/>
        <xsl:element name="xsl:apply-templates">
          <xsl:attribute name="select" select="'$code'"/>
          <xsl:attribute name="mode" select="'el'"/>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'*'"/>
        <xsl:attribute name="mode" select="'el'"/>
        <xsl:element name="xsl:element">
          <xsl:attribute name="name" select="'xsl:element'"/>
          <xsl:element name="xsl:attribute">
            <xsl:attribute name="name" select="'name'"/>
            <xsl:attribute name="select" select="'name()'"/>
          </xsl:element>
          <xsl:element name="xsl:apply-templates">
            <xsl:attribute name="select" select="'@*|*|text()|comment()'"/>
            <xsl:attribute name="mode" select="'el'"/>
          </xsl:element>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'@*'"/>
        <xsl:attribute name="mode" select="'el'"/>
        <xsl:element name="xsl:element">
          <xsl:attribute name="name" select="'xsl:attribute'"/>
          <xsl:element name="xsl:attribute">
            <xsl:attribute name="name" select="'name'"/>
            <xsl:attribute name="select" select="'name()'"/>
          </xsl:element>
          <xsl:element name="xsl:attribute">
            <xsl:attribute name="name" select="'select'"/>
            <xsl:text>'</xsl:text>
            <xsl:element name="xsl:value-of">
              <xsl:attribute name="select" select="'.'"/>
            </xsl:element>
            <xsl:text>'</xsl:text>
          </xsl:element>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'text()'"/>
        <xsl:attribute name="mode" select="'el'"/>
        <xsl:element name="xsl:element">
          <xsl:attribute name="name" select="'xsl:text'"/>
          <xsl:element name="xsl:value-of">
            <xsl:attribute name="select" select="'.'"/>
          </xsl:element>
        </xsl:element>
      </xsl:element>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match" select="'comment()'"/>
        <xsl:attribute name="mode" select="'el'"/>
        <xsl:element name="xsl:element">
          <xsl:attribute name="name" select="'xsl:comment'"/>
          <xsl:element name="xsl:value-of">
            <xsl:attribute name="select" select="'.'"/>
          </xsl:element>
        </xsl:element>
      </xsl:element>
    </xsl:element>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:apply-templates select="$code" mode="copy"/>
  </xsl:template>
  <xsl:template match="@*|node()" mode="copy">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" mode="copy"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="foo" mode="copy">
    <xsl:apply-templates select="$code" mode="el"/>
  </xsl:template>
  <xsl:template match="*" mode="el">
    <xsl:element name="xsl:element">
      <xsl:attribute name="name" select="name()"/>
      <xsl:apply-templates select="@*|*|text()|comment()" mode="el"/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="@*" mode="el">
    <xsl:element name="xsl:attribute">
      <xsl:attribute name="name" select="name()"/>
      <xsl:attribute name="select">'<xsl:value-of
select="."/>'</xsl:attribute>
    </xsl:element>
  </xsl:template>
  <xsl:template match="text()" mode="el">
    <xsl:element name="xsl:text">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="comment()" mode="el">
    <xsl:element name="xsl:comment">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Extension[modifier | modifier le code]

Un quine est dit polyglotte quand il est valide dans plusieurs langages simultanément. Différents exemples de tels quines sont disponibles dans les liens externes en bas de page.

Références[modifier | modifier le code]

  1. (en) Michael Sipser, Introduction to the Theory of Computation, Cengage Learning, (ISBN 1285401069, lire en ligne)
  2. (en) « Shortest Ruby Quine [closed] ».

Voir aussi[modifier | modifier le code]

Liens externes[modifier | modifier le code]