Python 3, no comments or string literals, 106 bytes
I've never liked how comments and string literals let you "turn off" most of your language's syntax in challenges like this, so I wanted to see how far I could golf things without using either comments or string literals. This is what I came up with.
Since I don't have any way to disable the syntactical significance of parentheses, I cannot use the function call operator. Any attempt to do so would result in the reversed code having a closing parenthesis before the first opening parenthesis, which is invalid outside a comment or string literal. I also can't use
def or container literals (aside from unparenthesized tuples), and my access to language features is in general extremely restricted.
One thing I can do is take advantage of Python's operator overloading to call functions implicitly. My ability to define any classes or functions is extremely limited, but fortunately, there are enough tools lying around in the built-in namespace for me to use. Most built-ins don't let me perform the attribute assignment I need to redefine their operator overloads, but (unless Python is run with one of the flags that disables
site importing) the auto-imported
site module adds
exit objects to the built-ins. These objects are instances of non-C classes, so I can reassign their operator overloads.
print lets me use addition to print things, and setting
exit lets me use the unary
+ operator to abort the program before the rest of the code runs. Without setting
__pos__, I would need a bunch of additional code to make sure the "backwards" part of the code can find all the variables and attributes it needs to not fail. With
__pos__, I only need to make sure the "backwards" code is still syntactically valid.
Forward, the code prints
Use quit() or Ctrl-D (i.e. EOF) to exit
Backward, the code prints
Use exit() or Ctrl-D (i.e. EOF) to exit
(The messages are slightly different on Windows. For platform-independent output at the expense of 3 extra bytes, you can replace the middle line with
1 when run forwards and
2 when run backwards.)
I also tried to figure out a way to do this by defining my own class instead of messing with
quit.__class__. I got as far as the following:
class ton:adbmal is one of the very few combinations of class name and class body such that the class statement is syntactically valid backward.
esiar would also have been valid class names (with a different class body, such as
not fi), but
ton is the only one where the reversed name can be part of an expression, giving the most flexibility.
if.1j:adbmal=1j assigns a value to
adbmal to make the class body succeed, while still being syntactically valid backward.
The stuff with
j1 lets me use
j1.ton to refer to my
ton class, which is still a valid expression backward.
At this point, I got stuck. I couldn't figure out how to get my class out of
j1.ton and into a more useful variable. I can't assign attributes on
j1.ton and still have valid syntax backward, so I can't set operator overloads. I also wanted to set
builtins.__build_class__ to my class so I could abuse the
class statement to construct instances without the function call operator, but trying to put
j1.ton on the right side of an assignment produces invalid syntax backward.
If I had been able to name my class something like
tpecxe, I could have used tricks like
b:j1.fi to get the class into an annotation and then
a.__dict__=__annotations__ to get it into
a.b, but I couldn't find any way to get the class statement and the annotation tricks to hook up. Anything that was compatible with the class statement was incompatible with the annotation tricks.
(You might wonder why I didn't abuse
builtins.__build_class__ to call an existing function directly, like
print. I couldn't figure out a way to do that and have the output be deterministic, and I wanted deterministic output.)