On Mon, 12 Jan 2004, Luke Palmer wrote: > > Well... A Coroutine is a pausable, resumable continuation, right? > > Or basically a closure with a continuation inside it. > > Both of those sentences seem wildly redundant to me. I think we might > be stuck on vocabulary. We're surely both understanding the same thing > in different ways.
Yes. I was "understanding" it in the "wrong" way. :) > A continuation is one snapshot -- it never changes, it never runs. > To invoke the continuation is to take you back to that snapshot and > start running from there. To invoke it a second time is exactly > like invoking it the first time. Thanks. I'd heard this a million times but putting it this way made it click for me. I've been thinking about continuations as if they were like python functions. In python, functions are objects. You can define them interactively at the prompt and then look inside them and see some representation of their bytecode. But with parrot, there's just one big long line of instructions. A .pcc_sub isn't an object, just a little segment of the list of instructions. Okay... Here's a metaphor I'm working on to try and help me understand how to picture all this. It's not finished (see the end). Feedback appreciated: =========== MR PARROT'S NEIGHBORHOOD Mr Parrot lives on a very long street. Each house on the street contains an opcode. His job is to go door to door and follow the instructions of the little ops. Mr Parrot carries with him as much paper as he can carry. Each sheet has 16 boxes on it, and he has eight different stacks of them: int 0..15 int 16..31 num 0..15 num 16..31 str 0..15 str 16..31 # should be "string", I know pmc 0..15 pmc 16..31 He also has about a zillion pockets on him. He can put things in his pockets (and of course keep track of where they are by writing it down in a pmc box). Every once in a while, he goes through his pockets and throws out anything he doesn't need anymore. So starts at the first address, performs the instruction, and then goes to whatever that opcode says. She might ask him to write a number down in one of the boxes ("set I0, 3") or to copy one box to another ("set I0, I1") or an object to keep track of, or something equally simple. Usually when he's done with the op, he just goes next door, but sometimes the op tells him to go somewhere else, either explicitly ("goto label") or based on the values in the boxes ("le I0, I1, label") or the objects in his pockets ("le P0, P1, label"). Often, an op will tell him to copy the top sheet on one (or some or all) of the stacks and put the copy on top ("push") or throw away the top sheet ("pop"). He gets really mad if you tell him to throw away the last sheet, or if a stack gets so big he can't carry it anymore. Every once in a while, the op will tell Mr. Parrot to do something like this: - make copies of all your stacks of paper - put the copies inside a briefcase - write this delivery address on the briefcase - (possibly) write a return address on the briefcase - put the briefcase in your pocket Is that an accurate portrayal of a continuation? ###### Now... I only described the register stacks. In docs/pmc/subs.pod it lays out the differences between the different kinds of Subs. It has this table: Subtype Controlstack PadStack UserStack Warnings ------------------------------------------------------------ Sub - - - C Closure - C - C Continuation C C C C Coroutine C C C C RetContinuation X X X X "C" ... COWed copy is in context "X" ... is in context "-" ... isn't. My problem is that I don't know what a Control stack, pad stack, user stack, and warnings are. Here's my guess: ControlStack { This is another set of smaller papers. One box each. if Mr. Parrot meets a "ret" op, he takes the top sheet and goes to whatever address is on it. When we call a Sub, we write the return address on the top sheet. Same with a closure. ** I don't understand what happens here when we call a continuation. } PadStack { Hmm. Does this mean lexical pads? In which case, it's a list of friendly names that he uses to remind him which box or pocket a particular thing is in. } UserStack { By process of elimination, this would be the eight register stacks? } Warnings { ** Beats me. Is this for holding exception handlers? } Final questions: What's a context? How would I picture Eval? Does that involve building new houses? > A coroutine is like a variable that holds continuations, and updates > itself whenever it "yields". I guess that's the best way I can put > it with my affliction against coming up with good similes. Well, you just saw my attempt. I understand what a coroutine does, but I'm still not sure how to picture it in terms of Mr Parrot's world. Obviously it's a briefcase of some kind. A Sub isn't a briefcase. For a sub, he just writes a return address on the control stack and then goes somewhere. Invoking a sub is really the same as firing off a "push this address on the ret stack" op and then doing a goto. Calling a continuation is saying: "throw away all your papers, and start over with copies of the ones in this briefcase." The class tree in subs.pod is confusing to me: Sub Closure Continuation Coroutine Eval RetContinuation For a closure, he has a briefcase but it only contains an old copy of the pad stack. So he can open up the briefcase and use the old pad stack to mess around with variables that don't have names on his usual stacks anymore. But when he meets a "ret" op, he knows to put the old pad stack back in the briefcase and go back tot he normal one. That step never happens with a continuation. For a continuation, nothing ever goes back in the briefcase, because a continuation briefcase also contains the control stack. So when he meets a "ret" he uses the old copy of the control stack. But I suppose it makes more sense if, for a closure, the control stack stored the return address and then stored a note that said "hey! remember to put the pad stack back in the briefcase"... Calling a coroutine though is different. Each time you call one, Mr Parrot SWAPS what's in his hands for what's in the briefcase. At least, I think that's what swap_context() does. I'm not sure I understand why he does that. :) > But it's easy to implement a loop using a single continuation. Like > this: > > > newsub $P0, .Continuation, again > again: > # ... loop body > invoke $P0 Sure. So the stacks are always the same every time Mr Parrot reaches "again:", but the objects in his pockets might have changed. He's probably gone on plenty of wonderful adventures since the last time he was there, and had a real effect on the neighborhood, but he doesn't remember any of it. :) Whew... I didn't mean to write so much... But it seems like this metaphor might make a good user friendly intro to parrot internals... (Assuming I got it right) Sincerely, Michal J Wallace Sabren Enterprises, Inc. ------------------------------------- contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --------------------------------------