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/
--------------------------------------

Reply via email to