The problem is that doing an explicit tailcall of a continuation
without set_params passes the sub's args to the continuation, instead of
no args.  As a result, I was getting weird param count mismatch errors
in cases where I was neither passing nor receiving anything.  (This is
why I hadn't noticed this until Leo turned on param checking by default;
I assume this is longstanding behavior.)

   This brings up a couple of issues:

   1.  For purposes of error checking, Parrot obviously considers that
tailcall passes arguments, as for function calls, even when tail-calling
a continuation in order to effect a return.  Should continuations be
handled specially, or do we want to define that "tailcall" always means
"call"?

   2.  Passing the sub args to a tail-called sub/continuation strikes me
as buggy, but I can't think of a way to fix this without breaking the
"feature" that it is currently possible to call get_params multiple
times.  One such fix is attached.  It works by having parrot_pass_args
"use up" the args and params in the PARROT_OP_get_params_pc case.  Doing
this for the other cases doesn't seem to break anything else, and
strikes me as a good idea; should I make it happen for all
parrot_pass_args calls?

   Alternatively, passing the sub args could be defined as expected
behavior, but that seems error-prone.

   If I hear no objections to flushing "multiple get_params" (nor
exhortations to generalize "using up" the args), I will commit the patch
as-is.

                                        -- Bob Rogers
                                           http://rgrjr.dyndns.org/

Index: src/inter_call.c
===================================================================
--- src/inter_call.c    (revision 11638)
+++ src/inter_call.c    (working copy)
@@ -1082,6 +1082,8 @@
     if (what == PARROT_OP_get_params_pc) {
         dst_pc = interpreter->current_params;
         src_pc = interpreter->current_args;
+        /* the args and params are now 'used.' */
+        interpreter->current_args = NULL;
         interpreter->current_params = NULL;
         action = "params";
     }
Index: t/op/calling.t
===================================================================
--- t/op/calling.t      (revision 11638)
+++ t/op/calling.t      (working copy)
@@ -701,6 +701,9 @@
 bar_ret
 OUTPUT
 
+SKIP: {
+  skip("can't get_params twice any more.", 1);
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "get_params twice");
 .pcc_sub main:
     new P16, .String
@@ -740,6 +743,8 @@
 back
 OUTPUT
 
+} # end of SKIP.
+
 pir_output_is(<<'CODE', <<'OUTPUT', "empty args");
 .sub main :main
     $P0 = new String
@@ -855,20 +860,25 @@
 
 pir_output_is(<<'CODE', <<'OUTPUT', "type conversion - native");
 .sub main :main
-    foo(42, "42", 42.20)
+    foo_int(42, "42", 42.20)
+    foo_float(42, "42", 42.20)
+    foo_string(42, "42", 42.20)
 .end
-.sub foo
+.sub foo_int
     get_params "(0,0,0)", $I0, $I1, $I2
     print_item $I0
     print_item $I1
     print_item $I2
     print_newline
-    # yeah fetch args again
+.end
+.sub foo_float
     get_params "(0,0,0)", $N0, $N1, $N2
     print_item $N0
     print_item $N1
     print_item $N2
     print_newline
+.end
+.sub foo_string
     get_params "(0,0,0)", $S0, $S1, $S2
     print_item $S0
     print_item $S1
@@ -1604,6 +1614,32 @@
 ok 2
 OUTPUT
 
+# this is a regression test for a bug in which tail-calling without set_args
+# used the args of the sub.
+pir_output_is(<<'CODE', <<'OUTPUT', "tail explicit continuation, no args");
+.sub main :main
+    .local string result
+    result = "not ok 2\n"
+    .local pmc cont
+    cont = new .Continuation
+    set_addr cont, cont_dest
+    bar(cont, "ok 1\n")
+    print "oops\n"
+cont_dest:
+    print "ok 2\n"
+.end
+
+.sub bar
+    .param pmc cc
+    .param string s
+    print s
+    tailcall cc
+.end
+CODE
+ok 1
+ok 2
+OUTPUT
+
 pir_output_is(<<'CODE', <<'OUTPUT', "call evaled vtable code");
 .sub main :main
     .local string s
@@ -2179,5 +2215,5 @@
 /duplicate name/
 OUTPUT
 ## remember to change the number of tests :-)
-BEGIN { plan tests => 86 }
+BEGIN { plan tests => 87 }
 

Reply via email to