Checked narrow casts; fix runtime require in self-contained-built binaries
byte/short/int/long/char silently wrapped or passed out-of-range values through; the JVM range-checks (RT.byteCast family). One checked-cast helper now carries the ranges: a double range-checks ITSELF before truncating ((byte 1.1) is 1, (byte 127.000001) throws), NaN casts to 0, ratios and bigdecs truncate, a non-number is CCE, and the throw carries the JVM message. float range-checks against Float/MAX_VALUE. The unchecked-* casts now genuinely wrap and sign-fold ((unchecked-byte 200) is -56 — the old bit-and lost the sign) with doubles saturating like Java's conversions; unchecked-long/int are host natives. double/float of a bigdec convert instead of crashing. The no-single-float residue stays accepted (SPEC.md). Also fixes #290: a binary built by the SELF-CONTAINED joltc died with 'variable var-deref is not bound' when a namespace loaded at runtime. The in-process build compiled flat.ss against a clean copy-environment, which orphans every top-level define in locations the binary's runtime eval can't see. It now compiles against the default interaction environment (defines land in the real symbol cells, same as the legacy fresh-Chez path) and a generated prologue pre-binds each kernel name the runtime redefines to its kernel value, so the earliest boot reads match the legacy path's primitive references. requiring-resolve is implemented (the issue's dynamic-require pattern), and the release workflow smokes a runtime require in a built binary. Cast namespaces byte/short/int/long/char now fully clean; cts baseline 5805 -> 5857 pass, 67 baselined namespaces. 7 JVM-certified corpus rows.
This commit is contained in:
parent
f80f9aab4b
commit
d0e1a11934
10 changed files with 237 additions and 77 deletions
|
|
@ -561,21 +561,67 @@
|
|||
(bld-native-link-flags natives))))))))
|
||||
|
||||
;; --- self-contained link (in-process compile + append the boot to the stub) ---
|
||||
;; compile-file runs with a FRESH scheme-environment as the interaction
|
||||
;; environment: the loaded jolt runtime redefines `error` (regex.ss), and flat.ss
|
||||
;; inlines that same runtime, so an early reference to `error` (before its define
|
||||
;; runs) must bind to the kernel primitive — a clean env gives exactly that, the
|
||||
;; same as the legacy path compiling in a fresh Chez process. Without it the boot
|
||||
;; dies at startup with "variable error is not bound".
|
||||
;; compile-file runs against the DEFAULT interaction environment, so the boot's
|
||||
;; top-level defines land in the real symbol cells — the runtime compiler's
|
||||
;; eval'd code must resolve them (var-deref, jolt-invoke, the jolt-n* macros)
|
||||
;; when the built binary dynamically requires a namespace. Compiling in a clean
|
||||
;; copy-environment instead orphans every define in locations eval can't see,
|
||||
;; and the binary dies with "variable var-deref is not bound" the moment a
|
||||
;; runtime require compiles source.
|
||||
;;
|
||||
;; The default env has a wrinkle the legacy fresh-Chez path doesn't: THIS
|
||||
;; process's cells hold jolt's redefinitions of some kernel names (`error`,
|
||||
;; regex.ss), so references to them compile as cell reads — and a read that
|
||||
;; runs before the redefining form would find the fresh binary's cell unbound.
|
||||
;; The prologue closes that: it first binds each redefined kernel name's cell
|
||||
;; to its kernel value, making the boot's earliest reads identical to the
|
||||
;; legacy path's primitive references.
|
||||
|
||||
;; every top-level (define nm …)/(define (nm …) …) name in the flat file that
|
||||
;; shadows a scheme-environment VARIABLE (syntax names don't eval; skip them).
|
||||
(define (bld-kernel-prologue flat-ss)
|
||||
(let ((seen (make-eq-hashtable))
|
||||
(kenv (scheme-environment))
|
||||
(names '()))
|
||||
(let ((ip (open-input-file flat-ss)))
|
||||
(let loop ()
|
||||
(let ((f (read ip)))
|
||||
(unless (eof-object? f)
|
||||
(when (and (pair? f) (eq? (car f) 'define) (pair? (cdr f)))
|
||||
(let* ((h (cadr f))
|
||||
(nm (if (pair? h) (car h) h)))
|
||||
(when (and (symbol? nm)
|
||||
(not (hashtable-ref seen nm #f))
|
||||
(guard (e (#t #f)) (begin (eval nm kenv) #t)))
|
||||
(hashtable-set! seen nm #t)
|
||||
(set! names (cons nm names)))))
|
||||
(loop))))
|
||||
(close-port ip))
|
||||
(apply string-append
|
||||
(map (lambda (nm)
|
||||
(let ((s (symbol->string nm)))
|
||||
(string-append "(define " s " (eval '" s " (scheme-environment)))\n")))
|
||||
(reverse names)))))
|
||||
|
||||
;; prepend the prologue to the flat file in place.
|
||||
(define (bld-prepend-prologue! flat-ss)
|
||||
(let ((prologue (bld-kernel-prologue flat-ss))
|
||||
(body (read-file-string flat-ss)))
|
||||
(let ((out (open-output-file flat-ss 'replace)))
|
||||
(put-string out ";; kernel-name cells pre-bound so early reads match the kernel primitives\n")
|
||||
(put-string out prologue)
|
||||
(put-string out body)
|
||||
(close-port out))))
|
||||
|
||||
(define (build-self-contained entry-ns out-path mode builddir flat-ss flat-so boot native-link)
|
||||
(let ((petite (string-append builddir "/petite.boot"))
|
||||
(scheme (string-append builddir "/scheme.boot")))
|
||||
(jolt-spill-embedded! "csv/petite.boot" petite)
|
||||
(jolt-spill-embedded! "csv/scheme.boot" scheme)
|
||||
(display (string-append "jolt build: compiling " entry-ns " (" mode " mode, self-contained)\n"))
|
||||
(parameterize ((interaction-environment (copy-environment (scheme-environment))))
|
||||
(compile-file flat-ss flat-so)
|
||||
(make-boot-file boot '() petite scheme flat-so))
|
||||
(bld-prepend-prologue! flat-ss)
|
||||
(compile-file flat-ss flat-so)
|
||||
(make-boot-file boot '() petite scheme flat-so)
|
||||
;; The stub is the native launcher the boot is appended to. With no :static
|
||||
;; natives it's the prebuilt one bundled in joltc (no cc needed); with :static
|
||||
;; natives it's re-linked here from the bundled kernel + launcher source so the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue