This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Concluding Continued Continuations
Feed Title: Michael Lucas-Smith
Feed URL: http://www.michaellucassmith.com/site.atom
Feed Description: Smalltalk and my misinterpretations of life
Now, to wrap it up. I'll quickly finish off the example I was discussing at the start of this thread. This isn't the final post I'll be making about continuations. There will be more to come, so if things aren't entirely clear now, here's hoping I can make more sense in the future.
We expanded it out to have subexpressions assigned to variables. These variables do not mean 'variables', but may in fact later turn in to registers, as some of them do.
myMethod: myInstVar
| a b c |
a := myInstVar + 1.
b := a printString.
c := Transcript.
c cr.
c show: b
A slight variation to last time, as this time I took the cascade in to account (the ; for those people unfamiliar with the term) and assigned it to another variable c
We then add in our continuation points. I was using a funky syntax for them, which is {}. I'll continue to do that.
myMethod: myInstVar
| a b c |
a := myInstVar + 1.
{c1} b := a printString.
{c2} c := Transcript.
{c3} c cr.
{c4} c show: b
In Smalltalk, every method returns something. We we are guarantee'd to lose eax at the point of a call. With this in mind, lets plonk in the ASM for the first part of our code.
// at this point, when called, eax will hold myInstVar!
push edx // put edx on the stack, it's our exit continuation and we're calling other methods
inc eax
mov edx, {c2}
jmp {method for printString}
c2: mov ebx, eax // tricky here, since ebx is the second parameter for the {c4} call.
mov eax, {pointer to Transcript, it is a global, this may be a method call to find this in a real Smalltalk system}
mov ecx, eax // tricky here, save a copy of Transcript for later, as eax gets destroyed from the call to cr
mov edx, {c4}
jmp {method of cr}
c4: mov eax, ecx
pop edx // suck our exit continuation back in so we can jump to it
jmp {method for show:}
The real tricky code is in handling the registers.. optimising their use. Whenever you cannot optimise a register, you need to store its value somewhere. That may mean on the heap or on the stack. The stack is still a reasonable place to put things.. but you have to do it a -lot- less than in stack passing style.