I can see how while
was able to leverage the no-arg-and-no-vars function-block inlining. That unfortunately means you have to write efficient loops in SC in something similar to C89/C90 style with the loop var declared outside the loop body.
i = 0; // var must be from outside scope
while { i < 10 } { i = i + 1 }
i
{ while { i < 10 } { i = i + 1 } }.def.dumpByteCodes
/*
BYTECODES: (15)
0 1A PushInstVar 'i'
1 2C 0A PushInt 10
3 E8 SendSpecialBinaryArithMsg '<'
4 F9 00 07 JumpIfFalsePushNil 7 (14)
7 1A PushInstVar 'i'
8 6B PushOneAndAdd
9 07 0A StoreInstVarX 'i'
11 FD 00 0C JumpBak 12 (0)
14 F2 BlockReturn
-> < closed FunctionDef >
*/
It’s the JumpBak
opcode that allows this (not needed for if
).
ArrayedCollection.do
says
do { arg function;
// special byte codes inserted by compiler for this method
var i=0;
while ({ i < this.size }, {
function.value(this.at(i), i);
i = i + 1;
})
}
I’m not sure if the comment refers to just the while
is uses or to do
itself. I’m guessing based on the discussion here it’s just the inner while
that’s being inlined. Actually I’m right, it’s only the while that’s inlined
{ (1..5).do { i = i + 1 } }.def.dumpByteCodes
/*
BYTECODES: (10)
0 64 PushSpecialValue 1
1 6E PushSpecialValue nil
2 2C 05 PushInt 5
4 04 00 PushLiteralX instance of FunctionDef - closed
6 B0 TailCallReturnFromFunction
7 C4 40 SendSpecialMsg 'forSeries'
9 F2 BlockReturn
*/
So it does seem to use an actual function for { i = i + 1 }
which itself is not inlined here. But there’s interestingly no msg-call to any do
, so that’s also inlined… a little bit.
That’s almost the same bytecode generated as if you’d had written
{ forSeries (1, 2, 5) { i = i + 1 } }.def.dumpByteCodes
/*
BYTECODES: (10)
0 64 PushSpecialValue 1
1 65 PushSpecialValue 2
2 2C 05 PushInt 5
4 04 00 PushLiteralX instance of FunctionDef - closed
6 B0 TailCallReturnFromFunction
7 C4 40 SendSpecialMsg 'forSeries'
9 F2 BlockReturn
*/
There’s a special msg for for
-style series generation, but it still
uses an actual function as its last argument, i.e. the function that makes the “block”
is itself not inlined for these constructs.