For some reason the topic of 2 + 2 = 5 came up today while working with Travis. He pointed out a funny thread where he demonstrated with two methods and a compiler deoptimization that he could make 2+2 = 5 in a Smalltalk image without breaking the rest of the running code.
I thought this was pretty funny - I'm sure people had good chuckles about it back when it was posted too. But I was a bit surprised that it took so much code. I wondered what would happen if you just changed the compiler... so if you're curious, add the following to your image:
AssemblerCodeStream>>sendNoCheck: selector numArgs: nargs
| index |
selector = #+ ifTrue:
[code skip: -2.
(code next: 2) = #[ 75 75 ]
ifTrue: [code skip: -2. ^self pushConstant: 5]].
... keep the rest of the method as is ...
This isn't quite as powerful as Travis's code - since you cannot put 2's in to variables and have them incidently add up to 5, but if you inspect '2+2' you will get 5.
Naturally, we could use this sort of technique for something more useful, like inlining the behaviour of ifNil: and ifNotNil: ... I'd actually rather we had two levels of bytecode - unmodified (exactly represents the code you wrote) and optimized (dynamically inlines, optimizes, unwinds loops, puts in jump statements etc).
May be we'll get there one day.