Index: sub.c
===================================================================
RCS file: /cvs/public/parrot/sub.c,v
retrieving revision 1.9
diff -u -r1.9 sub.c
--- sub.c	15 Nov 2002 05:49:06 -0000	1.9
+++ sub.c	15 Nov 2002 21:00:42 -0000
@@ -18,6 +18,7 @@
 save_context(struct Parrot_Interp *interp, struct Parrot_Context *ctx)
 {
     memcpy(ctx, &interp->ctx, sizeof(*ctx));
+    stack_mark_cow(ctx->pad_stack);
     stack_mark_cow(ctx->user_stack);
     stack_mark_cow(ctx->control_stack);
 }
@@ -34,11 +35,10 @@
     /* Using system memory until I figure out GC issues */
     struct Parrot_Sub *newsub = mem_sys_allocate(sizeof(struct Parrot_Sub));
     newsub->init = address;
-    newsub->lex_pad = NULL;
+    newsub->lex_pad = scratchpad_get_current(interp);
     return newsub;
 }
 
-
 struct Parrot_Coroutine *
 new_coroutine(struct Parrot_Interp *interp, opcode_t *address)
 {
@@ -49,7 +49,7 @@
     newco->resume = NULL;
     newco->ctx.user_stack = new_stack(interp);
     newco->ctx.control_stack = new_stack(interp);
-    newco->lex_pad = NULL;
+    newco->lex_pad = scratchpad_get_current(interp);
     return newco;
 }
 
@@ -80,6 +80,15 @@
     }
 
     return ((struct Parrot_Lexicals **)pad->data)[scope_index];
+}
+
+/*
+ * Returns a pointer to the current scratchpad.
+ */
+PMC * 
+scratchpad_get_current(struct Parrot_Interp * interp)
+{
+    return (PMC *)stack_peek(interp, interp->ctx.pad_stack, NULL);
 }
 
 /* 
Index: core.ops
===================================================================
RCS file: /cvs/public/parrot/core.ops,v
retrieving revision 1.228
diff -u -r1.228 core.ops
--- core.ops	15 Nov 2002 05:49:06 -0000	1.228
+++ core.ops	15 Nov 2002 21:00:44 -0000
@@ -3718,8 +3718,7 @@
 
 op new_pad(in INT) {
     PMC * pad;
-    PMC * parent = (PMC *)stack_peek(interpreter,
-				     interpreter->ctx.pad_stack, NULL);
+    PMC * parent = scratchpad_get_current(interpreter);
     pad = scratchpad_new(interpreter, parent, $1);
     stack_push(interpreter, &interpreter->ctx.pad_stack, pad,
                STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
@@ -3727,8 +3726,7 @@
 }
 
 op new_pad(out PMC, in INT) {
-    PMC * parent = (PMC *)stack_peek(interpreter, 
-                                     interpreter->ctx.pad_stack, NULL);
+    PMC * parent = scratchpad_get_current(interpreter);
     $1 = scratchpad_new(interpreter, parent, $2);
     goto NEXT();
 }
@@ -3746,56 +3744,48 @@
 }
 
 op peek_pad(out PMC) {
-    $1 = (PMC*)stack_peek(interpreter, 
-                          interpreter->ctx.pad_stack, NULL);
+    $1 = scratchpad_get_current(interpreter);
     goto NEXT();
 }
 
 op store_lex(in STR, in PMC) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-                                  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     scratchpad_store(interpreter, pad, $1, 0, $2);
     goto NEXT();
 }
 
 op store_lex(in INT, in STR, in PMC) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-                                  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     scratchpad_store_index(interpreter, pad, $1, $2, 0, $3);
     goto NEXT();
 }
 
 op store_lex(in INT, in INT, in PMC) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-                                  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     scratchpad_store_index(interpreter, pad, $1, NULL, $2, $3);
     goto NEXT();
 }
 
 op find_lex(out PMC, in STR) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-				  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     $1 = scratchpad_get(interpreter, pad, $2, 0);
     goto NEXT();
 }
 
 op find_lex(out PMC, in INT) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-				  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     $1 = scratchpad_get(interpreter, pad, NULL, $2);
     goto NEXT();
 }
 
 op find_lex(out PMC, in INT, in STR) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-				  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     $1 = scratchpad_get_index(interpreter, pad, $2, $3, 0);
     goto NEXT();
 }
 
 op find_lex(out PMC, in INT, in INT) {
-    PMC * pad = (PMC *)stack_peek(interpreter,
-				  interpreter->ctx.pad_stack, NULL);
+    PMC * pad = scratchpad_get_current(interpreter);
     $1 = scratchpad_get_index(interpreter, pad, $2, NULL, $3);
     goto NEXT();
 }
Index: include/parrot/sub.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/sub.h,v
retrieving revision 1.9
diff -u -r1.9 sub.h
--- include/parrot/sub.h	15 Nov 2002 05:49:12 -0000	1.9
+++ include/parrot/sub.h	15 Nov 2002 21:00:44 -0000
@@ -59,6 +59,8 @@
 
 PMC * scratchpad_new(struct Parrot_Interp * interp, PMC * base, INTVAL depth);
 
+PMC * scratchpad_get_current(struct Parrot_Interp * interp);
+
 void scratchpad_store(struct Parrot_Interp * interp, PMC * pad, 
                       STRING * name, INTVAL position, PMC* value);
 
Index: classes/sub.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/sub.pmc,v
retrieving revision 1.6
diff -u -r1.6 sub.pmc
--- classes/sub.pmc	6 Nov 2002 13:57:38 -0000	1.6
+++ classes/sub.pmc	15 Nov 2002 21:00:44 -0000
@@ -29,7 +29,17 @@
                             * parameter, but that's not valid.  So
                             * this is totally broken now. */
        SELF->data = new_sub(INTERP, (opcode_t*)address);
