Add primitives VALUES and CALL-WITH-VALUES.
authorMatt Birkholz <matt@birchwood-abbey.net>
Sun, 5 Feb 2017 02:31:49 +0000 (19:31 -0700)
committerMatt Birkholz <matt@birchwood-abbey.net>
Sun, 5 Feb 2017 02:31:49 +0000 (19:31 -0700)
* microcode/hooks.c (Prim_values Prim_call_with_values): New.

* microcode/returns.h (RC_MULTIPLE_VALUES): New return code.
* microcode/interp.c: Interpret new return code.
* runtime/conpar.scm: Parse new stack frame type.

* runtime/boot.scm (values call-with-values with-values): Assign
these bindings earlier in the boot.  They are no longer inlined by the
scode optimizer and cannot be assigned later.
* runtime/global.scm: Remove old definitions.
* runtime/runtime.pkg: Move declarations.

* runtime/thread.scm (with-thread-events-blocked): Pass multiple values.
* runtime/wind.scm (%execute-at-new-state-point): Pass multiple values.
* compiler/base/cfg2.scm (cleanup-noop-nodes): Pass multiple values.

* src/sf/usiexp.scm (values-expansion call-with-values-expansion):
Remove.

src/compiler/base/cfg2.scm
src/microcode/hooks.c
src/microcode/interp.c
src/microcode/returns.h
src/runtime/boot.scm
src/runtime/conpar.scm
src/runtime/global.scm
src/runtime/runtime.pkg
src/runtime/thread.scm
src/runtime/wind.scm
src/sf/usiexp.scm

index a3129f431794e15f2e9c5d27728fe1f54416d79e..d39d5bb3fce2ff18970b24ac781fbcbd3b6f8b88 100644 (file)
@@ -178,9 +178,10 @@ USA.
 
 (define (cleanup-noop-nodes thunk)
   (fluid-let ((*noop-nodes* '()))
-    (let ((value (thunk)))
-      (for-each snode-delete! *noop-nodes*)
-      value)))
+    (call-with-values thunk
+      (lambda value*
+       (for-each snode-delete! *noop-nodes*)
+       (apply values value*)))))
 
 (define (make-false-pcfg)
   (snode->pcfg-false (make-noop-node)))
index 08316165f17591797cf0b9c5d1851b6a7652ebd6..eba399f472064bffb4c21ac86ca130b3cd8696e1 100644 (file)
@@ -113,6 +113,63 @@ Invokes PROCEDURE on the arguments in ARG-LIST.")
   }
 }
 \f
+DEFINE_PRIMITIVE ("VALUES", Prim_values, 0, LEXPR,
+                 "(VALUES . values)\n\
+Return zero or more values to the current continuation.")
+{
+  PRIMITIVE_HEADER (LEXPR);
+  {
+    unsigned long n_args = GET_LEXPR_ACTUALS;
+    unsigned long extra = 0;
+
+#ifdef CC_SUPPORT_P
+    if (return_to_interpreter == (STACK_REF (n_args)))
+      extra = 1;
+#endif
+
+    if (CHECK_RETURN_CODE (RC_MULTIPLE_VALUES, n_args+extra))
+      {
+       SCHEME_OBJECT consumer = (CONT_EXP (n_args+extra));
+       unsigned long n_words = CONTINUATION_SIZE+extra;
+       {
+         SCHEME_OBJECT * scan_from = (STACK_LOC (n_args));
+         SCHEME_OBJECT * scan_end = (STACK_LOC (0));
+         SCHEME_OBJECT * scan_to = (STACK_LOC (n_args + n_words));
+         while (scan_from != scan_end)
+           (STACK_LOCATIVE_PUSH (scan_to)) = (STACK_LOCATIVE_PUSH (scan_from));
+         stack_pointer = (STACK_LOC (n_words));
+       }
+       assert (RETURN_CODE_P (STACK_REF (n_args)));
+       STACK_PUSH (consumer);
+       PUSH_APPLY_FRAME_HEADER (n_args);
+       PRIMITIVE_ABORT (PRIM_APPLY);
+       /*NOTREACHED*/
+       PRIMITIVE_RETURN (UNSPECIFIC);
+      }
+
+    PRIMITIVE_RETURN (n_args == 0 ? UNSPECIFIC : (ARG_REF(1)));
+  }
+}
+
+DEFINE_PRIMITIVE ("CALL-WITH-VALUES", Prim_call_with_values, 2, 2,
+                 "(CALL-WITH-VALUES PRODUCER CONSUMER)\n\
+Call PRODUCER and tail-apply its return values to CONSUMER.")
+{
+  PRIMITIVE_HEADER (2);
+  canonicalize_primitive_context ();
+  {
+    SCHEME_OBJECT producer = (STACK_POP ());
+    STACK_PUSH (MAKE_RETURN_CODE (RC_MULTIPLE_VALUES));
+   Will_Push (STACK_ENV_EXTRA_SLOTS + 1);
+    STACK_PUSH (producer);
+    PUSH_APPLY_FRAME_HEADER (0);
+   Pushed ();
+    PRIMITIVE_ABORT (PRIM_APPLY);
+    /*NOTREACHED*/
+    PRIMITIVE_RETURN (UNSPECIFIC);
+  }
+}
+\f
 /* CALL-WITH-CURRENT-CONTINUATION creates a control point (a pointer
    to the current stack) and passes it to PROCEDURE as its only
    argument.  The inverse operation, typically called THROW, is
index 33f09dd50295366ef91de33b9bcd0f9c6605c1a6..26eb32c7ea3ef39959927f16ffb48c11caa2f758 100644 (file)
@@ -1162,6 +1162,17 @@ Interpret (int pop_return_p)
        }
       break;
 
+    case RC_MULTIPLE_VALUES:
+      /* Frame consists of the consumer already popped into EXP. */
+      /* This is a normal return; tail-apply EXP to VAL. */
+     Will_Push (STACK_ENV_EXTRA_SLOTS + 2);
+      STACK_PUSH (GET_VAL);
+      STACK_PUSH (GET_EXP);
+      PUSH_APPLY_FRAME_HEADER (1);
+     Pushed ();
+      SET_PRIMITIVE (SHARP_F);
+      goto internal_apply;
+
     default:
       POP_RETURN_ERROR (ERR_INAPPLICABLE_CONTINUATION);
     }
