diff --git a/pkgs/racket-test-core/tests/racket/function.rktl b/pkgs/racket-test-core/tests/racket/function.rktl index bc96e5e9c2..42d14d91c8 100644 --- a/pkgs/racket-test-core/tests/racket/function.rktl +++ b/pkgs/racket-test-core/tests/racket/function.rktl @@ -111,9 +111,13 @@ (test 1 procedure-result-arity car) (test 1 procedure-result-arity list) (test 1 procedure-result-arity (procedure-reduce-arity car 1)) -(test (arity-at-least 0) procedure-result-arity values) -(test (arity-at-least 0) procedure-result-arity (procedure-reduce-arity values 1)) -(test (arity-at-least 0) procedure-result-arity call/cc) +(let ([adjust-no-information (lambda (x) + ;; `(arity-at-least 0)` is the same as `#f`, + ;; since both are no information + (or x (arity-at-least 0)))]) + (test (arity-at-least 0) adjust-no-information (procedure-result-arity values)) + (test (arity-at-least 0) adjust-no-information (procedure-result-arity (procedure-reduce-arity values 1))) + (test (arity-at-least 0) adjust-no-information (procedure-result-arity call/cc))) (let () (struct s (x)) (test 1 procedure-result-arity s-x) @@ -152,11 +156,14 @@ [(a b c d e f) (values 1 2 3 4 5 6 7 8)] [(a b . whatever) a])))) -;; hopefully this test will start failing at -;; some point and return 1 instead of #f (let () (struct s (f) #:property prop:procedure 0) - (test #f procedure-result-arity (s car))) + (test (case (system-type 'vm) + ;; maybe this test will start failing at + ;; some point and return 1 instead of #f + [(racket) #f] + [else 1]) + procedure-result-arity (s car))) ;; ---------- identity ---------- (let () diff --git a/racket/src/cs/Makefile b/racket/src/cs/Makefile index dfea94d2e8..1a958f34a2 100644 --- a/racket/src/cs/Makefile +++ b/racket/src/cs/Makefile @@ -246,6 +246,7 @@ RUMBLE_SRCS = rumble/define.ss \ rumble/thread-cell.ss \ rumble/parameter.ss \ rumble/begin0.ss \ + rumble/value.ss \ rumble/pthread.ss \ rumble/control.ss \ rumble/interrupt.ss \ diff --git a/racket/src/cs/rumble.sls b/racket/src/cs/rumble.sls index d6719c8a37..64639a3547 100644 --- a/racket/src/cs/rumble.sls +++ b/racket/src/cs/rumble.sls @@ -5,6 +5,7 @@ null eof void void? begin0 + $value letrec*/names @@ -706,6 +707,7 @@ (include "rumble/begin0.ss") (include "rumble/letrec.ss") (include "rumble/syntax-rule.ss") + (include "rumble/value.ss") (include "rumble/lock.ss") (include "rumble/thread-local.ss") (include "rumble/version.ss") diff --git a/racket/src/cs/rumble/procedure.ss b/racket/src/cs/rumble/procedure.ss index e1af5fae7d..51ab17a5b1 100644 --- a/racket/src/cs/rumble/procedure.ss +++ b/racket/src/cs/rumble/procedure.ss @@ -278,9 +278,26 @@ (define/who (procedure-result-arity p) (check who procedure? p) - (and (#%procedure? p) - (procedure-known-single-valued? p) - 1)) + (cond + [(#%procedure? p) + (and (procedure-known-single-valued? p) + 1)] + [(impersonator? p) + (procedure-result-arity (strip-impersonator p))] + [(record? p) + (let* ([rtd (record-rtd p)] + [v (struct-property-ref prop:procedure rtd none)]) + (cond + [(eq? v none) #f] + [(fixnum? v) + (procedure-result-arity (unsafe-struct-ref p v))] + [(eq? v 'unsafe) + (procedure-result-arity + (if (chaperone? p) + (unsafe-procedure-chaperone-replace-proc p) + (unsafe-procedure-impersonator-replace-proc p)))] + [else (procedure-result-arity v)]))] + [else #f])) ;; ---------------------------------------- diff --git a/racket/src/cs/rumble/struct.ss b/racket/src/cs/rumble/struct.ss index 84dd37c4c6..bf3ea57df0 100644 --- a/racket/src/cs/rumble/struct.ss +++ b/racket/src/cs/rumble/struct.ss @@ -652,9 +652,10 @@ [wrap-p (procedure-rename (lambda (v) - (if (impersonator? v) - (impersonate-ref p rtd pos v) - (p v))) + ($value + (if (impersonator? v) + (impersonate-ref p rtd pos v) + (p v)))) (string->symbol (string-append (symbol->string (record-type-name rtd)) "-" (if name diff --git a/racket/src/cs/rumble/value.ss b/racket/src/cs/rumble/value.ss new file mode 100644 index 0000000000..04b2d640e1 --- /dev/null +++ b/racket/src/cs/rumble/value.ss @@ -0,0 +1,7 @@ + +;; Declare/enforce that an expression has a single result, which can +;; enable the optimizer to infer that an enclosing procedure always +;; has a single result. Beware that the subexpression of `$value` +;; is not in tail position. +(define-syntax-rule ($value x) + (#%$value x)) diff --git a/racket/src/schemify/interpret.rkt b/racket/src/schemify/interpret.rkt index d268ab8329..c0ba219893 100644 --- a/racket/src/schemify/interpret.rkt +++ b/racket/src/schemify/interpret.rkt @@ -227,7 +227,7 @@ (vector 'begin0 (compile-expr e env stack-depth stk-i #f) new-body)] - [`(pariah ,e) + [`($value ,e) (compile-expr e env stack-depth stk-i tail?)] [`(if ,tst ,thn ,els) (define then-stk-i (stack-info-branch stk-i)) diff --git a/racket/src/schemify/jitify.rkt b/racket/src/schemify/jitify.rkt index 4e0be0ed99..9b3060a645 100644 --- a/racket/src/schemify/jitify.rkt +++ b/racket/src/schemify/jitify.rkt @@ -265,10 +265,10 @@ (values (reannotate v `(begin0 ,new-v0 . ,new-body)) new-free new-lifts)] - [`(pariah ,e) + [`($value ,e) (define-values (new-e new-free new-lifts) (jitify-expr e env mutables free lifts convert-mode name in-name)) - (values (reannotate v `(pariah ,new-e)) + (values (reannotate v `($value ,new-e)) new-free new-lifts)] [`(if ,tst ,thn ,els) diff --git a/racket/src/schemify/schemify.rkt b/racket/src/schemify/schemify.rkt index b2e7a2b400..be3e9554dd 100644 --- a/racket/src/schemify/schemify.rkt +++ b/racket/src/schemify/schemify.rkt @@ -445,7 +445,7 @@ `(struct-type-constructor-add-guards ,ctr ,struct:s ',(struct-type-info-name sti))))) (define ,raw-s? (record-predicate ,struct:s)) ,@(if can-impersonate? - `((define ,s? (lambda (v) (if (,raw-s? v) #t (pariah (if (impersonator? v) (,raw-s? (impersonator-val v)) #f)))))) + `((define ,s? (lambda (v) (if (,raw-s? v) #t ($value (if (impersonator? v) (,raw-s? (impersonator-val v)) #f)))))) null) ,@(for/list ([acc/mut (in-list acc/muts)] [make-acc/mut (in-list make-acc/muts)]) @@ -459,7 +459,7 @@ (define ,acc/mut (lambda (s) (if (,raw-s? s) (,raw-acc/mut s) - (pariah (impersonate-ref ,raw-acc/mut ,struct:s ,pos s)))))) + ($value (impersonate-ref ,raw-acc/mut ,struct:s ,pos s)))))) raw-def)] [`(make-struct-field-mutator ,(? (lambda (v) (wrap-eq? v -set!))) ,pos ,_) (define raw-def `(define ,raw-acc/mut (record-mutator ,struct:s ,pos))) @@ -471,7 +471,7 @@ (define ,acc/mut (lambda (s v) (if (,raw-s? s) (,raw-acc/mut s v) - (pariah (impersonate-set! ,raw-acc/mut ,struct:s ,pos ,abs-pos s v)))))) + ($value (impersonate-set! ,raw-acc/mut ,struct:s ,pos ,abs-pos s v)))))) raw-def)] [`,_ (error "oops")])) (define ,(gensym)