-       SELF->flags |= PMC_active_destroy_FLAG;
+       SELF->flags |= PMC_custom_mark_FLAG | PMC_active_destroy_FLAG;
+   }
+
+   PMC* mark (PMC *end_of_used_list) {
+       PMC * pad = ((struct Parrot_Sub *)SELF->data)->lex_pad;
+       if (pad) {
+           return mark_used(pad, end_of_used_list);
+       }
+       else {
+           return end_of_used_list;
+       }
    }
 
    void destroy () {
@@ -45,9 +55,18 @@
    }
 
    void* invoke (void* next) {
+       PMC * pad = ((struct Parrot_Sub *)SELF->data)->lex_pad;
+
+       if (pad) {
+           /* put the correct pad in place */
+           stack_push(INTERP, &INTERP->ctx.pad_stack, pad, 
+                      STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
+       }
+
        /* return address that the interpreter should jump to */
        stack_push(INTERP, &(INTERP->ctx.control_stack), next,
 		  STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
+
        return ((struct Parrot_Sub*)SELF->data)->init;
    }
 
Index: classes/coroutine.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/coroutine.pmc,v
retrieving revision 1.8
diff -u -r1.8 coroutine.pmc
--- classes/coroutine.pmc	3 Nov 2002 21:15:09 -0000	1.8
+++ classes/coroutine.pmc	15 Nov 2002 21:00:44 -0000
@@ -5,8 +5,8 @@
  *  Overview:
  *     These are the vtable functions for the Coroutine base class
  *  Data Structure and Algorithms:
- *     Initial version by Melvin on 2002/06/6
  *  History:
+ *     Initial version by Melvin on 2002/06/6
  *  Notes:
  *  References:
  */
@@ -76,9 +76,17 @@
     }
 
     void* invoke (void* next) {
+        PMC * pad = ((struct Parrot_Coroutine *)SELF->data)->lex_pad;
         struct Parrot_Coroutine* co = (struct Parrot_Coroutine*)SELF->data;
         void * dest = co->resume;
         co->resume = (opcode_t *)next;
+
+        if (pad) {
+           /* put the correct pad in place */
+           stack_push(INTERP, &INTERP->ctx.pad_stack, pad, 
+                      STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
+        }
+
         return dest;
     }
 
Index: t/pmc/sub.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/sub.t,v
retrieving revision 1.2
diff -u -r1.2 sub.t
--- t/pmc/sub.t	6 Aug 2002 22:43:08 -0000	1.2
+++ t/pmc/sub.t	15 Nov 2002 21:00:44 -0000
@@ -1,6 +1,6 @@
 #! perl -w
 
-use Parrot::Test tests => 3;
+use Parrot::Test tests => 4;
 use Test::More;
 
 output_is(<<'CODE', <<'OUTPUT', "PASM subs");
@@ -149,3 +149,72 @@
 back  1
 done
 OUTPUT
+
+
+
+output_is(<<'CODE', <<'OUTPUT', "PASM sub as closure");
+    # sub foo {
+    #     my ($n) = @_;
+    #     sub {$n += shift}
+    # }
+main:
+    new P0, .Sub
+    set_addr I3, foo
+    set P0, I3
+    set I5, 3
+
+    new P1, .PerlInt
+    set P1, 5
+
+    invoke
+
+    new P1, .PerlInt
+    set P1, 3
+    set P0, P2 # move sub to P0 for invoke
+
+    saveall
+    invoke
+    print P2
+    print "\n"
+    restoreall
+
+    saveall
+    invoke
+    print P2
+    print "\n"
+    restoreall
+
+    saveall
+    invoke
+    print P2
+    print "\n"
+    restoreall
+
+    end
+
+# foo takes a number n (P1) and returns a sub (in P2) that takes 
+# a number i (P1) and returns n incremented by i.
+foo:
+    new_pad 0
+    store_lex 0, "n", P1
+    new P2, .Sub
+    set_addr I3, accumulator
+    set P2, I3
+    pop_pad
+    ret
+
+# expects arg in P1, returns incremented result in P2
+accumulator: 
+    find_lex P2, "n"
+    new P3, .PerlInt
+    add P2, P1
+    pop_pad
+    ret
+
+CODE
+8
+11
+14
+OUTPUT
+
+1;
