Here's a small change to push* which copies the last context
automatically.  I was thinking about Dan's "clone" opcode, when I
realized that most of the time you're going to want the values, and if
you don't, you can always issue a clear.  It passes all of the make
tests, and it allows recursive programs to be written, such as the
factorial below.

Dan, what do you think?

Brian


# compute the factorial....recursively!
# lets do it for the numbers 0 to 6

main:
        set     I1,0

$loop:
        print   "fact of "
        print   I1
        print   " is: "
        set     I0,I1
        bsr     fact
        print   I0
        print   "\n"
        inc     I1,1
        eq      I1,7,$done
        branch  $loop
$done:
        end

# I0 is the number to compute
fact:
        pushi
        lt      I0,2,$is_one
        set     I1,I0
        dec     I0,1    
        bsr     fact
        mul     I0,I0,I1
        save    I0
        branch  $done
$is_one:
        set     I0,1
        save    I0
$done:
        popi
        restore I0
        ret
Index: register.c
===================================================================
RCS file: /home/perlcvs/parrot/register.c,v
retrieving revision 1.10
diff -u -r1.10 register.c
--- register.c  2001/10/02 14:01:30     1.10
+++ register.c  2001/10/14 01:28:43
@@ -24,6 +24,9 @@
     if (chunk_base->free) {
         interpreter->int_reg = &chunk_base->IReg[chunk_base->used++];
         chunk_base->free--;
+        mem_sys_memcopy(&chunk_base->IReg[chunk_base->used-1],
+                        &chunk_base->IReg[chunk_base->used-2],
+                        sizeof(struct IReg));
     }
     /* Nope, so plan B time. Allocate a new chunk of integer register frames */     
else {
@@ -34,6 +37,9 @@
         new_chunk->next = NULL;
         new_chunk->prev = chunk_base;
         chunk_base->next = new_chunk;
+        mem_sys_memcopy(&new_chunk->IReg[0],
+                        &chunk_base->IReg[chunk_base->used-1],
+                        sizeof(struct IReg));
         interpreter->int_reg = &new_chunk->IReg[0];
     }
 }
@@ -90,6 +96,9 @@
     if (chunk_base->free) {
         interpreter->string_reg = &chunk_base->SReg[chunk_base->used++];
         chunk_base->free--;
+        mem_sys_memcopy(&chunk_base->SReg[chunk_base->used-1],
+                        &chunk_base->SReg[chunk_base->used-2],
+                        sizeof(struct SReg));
     }
     /* Nope, so plan B time. Allocate a new chunk of string register frames */
     else {
@@ -100,6 +109,9 @@
         new_chunk->next = NULL;
         new_chunk->prev = chunk_base;
         chunk_base->next = new_chunk;
+        mem_sys_memcopy(&new_chunk->SReg[0],
+                        &chunk_base->SReg[chunk_base->used-1],
+                        sizeof(struct SReg));
         interpreter->string_reg = &new_chunk->SReg[0];
         /* Gotta NULL them out as some string
            functions depend on NULL strings */
@@ -159,6 +171,9 @@
     if (chunk_base->free) {
         interpreter->num_reg = &chunk_base->NReg[chunk_base->used++];
         chunk_base->free--;
+        mem_sys_memcopy(&chunk_base->NReg[chunk_base->used-1],
+                        &chunk_base->NReg[chunk_base->used-2],
+                        sizeof(struct NReg));
     }
     /* Nope, so plan B time. Allocate a new chunk of float register frames */
     else {
@@ -169,6 +184,9 @@
         new_chunk->next = NULL;
         new_chunk->prev = chunk_base;
         chunk_base->next = new_chunk;
+        mem_sys_memcopy(&new_chunk->NReg[0],
+                        &chunk_base->NReg[chunk_base->used-1],
+                        sizeof(struct NReg));
         interpreter->num_reg = &new_chunk->NReg[0];
     }
 }
@@ -225,6 +243,9 @@
     if (chunk_base->free) {
         interpreter->pmc_reg = &chunk_base->PReg[chunk_base->used++];
         chunk_base->free--;
+        mem_sys_memcopy(&chunk_base->PReg[chunk_base->used-1],
+                        &chunk_base->PReg[chunk_base->used-2],
+                        sizeof(struct PReg));
     }
     /* Nope, so plan B time. Allocate a new chunk of float register frames */
     else {
@@ -235,6 +256,9 @@
         new_chunk->next = NULL;
         new_chunk->prev = chunk_base;
         chunk_base->next = new_chunk;
+        mem_sys_memcopy(&new_chunk->PReg[0],
+                        &chunk_base->PReg[chunk_base->used-1],
+                        sizeof(struct PReg));
         interpreter->pmc_reg = &new_chunk->PReg[0];
         /* Gotta NULL them out or we might GC Wrong things later */
         Parrot_clear_p(interpreter);

Reply via email to