index 4e8388ef8a2a9c1d3c40b8265d654db786105773..1e201e963192c4fa91712733a1ecb848dc0c6b9a 100644 (file)
@@ -29,7 +29,7 @@ USA.
 \f
 #define RC_END_OF_COMPUTATION          0x00
 #define RC_JOIN_STACKLETS              0x01
-/* unused                              0x02 */
+#define RC_MULTIPLE_VALUES             0x02
 #define RC_INTERNAL_APPLY              0x03
 /* unused                              0x04 */
 #define RC_RESTORE_HISTORY             0x05
@@ -98,7 +98,7 @@ USA.
 {                                                                      \
 /* 0x00 */             "non-existent-continuation",                    \
 /* 0x01 */             "join-stacklets",                               \
-/* 0x02 */             0,                                              \
+/* 0x02 */             "multiple-values",                              \
 /* 0x03 */             "internal-apply",                               \
 /* 0x04 */             0,                                              \
 /* 0x05 */             "restore-history",                              \
index 3350632a88f11524baaa2d11ce0eafea6abe2a39..7b44447b6de66228f2e219c7e3d9b22803d95ce1 100644 (file)
@@ -126,6 +126,12 @@ USA.
   ((ucode-primitive with-interrupt-mask)
    (fix:and limit-mask (get-interrupt-enables))
    procedure))
+
+(define values (ucode-primitive values -1))
+
+(define call-with-values (ucode-primitive call-with-values 2))
+
+(define with-values (ucode-primitive call-with-values 2))
 \f
 (define (object-constant? object)
   ((ucode-primitive constant?) object))
index bf9b8fecdf7cc97588eafb4a2a1ffe352b0fb68c..a819bba2a5ea2b99e8312be08920e27995478aa5 100644 (file)
@@ -798,6 +798,7 @@ USA.
     (standard-frame 'NON-EXISTENT-CONTINUATION 2)
     (standard-frame 'POP-RETURN-ERROR 2)
     (standard-frame 'RESTORE-VALUE 2)
+    (standard-frame 'MULTIPLE-VALUES 2)
 
     (standard-frame 'RESTORE-DONT-COPY-HISTORY 4 parser/restore-history)
     (standard-frame 'RESTORE-HISTORY 4 parser/restore-history)
index 1e32ddf14e8fd455c3eaca89407cedc831109b66..84a78672878c59e93b3d3424d5b1865ef2bd0f64 100644 (file)
@@ -139,15 +139,6 @@ USA.
 (define bind-cell-contents!
   (object-component-binder cell-contents set-cell-contents!))
 
-(define (values . objects)
-  (lambda (receiver)
-    (apply receiver objects)))
-
-(define (call-with-values thunk receiver)
-  ((thunk) receiver))
-
-(define with-values call-with-values)
-
 (define (write-to-string object #!optional max)
   (if (or (default-object? max) (not max))
       (with-output-to-string (lambda () (write object)))
index 9ff8d529eefe30d905c9716e47acf1c5b738c79e..edcda198dc709668292e438dfebd34b4c925123b 100644 (file)
@@ -145,6 +145,7 @@ USA.
          guarantee-unparser-method
          ;; END deprecated bindings
          bracketed-unparser-method
+         call-with-values
          default-object
          default-object?
          gc-space-status
@@ -168,8 +169,10 @@ USA.
          simple-unparser-method
          standard-unparser-method
          unparser-method?
+         values
          with-absolutely-no-interrupts
          with-limited-interrupts
+         with-values
          without-interrupts)
   (export (runtime)
          add-boot-init!))
@@ -457,7 +460,6 @@ USA.
          append-hook-to-list
          apply
          bind-cell-contents!
-         call-with-values
          cd
          cell-contents
          cell?
@@ -558,11 +560,9 @@ USA.
          unspecific
          user-initial-environment
          user-initial-prompt
-         values
          wait-interval
          with-history-disabled
          with-interrupt-mask
-         with-values
          write-to-string)
   (import (runtime thread)
          with-obarray-lock)
index 13e32e45c44bbaff00ae78fd506083e9eec0c550..22f547e5235f0ce7b3dd4dba438c7dc5ee586a5d 100644 (file)
@@ -871,20 +871,20 @@ USA.
       (if thread
          (let ((block-events? (thread/block-events? thread)))
            (set-thread/block-events?! thread #t)
-           (let ((value
-                  ((ucode-primitive with-stack-marker 3)
-                   (lambda ()
-                     (set-interrupt-enables! interrupt-mask)
-                     (let ((value (thunk)))
-                       (set-interrupt-enables! interrupt-mask/gc-ok)
-                       value))
-                   'WITH-THREAD-EVENTS-BLOCKED
-                   block-events?)))
+           (let ((value*))
+             ((ucode-primitive with-stack-marker 3)
+              (lambda ()
+                (set-interrupt-enables! interrupt-mask)
+                (call-with-values thunk
+                  (lambda values** (set! value* values**)))
+                (set-interrupt-enables! interrupt-mask/gc-ok))
+              'WITH-THREAD-EVENTS-BLOCKED
+              block-events?)
              (let ((thread first-running-thread))
                (if thread
                    (set-thread/block-events?! thread block-events?)))
              (set-interrupt-enables! interrupt-mask)
-             value))
+             (apply values value*)))
          (begin
            (set-interrupt-enables! interrupt-mask)
            (thunk))))))
index a48f001457360378507b3a89759dcc4ca1a56a93..2f05954cbd53a2cf131ee9cdc72338ef11af35ef 100644 (file)
@@ -83,10 +83,13 @@ USA.
                (set-state-point/from-nearer! old-root after)
                (set-state-space/nearest-point! space new-point))
              old-root)))))
