Numeric return-type hints: ^double/^long on a defn (round 3)
A ^double/^long return hint on a fn's name now (a) coerces the fn's value on the way out — exact->inexact / jolt->fx, like a JVM primitive return — and (b) types a call to it, so an accumulator over the result specializes: (defn ^double work [^double x ^double y] (+ (* x x) (* y y))) (loop [acc 0.0] (recur (+ acc (work a b)))) ; (+ acc (work ..)) -> fl+ The analyzer pushes the name's numeric tag onto each arity (:ret-nhint) for the back-end coercion, and resolve-global surfaces the callee's declared return (:num-ret, read from var meta) onto the :var node so jolt.passes.numeric types the call. defn carries the name hint through. This unblocks the accumulator-over-fn-result pattern that round 2 had to demote. The win is bounded by call overhead in an open/dispatched build (~1.15x on a hot loop whose body is a helper call); it compounds with direct-linking and, later, inlining. A numeric return hint is a contract, like ^long — redefining the var to return another type in an open build breaks it. Not yet: per-arity arglist return hints, (defn f (^double [x] ..)). Gate: test/chez/numeric-test.ss 39/39; full make test green, 0 new corpus divergences.
This commit is contained in:
parent
0db417a491
commit
5a9acd3cf4
6 changed files with 227 additions and 164 deletions
|
|
@ -32,6 +32,9 @@
|
|||
(define hc-kw-name (keyword #f "name"))
|
||||
(define hc-kw-var (keyword #f "var"))
|
||||
(define hc-kw-unresolved (keyword #f "unresolved"))
|
||||
(define hc-kw-num-ret (keyword #f "num-ret"))
|
||||
(define hc-kw-double (keyword #f "double"))
|
||||
(define hc-kw-long (keyword #f "long"))
|
||||
(define hc-kw-regex (keyword #f "regex"))
|
||||
(define hc-kw-inst (keyword #f "#inst"))
|
||||
(define hc-kw-uuid (keyword #f "#uuid"))
|
||||
|
|
@ -176,13 +179,24 @@
|
|||
;; No :host branch: there is no separate native-op env — the hot
|
||||
;; clojure.core primitives (+,-,map,...) are declared in clojure.core below so
|
||||
;; they classify as :var and the emitter's native-op path lowers them.
|
||||
;; A var's declared numeric return (^double/^long on its name) -> :double/:long,
|
||||
;; read from its meta. Lets jolt.passes.numeric type a call to it.
|
||||
(define (hc-cell-num-ret cell)
|
||||
(let ((m (and cell (hashtable-ref var-meta-table cell #f))))
|
||||
(and m (let ((t (jolt-get m hc-kw-tag)))
|
||||
(cond ((equal? t "double") hc-kw-double)
|
||||
((equal? t "long") hc-kw-long)
|
||||
(else #f))))))
|
||||
|
||||
(define (hc-resolve-global ctx sym)
|
||||
(let* ((nm (symbol-t-name sym))
|
||||
(cell (hc-resolve-cell ctx sym)))
|
||||
(if (and cell (var-cell-defined? cell))
|
||||
(jolt-hash-map hc-kw-kind hc-kw-var
|
||||
hc-kw-ns (var-cell-ns cell)
|
||||
hc-kw-name (var-cell-name cell))
|
||||
(let ((base (jolt-hash-map hc-kw-kind hc-kw-var
|
||||
hc-kw-ns (var-cell-ns cell)
|
||||
hc-kw-name (var-cell-name cell)))
|
||||
(nr (hc-cell-num-ret cell)))
|
||||
(if nr (jolt-assoc base hc-kw-num-ret nr) base))
|
||||
(jolt-hash-map hc-kw-kind hc-kw-unresolved hc-kw-name nm))))
|
||||
|
||||
(define (hc-intern! ctx ns-name nm) (declare-var! ns-name nm) jolt-nil)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue