Created
May 12, 2025 16:33
-
-
Save Gro-Tsen/8ce3f62c0eafe6221ecbd2446a78fb02 to your computer and use it in GitHub Desktop.
A Perl program that prints a Python program that prints back this Perl program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env perl | |
## This Perl program outputs a Python program that outputs this Perl | |
## program. The comments should hopefully make it clear how it all | |
## works and show that this there is nothing tricky going on. | |
## Written by David A. Madore on 2025-05-12. Public Domain | |
## See <http://www.madore.org/~david/computers/quine.html> for more on | |
## the art of writing quines without any tricks. | |
use strict; | |
use warnings; | |
# The variables $data_pre and $data_post contains a textual | |
# representation of everything up to the definition of $data_pre and | |
# everything after the definition of $data_post respectively. | |
# (Presentation is standardized as per print_as_data() below. To | |
# bootstrap the quine, format the representation however you like it, | |
# e.g. with a heredoc, then run the program once and it will | |
# standardize the representation.) | |
my $data_pre = "#! /usr/bin/env perl\n\n## This Perl program outpu" | |
. "ts a Python program that outputs this Perl\n## pr" | |
. "ogram. The comments should hopefully make it cl" | |
. "ear how it all\n## works and show that this there" | |
. " is nothing tricky going on.\n\n## Written by Davi" | |
. "d A. Madore on 2025-05-12. Public Domain\n\n## Se" | |
. "e <http://www.madore.org/~david/computers/quine." | |
. "html> for more on\n## the art of writing quines w" | |
. "ithout any tricks.\n\nuse strict;\nuse warnings;\n\n#" | |
. " The variables \$data_pre and \$data_post contains" | |
. " a textual\n# representation of everything up to " | |
. "the definition of \$data_pre and\n# everything aft" | |
. "er the definition of \$data_post respectively.\n# " | |
. "(Presentation is standardized as per print_as_da" | |
. "ta() below. To\n# bootstrap the quine, format th" | |
. "e representation however you like it,\n# e.g. wit" | |
. "h a heredoc, then run the program once and it wi" | |
. "ll\n# standardize the representation.)\n\n"; | |
my $data_post = "# The variable \$mycode will reconstruct the text" | |
. "ual representation of\n# the entire program. The" | |
. " filehandle \$fh is used to conveniently\n# write " | |
. "into it.\nmy \$mycode;\nopen my \$fh, \">\", \\\$mycode;" | |
. "\n\nsub print_as_code {\n # Write argument as co" | |
. "de (i.e., directly).\n my \$s = shift;\n prin" | |
. "t \$fh \$s;\n}\n\nsub print_as_data {\n # Construct" | |
. " a string declaration of the first argument (the" | |
. "\n # variable being named as given by the seco" | |
. "nd argument).\n my \$s = shift;\n my \$name = " | |
. "shift;\n print \$fh \"my \\\$\$name = \";\n for ( " | |
. "my \$i=0 ; \$i<length(\$s) || \$i==0 ; \$i+=48 ) {\n\tm" | |
. "y \$chunk = substr(\$s, \$i, 48);\n\t# Escape some st" | |
. "uff that needs to be escaped:\n\t\$chunk =~ s/([\\\\\\" | |
. "\"\\\$\\\@\\\%])/\\\\\$1/g;\n\t\$chunk =~ s/\\t/\\\\t/g;\n\t\$chunk" | |
. " =~ s/\\n/\\\\n/g;\n\t\$chunk = \"\\\"\" . \$chunk . \"\\\"\";\n" | |
. "\tprint \$fh \"\\n . \" if \$i>0;\n\tprint \$fh \$chunk;\n" | |
. " }\n print \$fh \";\\n\\n\";\n}\n\n# Reconstruct ou" | |
. "r own code:\nprint_as_code \$data_pre;\nprint_as_da" | |
. "ta \$data_pre, \"data_pre\";\nprint_as_data \$data_po" | |
. "st, \"data_post\";\nprint_as_code \$data_post;\nclose" | |
. " \$fh;\n\n# Now we hold our own code in \$mycode. W" | |
. "hat do we want to do with it?\n\nsub pythonize {\n " | |
. " # Construct a Python program that produces th" | |
. "e given string as\n # output. Nothing smart h" | |
. "appens here!\n my \$s = shift;\n # Read strin" | |
. "g line by line:\n open my \$fh, \"<\", \\\$s;\n p" | |
. "rint \"#! /usr/bin/env python3\\n\";\n while (my " | |
. "\$line = <\$fh>) {\n\tchomp \$line;\n\t# Escape some st" | |
. "uff that needs to be escaped:\n\t\$line =~ s/([\\\\\\\"" | |
. "\\'])/\\\\\$1/g;\n\t\$line =~ s/\\t/\\\\t/g;\n\t# Just outpu" | |
. "t a print command for each line!\n\tprint \"print(\\" | |
. "\"\", \$line, \"\\\")\\n\";\n }\n close \$fh;\n}\n\npyth" | |
. "onize \$mycode;\n"; | |
# The variable $mycode will reconstruct the textual representation of | |
# the entire program. The filehandle $fh is used to conveniently | |
# write into it. | |
my $mycode; | |
open my $fh, ">", \$mycode; | |
sub print_as_code { | |
# Write argument as code (i.e., directly). | |
my $s = shift; | |
print $fh $s; | |
} | |
sub print_as_data { | |
# Construct a string declaration of the first argument (the | |
# variable being named as given by the second argument). | |
my $s = shift; | |
my $name = shift; | |
print $fh "my \$$name = "; | |
for ( my $i=0 ; $i<length($s) || $i==0 ; $i+=48 ) { | |
my $chunk = substr($s, $i, 48); | |
# Escape some stuff that needs to be escaped: | |
$chunk =~ s/([\\\"\$\@\%])/\\$1/g; | |
$chunk =~ s/\t/\\t/g; | |
$chunk =~ s/\n/\\n/g; | |
$chunk = "\"" . $chunk . "\""; | |
print $fh "\n . " if $i>0; | |
print $fh $chunk; | |
} | |
print $fh ";\n\n"; | |
} | |
# Reconstruct our own code: | |
print_as_code $data_pre; | |
print_as_data $data_pre, "data_pre"; | |
print_as_data $data_post, "data_post"; | |
print_as_code $data_post; | |
close $fh; | |
# Now we hold our own code in $mycode. What do we want to do with it? | |
sub pythonize { | |
# Construct a Python program that produces the given string as | |
# output. Nothing smart happens here! | |
my $s = shift; | |
# Read string line by line: | |
open my $fh, "<", \$s; | |
print "#! /usr/bin/env python3\n"; | |
while (my $line = <$fh>) { | |
chomp $line; | |
# Escape some stuff that needs to be escaped: | |
$line =~ s/([\\\"\'])/\\$1/g; | |
$line =~ s/\t/\\t/g; | |
# Just output a print command for each line! | |
print "print(\"", $line, "\")\n"; | |
} | |
close $fh; | |
} | |
pythonize $mycode; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment