Because I was bored this evening, I implemented the clone operators.

Dan?

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:
        clonei
        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
? test.pasm
? test.inc
? test.list
? fact.pasm
? interp_guts.c
? config.h
? basic_opcodes.c
? DCn.diff
? macro.pbc
? macro.list
? local_label.pbc
? test.pbc
? euclid.pbc
? macro.pasm
? test2.pbc
? test3.pbc
? mytest.pasm
? cequ.code
? assemble.pl-new_macros
? mytest.pbc
? op_info.c
? frame_test.pbc
? fact.pbc
? frame_test.pasm
? clone.diff
? include/parrot/op_info.h
? t/test.pbc
? t/test1.c
? t/test1
Index: core.ops
===================================================================
RCS file: /home/perlcvs/parrot/core.ops,v
retrieving revision 1.4
diff -u -r1.4 core.ops
--- core.ops    2001/10/15 21:18:42     1.4
+++ core.ops    2001/10/16 00:29:05
@@ -1678,6 +1678,35 @@
   Parrot_push_p(interpreter);
 }
 
+########################################
+
+=item B<clonei>()
+
+=item B<clonen>()
+
+=item B<clonep>()
+
+=item B<clones>()
+
+Save all the registers of the type indicated in the name of the operation.
+
+=cut
+
+AUTO_OP clonei() {
+  Parrot_clone_i(interpreter);
+}
+
+AUTO_OP clonen() {
+  Parrot_clone_n(interpreter);
+}
+
+AUTO_OP clones() {
+  Parrot_clone_s(interpreter);
+}
+
+AUTO_OP clonep() {
+  Parrot_clone_p(interpreter);
+}
 
 =back
 
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/16 00:29:06
@@ -38,6 +38,39 @@
     }
 }
 
+/*=for api register Parrot_clone_i
+  pushes a new integer register frame on the frame stack and
+  copies the last frame to the current frame
+*/
+void
+Parrot_clone_i(struct Parrot_Interp *interpreter) {
+    struct IRegChunk *chunk_base;
+    
+    chunk_base = CHUNK_BASE(interpreter->int_reg);
+    /* Do we have any slots left in the current chunk? */
+    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 {
+        struct IRegChunk *new_chunk;
+        new_chunk = mem_allocate_aligned(sizeof(struct IRegChunk));
+        new_chunk->used = 1;
+        new_chunk->free = FRAMES_PER_INT_REG_CHUNK - 1;
+        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];
+    }
+}
+
 /*=for api register Parrot_pop_i
   pops an integer register frame off of the frame stack
 */
@@ -107,6 +140,42 @@
     }
 }
 
+/*=for api register Parrot_clone_s
+  pushes a new string register frame on the frame stack and
+  copies the last frame to the current frame
+*/
+void
+Parrot_clone_s(struct Parrot_Interp *interpreter) {
+    struct SRegChunk *chunk_base;
+    
+    chunk_base = CHUNK_BASE(interpreter->string_reg);
+    /* Do we have any slots left in the current chunk? */
+    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 {
+        struct SRegChunk *new_chunk;
+        new_chunk = mem_allocate_aligned(sizeof(struct SRegChunk));
+        new_chunk->used = 1;
+        new_chunk->free = FRAMES_PER_STR_REG_CHUNK - 1;
+        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 */
+        Parrot_clear_s(interpreter);
+    }
+}
+
 /*=for api register Parrot_pop_s
   pops a string register frame off of the frame stack
 */
@@ -173,6 +242,39 @@
     }
 }
 
+/*=for api register Parrot_clone_n
+  pushes a new numeric register frame on the frame stack and copy the
+  previous frame to the current frame
+*/
+void
+Parrot_clone_n(struct Parrot_Interp *interpreter) {
+    struct NRegChunk *chunk_base;
+    
+    chunk_base = CHUNK_BASE(interpreter->num_reg);
+    /* Do we have any slots left in the current chunk? */
+    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 {
+        struct NRegChunk *new_chunk;
+        new_chunk = mem_allocate_aligned(sizeof(struct NRegChunk));
+        new_chunk->used = 1;
+        new_chunk->free = FRAMES_PER_NUM_REG_CHUNK - 1;
+        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];
+    }
+}
+
 /*=for api register Parrot_pop_n
   pops a numeric register frame off of the frame stack
 */
@@ -235,6 +337,41 @@
         new_chunk->next = NULL;
         new_chunk->prev = chunk_base;
         chunk_base->next = new_chunk;
+        interpreter->pmc_reg = &new_chunk->PReg[0];
+        /* Gotta NULL them out or we might GC Wrong things later */
+        Parrot_clear_p(interpreter);
+    }
+}
+
+/*=for api register Parrot_clone_p
+  pushes a new PMC register frame on the frame stack and copy the
+  previous frame to the current frame
+*/
+void
+Parrot_clone_p(struct Parrot_Interp *interpreter) {
+    struct PRegChunk *chunk_base;
+    
+    chunk_base = CHUNK_BASE(interpreter->pmc_reg);
+    /* Do we have any slots left in the current chunk? */
+    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 {
+        struct PRegChunk *new_chunk;
+        new_chunk = mem_allocate_aligned(sizeof(struct PRegChunk));
+        new_chunk->used = 1;
+        new_chunk->free = FRAMES_PER_PMC_REG_CHUNK - 1;
+        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);
Index: include/parrot/register.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/register.h,v
retrieving revision 1.6
diff -u -r1.6 register.h
--- include/parrot/register.h   2001/10/06 01:04:47     1.6
+++ include/parrot/register.h   2001/10/16 00:29:07
@@ -77,6 +77,11 @@
 void Parrot_push_s(struct Parrot_Interp *);
 void Parrot_push_p(struct Parrot_Interp *);
 
+void Parrot_clone_i(struct Parrot_Interp *);
+void Parrot_clone_n(struct Parrot_Interp *);
+void Parrot_clone_s(struct Parrot_Interp *);
+void Parrot_clone_p(struct Parrot_Interp *);
+
 void Parrot_pop_i(struct Parrot_Interp *);
 void Parrot_pop_n(struct Parrot_Interp *);
 void Parrot_pop_s(struct Parrot_Interp *);

Reply via email to