Hello! Check this:
scheme@(guile-user)> ,x (lambda () (call-with-values (lambda () (values 2 3)) *)) Disassembly of #<program #(0 32 #f) (0)>: nargs = 0 nrest = 0 nlocs = 0 nexts = 0 Bytecode: 0 (late-variable-ref 0) 2 (object-ref 1) ;; #<program #(0 43 #f) (0)> 4 (mv-call 0 0 2) ;; MV -> 10 This new instruction, mv-call, takes three byte arguments, and at least two stack arguments. The byte arguments are the number of args, and two bytes to specify an offset to the multiple values return address. The stack arguments are two procedures, a producer of values, and a consumer of values. Here we see that the producer takes no values, and multiple values should return to the address 10 instead of the next address, 8. 8 (goto/args 1) Here we arrived with just one value, so tail-call (goto/args used to be called `tail-call') the procedure on the stack (pushed at instruction 0, that is, *) with one arg, also on the stack. 10 (goto/nargs) Or in this case there were a number of args pushed by the producer, which then pushed the number of args on top of that. So pop off the number of args, and tail-call `*' with that many args. Objects: 0 * 1 #<program #(0 43 #f) (0)> Sources: 4 #(0 32 #f) ---------------------------------------- Disassembly of #<program #(0 43 #f) (0)>: nargs = 0 nrest = 0 nlocs = 0 nexts = 0 Bytecode: 0 (make-int8 2) ;; 2 2 (make-int8 3) ;; 3 4 (return/values 2) Here is the multiple-value return instruction. Sources: 6 #(0 43 #f) Guile (with the VM) now supports multiple values, without consing at all! There are some important optimizations to be made though, especially when the second expression is a lambda. Soon, soon! Andy -- http://wingolog.org/