-    (let ((value
-          (with-stack-marker during %translate-to-state-point old-root)))
+    (let ((value*))
+      (with-stack-marker
+       (lambda ()
+        (call-with-values during (lambda value** (set! value* value**))))
+       %translate-to-state-point old-root)
       (%translate-to-state-point old-root)
-      value)))
+      (apply values value*))))
 
 (define (%translate-to-state-point point)
   (%without-interrupts
index 96da1ae4699b9e0daf2d00748eddba2df94db7bc..b7406d9a8d61644c707b7a0459d9d4ff02f54613 100644 (file)
@@ -336,50 +336,6 @@ USA.
        ((null? rest) (constant/make (and expr (object/scode expr)) '()))
        (else (error "Improper list."))))
 \f
-(define (values-expansion expr operands block)
-  (let ((block (block/make block #t '())))
-    (let ((variables
-          (map (lambda (position)
-                 (variable/make&bind!
-                  block
-                  (string->uninterned-symbol
-                   (string-append "value-" (number->string position)))))
-               (iota (length operands)))))
-      (combination/make
-       expr
-       block
-       (procedure/make
-       #f
-       block lambda-tag:let variables '() #f
-       (let ((block (block/make block #t '())))
-         (let ((variable (variable/make&bind! block 'RECEIVER)))
-           (procedure/make
-            #f block lambda-tag:unnamed (list variable) '() #f
-            (declaration/make
-             #f
-             ;; The receiver is used only once, and all its operand
-             ;; expressions are effect-free, so integrating here is
-             ;; safe.
-             (declarations/parse block '((INTEGRATE-OPERATOR RECEIVER)))
-             (combination/make #f
-                               block
-                               (reference/make #f block variable)
-                               (map (lambda (variable)
-                                      (reference/make #f block variable))
-                                    variables)))))))
-       operands))))
-
-(define (call-with-values-expansion expr operands block)
-  (if (and (pair? operands)
-          (pair? (cdr operands))
-          (null? (cddr operands)))
-      (combination/make expr
-                       block
-                       (combination/make #f block (car operands) '())
-                       (cdr operands))
-      #f))
-
-\f
 ;;;; General CAR/CDR Encodings
 
 (define (call-to-car? expression)
@@ -720,7 +676,6 @@ USA.
            cadddr
            caddr
            cadr
-           call-with-values
            car
            cdaaar
            cdaadr
@@ -772,9 +727,7 @@ USA.
            string->symbol
            symbol?
            third
-           values
            weak-pair?
-           with-values
            zero?)
          (map car global-primitives)))
 \f
@@ -806,7 +759,6 @@ USA.
           cadddr-expansion
           caddr-expansion
           cadr-expansion
-          call-with-values-expansion
           car-expansion
           cdaaar-expansion
           cdaadr-expansion
@@ -858,9 +810,7 @@ USA.
           string->symbol-expansion
           symbol?-expansion
           third-expansion
-          values-expansion
           weak-pair?-expansion
-          call-with-values-expansion
           zero?-expansion)
          (map (lambda (p)
                 (make-primitive-expander