# New Ticket Created by Kenneth A Graves
# Please include the string: [perl #23186]
# in the subject line of all future correspondence about this issue.
# http://rt.perl.org/rt2/Ticket/Display.html?id=23186 >
The .pcc_* directives are working for me in terms of implementing
function calls. I want to do something similar for iterator calls.
I've decided to implement iterators using coroutines.
The initial call to the iterator (sending in the parameters) is
identical to a function call, except P0 is a Coroutine PMC instead of a
Sub, and there is an implicit Continuation argument to mark where the
caller wants control to go after the iterator is complete.
Subsequent calls to the iterator are just savetop, invoke, loop around
to the return_from_subroutine label.
Inside the iterator, there are three differences compared to a function:
1) Every register in use needs to be saved to the user stack. (Anyone
have a clean way to do this?)
2) Returning control to the caller is via "invoke", not "invoke P1".
3) When finished, invoke the implicit Continuation mentioned above.
To get this to work with IMCC, the only change I need is to get (2) to
happen. So I added ".pcc_begin_yield" and ".pcc_end_yield", which do
the exact same thing as ".pcc_begin_return" and ".pcc_end_return",
except leaving off the " P1". (For now. Moving the save/restore of (1)
sub into the yield would be nice if I can figure out a way to do it.)
Example code and patch (relative to languages/imcc) attached. If I'm
off in left field compared to how coroutines/iterators were planned to
be supported, someone please say so.
--kag
-- attachment 1 --
url: http://rt.perl.org/rt2/attach/62028/45719/dee7e8/pcc_yield.patch
-- attachment 2 --
url: http://rt.perl.org/rt2/attach/62028/45720/422adf/foo.pir
--- imcc.l.~1.40.~ 2003-07-30 11:00:29.0 -0400
+++ imcc.l 2003-07-31 12:38:42.0 -0400
@@ -153,6 +153,8 @@
".pcc_sub" return(PCC_SUB);
".pcc_begin_return"return(PCC_BEGIN_RETURN);
".pcc_end_return" return(PCC_END_RETURN);
+".pcc_begin_yield"return(PCC_BEGIN_YIELD);
+".pcc_end_yield" return(PCC_END_YIELD);
"prototyped"return PROTOTYPED;
"non_prototyped"return NON_PROTOTYPED;
--- imcc.y.~1.71.~ 2003-07-30 19:00:18.0 -0400
+++ imcc.y 2003-07-31 13:01:50.0 -0400
@@ -409,13 +409,14 @@
%token GLOBAL ADDR CLONE RESULT RETURN POW SHIFT_RIGHT_U LOG_AND LOG_OR
%token COMMA ESUB
%token PCC_BEGIN PCC_END PCC_CALL PCC_SUB PCC_BEGIN_RETURN PCC_END_RETURN
+%token PCC_BEGIN_YIELD PCC_END_YIELD
%token PROTOTYPED NON_PROTOTYPED
%token LABEL
%token EMIT EOM
%token IREG NREG SREG PREG IDENTIFIER STRINGC INTC FLOATC REG MACRO ENDM
%token PARROT_OP
%type type
-%type program sub sub_start emit nsub pcc_sub sub_body pcc_ret
+%type program sub sub_start emit nsub pcc_sub sub_body pcc_ret pcc_yield
%type classname relop
%type labels _labels label statements statement
%type pcc_sub_call
@@ -582,6 +583,22 @@
PCC_END_RETURN '\n' { $$ = 0; }
;
+pcc_yield: PCC_BEGIN_YIELD '\n' {
+Instruction *i, *ins = instructions;
+char name[128];
+if (!ins || !ins->r[1] || ins->r[1]->type != VT_PCC_SUB)
+fataly(EX_SOFTWARE, "pcc_yield", line,
+"pcc_yield not inside pcc subroutine\n");
+$$ = ins->r[1];
+sprintf(name, "#pcc_sub_yield_%d:", line - 1);
+i = _mk_instruction("", name, NULL, 0);
+i = emitb(i);
+i->type = ITPCCSUB | ITLABEL | ITPCCYIELD;
+}
+pcc_returns
+PCC_END_YIELD '\n' { $$ = 0; }
+;
+
pcc_returns: /* empty */{ $$ = 0; }
| pcc_returns '\n'{ if($1) add_pcc_return($0, $1); }
| pcc_returns pcc_return '\n' { if($2) add_pcc_return($0, $2); }
@@ -599,6 +616,7 @@
| MACRO '\n' { $$ = 0; }
| pcc_sub_call{ $$ = 0; }
| pcc_ret
+| pcc_yield
;
labels:/* none */ { $$ = NULL; }
--- instructions.h.~1.24.~ 2003-07-29 11:00:15.0 -0400
+++ instructions.h 2003-07-31 12:53:29.0 -0400
@@ -11,7 +11,8 @@
ITSPILL = 0x40, /* set P31,x ; set x, p31 spilling */
ITEXT = 0x80, /* instruction is extcall in JIT */
ITSAVES = 0x100, /* saveall/restoreall in a bsr */
-ITPCCSUB = 0x200 /* PCC sub call */
+ITPCCSUB = 0x200, /* PCC sub call */
+ITPCCYIELD = 0x400 /* yield from PCC call instead of return */
};
--- pcc.c.~1.1.~2003-07-30 09:42:48.0 -0400
+++ pcc.c 2003-07-31 13:22:15.0 -0400
@@ -48,9 +48,10 @@
expand_pcc_sub_ret(Parrot_Interp interpreter, Instruction *ins)
{
SymReg *