Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Will Eat Itself

Code Will Eat Itself

To prove the undecidability of the halting problem you have to feed a program its own source code as input. Sometimes this can be done by reading data from the filesystem, but Kleene’s recursion theorem guarantees that a program can always calculate its own source code without relying on external storage.

This talk shows how to extend any Ruby program with a local variable containing its own source.

A lightning talk given at Scottish Ruby Conference 2013 (http://lanyrd.com/2013/scotruby/). There’s a video of this talk at https://tomstu.art/impossible-programs. This talk is adapted from chapter 8 of Understanding Computation (http://computationbook.com/).

Tom Stuart

May 13, 2013
Tweet

More Decks by Tom Stuart

Other Decks in Programming

Transcript

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

    View Slide

  2. 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?

    View Slide

  3. 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.

    View Slide

  4. x = 1
    y = 2
    puts x + y

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. >> 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

    View Slide

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

    View Slide

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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. 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:

    View Slide

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

    View Slide

  16. 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

    View Slide

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

    View Slide

  18. 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:

    View Slide

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

    View Slide

  20. 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.

    View Slide

  21. 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.

    View Slide

  22. 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.

    View Slide

  23. 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.

    View Slide

  24. 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!

    View Slide

  25. puts program

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. >> 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

    View Slide

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

    View Slide

  32. This technique works for any program.

    View Slide

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

    View Slide