Skip to content

Instantly share code, notes, and snippets.

@Gadgetoid
Last active March 12, 2016 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gadgetoid/999958ccc28255e6547f to your computer and use it in GitHub Desktop.
Save Gadgetoid/999958ccc28255e6547f to your computer and use it in GitHub Desktop.
Absurdly fudgetastic method of including Python and Ruby in the same file. Will certainly break!
#!/usr/bin/env ruby
x=x\
=begin = 1
print("Hello World, I'm Python!")
'''
=end
puts "Hello World, I'm Ruby!"
=begin
'''
end=1
x \
=end
@Gadgetoid
Copy link
Author

I don't know why I did this, but I felt it should be possible. A quick Google only turned up answers to problems I didn't have, so I chipped away at this slowly- focussing around comment syntax since I figured that would be the likely candidate for abuse.

=begin and =end are used as muti-line comments in Ruby. In most languages they're also the right-hand of a full assignment. Abusing Python's line continuation operator \ ( backslash ) allowed me to trick Python into thinking I was writing:

x=begin

This was a good start, but if you haven't already guessed it yielded me:

NameError: name 'begin' is not defined

To fix this, =begin can be suffixed with an assignment, resulting in:

x=begin=1

which exploits a trick to assign multiple variables with the same value. This is constructed like so:

x\
=begin = 1

This works either because Ruby considers anything ( as long as it's separated by a space ) after =begin to be inside the comment, or just ignores anything else on that line altogether.

However, now Ruby throws an error: '<main>': undefined local variable or method 'x' for main:Object (NameError)

This is because Ruby's loose rules about parentheses lead x to be mistaken for a call to a method when it's on its lonesome. Substitute this for:

x=x

...and it's always interpreted as an assignment to x of a nil value unassigned variable x... Bonkers!

This brings us up to:

x=x\
=begin = 1

Which is an opening Ruby comment that is treated in Python as setting x and begin to 1.

Commenting out all the Ruby code at this point is easy. Just use a multi-line Python comment '''. Triple single or triple double quotes, either will do. You'll usually find these as part of DocStrings in Python.

Now the whole Ruby body of the script is inside a big Python comment, and any Python immediately before the opening comment will be executed in Python but commented out in Ruby.

But we need to seal the deal, or we'll get something like this in Python: SyntaxError: EOF while scanning triple-quoted string literal

So we'll just close that triple-quoted string right up:

=begin
'''
=end

Or not...

    =end
    ^
SyntaxError: invalid syntax

In this instance our =begin is already commented out in Python. But =end isn't. But we can use the same trick we used above, right?

=begin
'''
x\
=end

Damn it. Not quite!

    =end
NameError: name 'end' is not defined

Well, this is an easy fudge though?

=begin
'''
end=1
x\
=end

Yay!

For some reason, this also works. Although I feel it shouldn't:

=begin
'''
x\
=end = 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment