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);