@@ -355,6 +355,49 @@ Notes:
355355 [(ref ,maybe-src ,x) (and (not (prelex-assigned x)) x)]
356356 [else #f ])))
357357
358+ (define (real-expr->flonum-expr x r )
359+ ; Transform 0 into 0.0 as usual
360+ ; Assume (predicate-implies r real-pred)
361+ (cond
362+ [(and (Lsrc? r)
363+ (nanopass-case (Lsrc Expr) r
364+ [(quote ,d ) d]
365+ [else #f ])) =>
366+ (lambda (d ) (make-1seq 'value x `(quote ,(real->flonum d) )))]
367+ [(predicate-implies? r flonum-pred)
368+ x]
369+ [else
370+ (let ([->flonum-name (if (predicate-implies? r 'fixnum )
371+ 'fixnum->flonum
372+ 'real->flonum )])
373+ `(call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x))]))
374+
375+ (define (real-expr->flonum-expr/- x r )
376+ ; Transform 0 into -0.0 instead of 0.0
377+ ; Assume (predicate-implies r real-pred)
378+ (cond
379+ [(and (Lsrc? r)
380+ (nanopass-case (Lsrc Expr) r
381+ [(quote ,d ) d]
382+ [else #f ])) =>
383+ (lambda (d ) (make-1seq 'value x `(quote ,(if (eqv? d 0) -0.0 (real->flonum d)) )))]
384+ [(predicate-implies? r flonum-pred)
385+ x]
386+ [else
387+ (let ([->flonum-name (if (predicate-implies? r 'fixnum )
388+ 'fixnum->flonum
389+ 'real->flonum )])
390+ (cond
391+ [(predicate-disjoint? r `(quote 0 ))
392+ `(call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x)]
393+ [else
394+ (build-let 'value (list x) (list r)
395+ (lambda (x* )
396+ (let ([x (car x*)])
397+ `(if (call ,(make-preinfo-call) ,(lookup-primref 3 'eq? ) ,x (quote 0 ))
398+ (quote -0.0 )
399+ (call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x)))))]))]))
400+
358401 (define (filter/head+rest pred? l )
359402 ; (filter/head+rest odd? '(1 3 2 5 4 6))
360403 ; ==> (values '(1 3) '(2 5 4 6))
@@ -1141,6 +1184,71 @@ Notes:
11411184 (and (eq? ctxt 'test )
11421185 (pred-env-add/ref ntypes val (rtd->record-predicate rtd #t ) plxc))
11431186 #f )]))])
1187+
1188+ (let ()
1189+ (define (predicate-implies-real? r ) (predicate-implies? r real-pred))
1190+ (define (predicate-implies-fixnum? r ) (predicate-implies? r 'fixnum ))
1191+ (define (predicate-implies-integer? r ) (predicate-implies? r integer-pred))
1192+ (define (predicate-implies-flonum? r ) (predicate-implies? r flonum-pred))
1193+ (define (predicate-implies-exact? r ) (predicate-implies? r exact-pred))
1194+ (define (predicate-implies-inexact? r ) (predicate-implies? r inexact-pred))
1195+
1196+ (define (predicate-close/plus r* )
1197+ (cond
1198+ [(andmap predicate-implies-exact? r*)
1199+ (if (andmap predicate-implies-real? r*)
1200+ (if (andmap predicate-implies-integer? r*)
1201+ 'exact-integer
1202+ exact-real-pred)
1203+ exact-pred)]
1204+ [(ormap predicate-implies-inexact? r*)
1205+ (if (andmap predicate-implies-real? r*)
1206+ flonum-pred
1207+ inexact-pred)]
1208+ [else
1209+ (if (andmap predicate-implies-real? r*)
1210+ real-pred
1211+ number-pred)]))
1212+
1213+ (define-specialize 2 +
1214+ [() (values `(quote 0 ) `(quote 0 ) ntypes #f #f )]
1215+ [(x) (values `(call ,preinfo ,pr ,x)
1216+ (predicate-intersect (get-type x) number-pred) ntypes #f #f )]
1217+ [x* ; x* has at least 2 arguments
1218+ (let* ([r* (get-type x*)]
1219+ [ret (predicate-close/plus
1220+ (map (lambda (r ) (predicate-intersect r number-pred)) r*))]
1221+ [ir (and (andmap predicate-implies-real? r*)
1222+ (cond
1223+ [(andmap predicate-implies-fixnum? r*)
1224+ `(call ,preinfo ,(lookup-primref 3 '$fxx+ ) ,x* ...)]
1225+ [(and (or (enable-arithmetic-left-associative)
1226+ (fx= (length r*) 2 ))
1227+ ; at least one of the first two is a flonum
1228+ (or (predicate-implies-flonum? (car r*))
1229+ (predicate-implies-flonum? (cadr r*))))
1230+ (cond
1231+ [(and (predicate-disjoint? (car r*) `(quote -0.0 ))
1232+ (predicate-disjoint? (cadr r*) `(quote -0.0 )))
1233+ ; use 0.0 in the first two and -0.0 in the others
1234+ `(call ,preinfo ,(lookup-primref 3 'fl+ )
1235+ ,(real-expr->flonum-expr (car x*) (car r*))
1236+ ,(real-expr->flonum-expr (cadr x*) (cadr r*))
1237+ ,(map real-expr->flonum-expr/- (cddr x*) (cddr r*)) ...)]
1238+ [else
1239+ `(call ,preinfo ,(lookup-primref 3 'fl+ )
1240+ ,(map real-expr->flonum-expr/- x* r*) ...)])]
1241+ [(and ; all or all but one are flonums, in case they are reordered
1242+ (let-values ([(head* rest*)
1243+ (filter/head+rest predicate-implies-flonum? r*)])
1244+ (or (null? rest*)
1245+ (andmap predicate-implies-flonum? (cdr rest*)))))
1246+ `(call ,preinfo ,(lookup-primref 3 'fl+ )
1247+ ,(map real-expr->flonum-expr/- x* r*) ...)]
1248+ [else
1249+ #f ]))])
1250+ (values (or ir `(call ,preinfo ,pr ,x* ...)) ret ntypes #f #f ))])
1251+ )
11441252
11451253 (define-specialize 2 (add1 sub1 1+ 1- -1+)
11461254 [(n) (let ([r (get-type n)])
0 commit comments