diff options
author | Andy Wingo <wingo@pobox.com> | 2008-09-15 00:04:34 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2008-09-15 00:04:34 +0200 |
commit | ef24c01bffb41a9855fe1aea36c4444742aba660 (patch) | |
tree | effab1206ed2d78ddfe0b046973662373fad7dd0 /libguile/vm-i-system.c | |
parent | a222b0fa91fe33461db1c7f8f4370ce6a5db588f (diff) | |
download | guile-ef24c01bffb41a9855fe1aea36c4444742aba660.tar.gz |
add special case for (apply values ...)
* libguile/vm-engine.c (vm_run): Move nvalues to the top level, to avoid
(spurious, it seems) gcc warnings about it being used uninitialized.
* libguile/vm-i-system.c (halt, return/values): Adapt to gcc silliness.
Deindent some of return/values.
(return/values*): New instruction, does what (apply values . args)
would do.
* module/language/scheme/translate.scm (custom-transformer-table): Move
the apply and @apply cases here from inline.scm, because we need some
more cleverness when dealing with cases like (apply values . args).
(lookup-apply-transformer): Define an eval transformer for `values',
turning it into ghil-values*.
* module/system/il/compile.scm (codegen): Compile <ghil-values*> into
return/values*.
* module/system/il/ghil.scm: Add <ghil-values*> and accessors.
(ghil-lookup): Add optional argument, define?, which if false tells us
not to actually cache the binding if it is not found in the toplevel.
* module/system/il/inline.scm: Remove apply clauses.
* module/system/vm/frame.scm (bootstrap-frame?): Update heuristic for
bootstrap-frame?, as the bootstrap frame is now 5 bytes since it
accepts multiple values.
Diffstat (limited to 'libguile/vm-i-system.c')
-rw-r--r-- | libguile/vm-i-system.c | 105 |
1 files changed, 64 insertions, 41 deletions
diff --git a/libguile/vm-i-system.c b/libguile/vm-i-system.c index 4e9ec4263..75642b5ba 100644 --- a/libguile/vm-i-system.c +++ b/libguile/vm-i-system.c @@ -55,7 +55,6 @@ VM_DEFINE_INSTRUCTION (nop, "nop", 0, 0, 0) VM_DEFINE_INSTRUCTION (halt, "halt", 0, 0, 0) { SCM ret; - int nvalues; vp->time += scm_c_get_internal_run_time () - start_time; HALT_HOOK (); nvalues = SCM_I_INUM (*sp--); @@ -859,55 +858,57 @@ VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1) VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1) { + /* nvalues declared at top level, because for some reason gcc seems to think + that perhaps it might be used without declaration. Fooey to that, I say. */ + SCM *data; + + nvalues = FETCH (); + vm_return_values: EXIT_HOOK (); RETURN_HOOK (); - { - int nvalues = FETCH (); - SCM *data = SCM_FRAME_DATA_ADDRESS (fp); + + data = SCM_FRAME_DATA_ADDRESS (fp); #ifdef THE_GOVERNMENT_IS_AFTER_ME - if (stack_base != data + 4) - abort (); + if (stack_base != data + 4) + abort (); #endif - /* data[3] is the mv return address */ - if (nvalues != 1 && data[3]) - { - int i; - /* Restore registers */ - sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1; - ip = SCM_FRAME_BYTE_CAST (data[3]); /* multiple value ra */ - fp = SCM_FRAME_STACK_CAST (data[2]); + /* data[3] is the mv return address */ + if (nvalues != 1 && data[3]) + { + int i; + /* Restore registers */ + sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1; + ip = SCM_FRAME_BYTE_CAST (data[3]); /* multiple value ra */ + fp = SCM_FRAME_STACK_CAST (data[2]); - /* Push return values, and the number of values */ - for (i = 0; i < nvalues; i++) - *++sp = stack_base[1+i]; - *++sp = SCM_I_MAKINUM (nvalues); + /* Push return values, and the number of values */ + for (i = 0; i < nvalues; i++) + *++sp = stack_base[1+i]; + *++sp = SCM_I_MAKINUM (nvalues); - /* Finally set new stack_base */ - stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1; - } - else if (nvalues >= 1) - { - /* Multiple values for a single-valued continuation -- here's where I - break with guile tradition and try and do something sensible. (Also, - this block handles the single-valued return to an mv - continuation.) */ - /* Restore registers */ - sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1; - ip = SCM_FRAME_BYTE_CAST (data[4]); /* single value ra */ - fp = SCM_FRAME_STACK_CAST (data[2]); + /* Finally set new stack_base */ + stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1; + } + else if (nvalues >= 1) + { + /* Multiple values for a single-valued continuation -- here's where I + break with guile tradition and try and do something sensible. (Also, + this block handles the single-valued return to an mv + continuation.) */ + /* Restore registers */ + sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1; + ip = SCM_FRAME_BYTE_CAST (data[4]); /* single value ra */ + fp = SCM_FRAME_STACK_CAST (data[2]); - /* Push first value */ - *++sp = stack_base[1]; + /* Push first value */ + *++sp = stack_base[1]; - /* Finally set new stack_base */ - stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1; - } - else - goto vm_error_no_values; - - - } + /* Finally set new stack_base */ + stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1; + } + else + goto vm_error_no_values; /* Restore the last program */ program = SCM_FRAME_PROGRAM (fp); @@ -917,6 +918,28 @@ VM_DEFINE_INSTRUCTION (return_values, "return/values", 1, -1, -1) NEXT; } +VM_DEFINE_INSTRUCTION (return_values_star, "return/values*", 1, -1, -1) +{ + SCM l; + + nvalues = FETCH (); +#ifdef THE_GOVERNMENT_IS_AFTER_ME + if (nvalues < 1) + abort (); +#endif + + nvalues--; + POP (l); + while (SCM_CONSP (l)) + { + PUSH (SCM_CAR (l)); + l = SCM_CDR (l); + nvalues++; + } + + goto vm_return_values; +} + /* Local Variables: c-file-style: "gnu" |