||"To be or not to be" – Shakespeare
expression or: aBlock
Last updated at 6:49 pm UTC on 11 September 2017
Sun, Sep 10, 2017 at 3:50 PM
Reply-To: "A friendly place to get answers to even the most basic questions about Squeak."
To: "A friendly place to get answers to even the most basic questionsabout Squeak."
Yes, when the compiler sees
exp or: [ ... ]
then it assumes that "exp" is a boolean-valued expression and generates code that fails if it isn't. Not all Smalltalk compilers perform this optimization, but it is very common. There are a bunch of methods treated like this, ifTrue:ifFalse: is another.
is an interesting slightly different case. The compiler usually optimizes whileTrue: only when both receiver and the argument are blocks.
So, you can define whileTrue: in other classes without any problem.
It avoids a message send and the allocation of a block. These used to be very costly with the interpreter, but even now with a JIT compiler having these get transformed to simple jumps behind the scenes is advantageous.
You can see how it works in class MessageNode, which is used by the Compiler.
In MessageNode class>>initialize all the macro transformations are registered. E.g. for "or:" we have "transformOr:" as a transformer and "emitCodeForIf:encoder:value:" as an emitter. The first transforms the "or:" message into an "ifTrue:ifFalse:" message, and the second emits the proper branch byte code to conditionally skip the blocks:
a or: [b]
gets transformed to
a ifTrue: [true] ifFalse: [b]
and then byte code is emitted like
jump if false to 1
jump to 2
As you can see, the closure is gone completely.