Slide 1

Slide 1 text

CODE WILL EAT ITSELF @tomstuart / Scottish Ruby Conference / 2013-05-13

Slide 2

Slide 2 text

A Ruby program run from a filesystem happens to be able to read its own source code: program = File.read(__FILE__) But what about Ruby programs that you type straight into IRB? What about compiled languages (Java, C)? What about JavaScript in a browser?

Slide 3

Slide 3 text

Kleene’s recursion theorem roughly : Any computer program can calculate its own source code. This means we can modify any Ruby program to read its own source, without touching the filesystem.

Slide 4

Slide 4 text

x = 1 y = 2 puts x + y

Slide 5

Slide 5 text

program = '...' x = 1 y = 2 puts x + y

Slide 6

Slide 6 text

program = 'program = \'...\'' x = 1 y = 2 puts x + y

Slide 7

Slide 7 text

program = 'program = \'program = \\\'program = \\\\\\\'...\\\\\\\'\\\'\'' x = 1 y = 2 puts x + y

Slide 8

Slide 8 text

>> puts 'Single quotes look like \'this\'.' Single quotes look like 'this'. => nil >> puts %q{Curly brackets look like {this}.} Curly brackets look like {this}. => nil >> puts %q{An unbalanced curly bracket like this} is a problem.} SyntaxError: syntax error, unexpected tIDENTIFIER, expecting end-of-input

Slide 9

Slide 9 text

program = %q{program = %q{program = %q{program = %q{...}}}}} x = 1 y = 2 puts x + y

Slide 10

Slide 10 text

program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{...}}}}}}}}}} x = 1 y = 2 puts x + y

Slide 11

Slide 11 text

program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{...}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} x = 1 y = 2 puts x + y

Slide 12

Slide 12 text

program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{...}}}}}}}}}}}}}}}}}}} }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} x = 1 y = 2 puts x + y

Slide 13

Slide 13 text

program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{program = %q{...}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} x = 1 y = 2 puts x + y

Slide 14

Slide 14 text

Our mistake is to try to put the program literally inside itself. A. Assign the current program’s source to program B. Do whatever other work the program is supposed to do i.e. the code we originally started with We're trying to write the program in two parts:

Slide 15

Slide 15 text

program = %q{program = %q{program = %q{program = %q{...}}}}} x = 1 y = 2 puts x + y A B

Slide 16

Slide 16 text

We can avoid the problem by computing the source dynamically from data we provide. Write a three-part program: A. Assign a string literal to a variable call it data) B. Use that string to compute the whole program’s source and assign it to program C. Do whatever other work the program is supposed to do i.e. the code we originally started with

Slide 17

Slide 17 text

data = %q{...} program = ... x = 1 y = 2 puts x + y A B C

Slide 18

Slide 18 text

A. Store the literal source code of parts B and C in data B. Compute part A's source from data, then concatenate the sources of A, B and C to get program C. Do whatever other work the program is supposed to do i.e. the code we originally started with Here's how to actually do it:

Slide 19

Slide 19 text

data = %q{...} program = ... x = 1 y = 2 puts x + y

Slide 20

Slide 20 text

data = %q{...} program = ... x = 1 y = 2 puts x + y We know most of the source of parts B and C already, so we can partially complete the value of data.

Slide 21

Slide 21 text

data = %q{ program = ... x = 1 y = 2 puts x + y } program = ... x = 1 y = 2 puts x + y We also know that the source of part A is just the string 'data = %q{...}' with the value of data filling the gap between the curly braces, so we can partially complete the value of program too.

Slide 22

Slide 22 text

data = %q{ program = ... x = 1 y = 2 puts x + y } program = "data = %q{#{data}}" + ... x = 1 y = 2 puts x + y Now all that’s missing from program is the source code of parts B and C, which is exactly what data contains, so we can append the value of data to program to finish it off.

Slide 23

Slide 23 text

data = %q{ program = ... x = 1 y = 2 puts x + y } program = "data = %q{#{data}}" + data x = 1 y = 2 puts x + y Finally, we can go back and fix up the value of data to reflect what part B actually looks like.

Slide 24

Slide 24 text

data = %q{ program = "data = %q{#{data}}" + data x = 1 y = 2 puts x + y } program = "data = %q{#{data}}" + data x = 1 y = 2 puts x + y That's it!

Slide 25

Slide 25 text

puts program

Slide 26

Slide 26 text

data = %q{...} program = ... puts program

Slide 27

Slide 27 text

data = %q{ program = ... puts program } program = ... puts program

Slide 28

Slide 28 text

data = %q{ program = "data = %q{#{data}}" + ... puts program } program = "data = %q{#{data}}" + ... puts program

Slide 29

Slide 29 text

data = %q{ program = "data = %q{#{data}}" + data puts program } program = "data = %q{#{data}}" + data puts program

Slide 30

Slide 30 text

>> data = %q{ program = "data = %q{#{data}}" + data puts program } => "\nprogram = \"data = %q{\#{data}}\" + data\nputs program\n" >> program = "data = %q{#{data}}" + data => "data = %q{\nprogram = \"data = %q{\#{data}}\" + data\nputs program\n} \nprogram = \"data = %q{\#{data}}\" + data\nputs program\n" >> puts program data = %q{ program = "data = %q{#{data}}" + data puts program } program = "data = %q{#{data}}" + data puts program => nil

Slide 31

Slide 31 text

data = %q{ program = "data = %q{#{data}}" + data puts program } program = "data = %q{#{data}}" + data puts program ..is a quine. The program...

Slide 32

Slide 32 text

This technique works for any program.

Slide 33

Slide 33 text

THE END @tomstuart / [email protected] / computationbook.com