From 720734a48159add364f9a07e784cf641a5c164ab Mon Sep 17 00:00:00 2001 From: Yogthos Date: Sat, 27 Jun 2026 13:33:30 -0400 Subject: [PATCH] Two general fixes shaken out by core.typed's runtime contract suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running clojure.core.typed's runtime contract tests (typed/runtime.jvm, test_contract — 5/5 pass) surfaced two general jolt gaps, both runtime, both JVM-certified: - instance? Object / java.lang.Object returned false for everything. Object is the root of the type hierarchy: every non-nil value is an instance of Object, nil is not. core.typed's (instance-c Object) contract depends on this; many libraries do. - @Compiler/LINE and @Compiler/COLUMN (clojure.lang.Compiler statics — Vars on the JVM holding the line/column of the form being compiled) were unresolved. Macros read @Compiler/LINE as a fallback when &form carries no position. Now backed by derefable cells updated per top-level form, like *current-source*. The core.typed type checker itself (tools.analyzer.jvm + ASM bytecode + clojure.lang.Compiler internals) and the cljs runtime are not portable, so the checker/check-ns surface is out of scope; this is the runtime contract layer. make test green (+4 corpus rows, 0 new divergences), shakesmoke byte-identical. --- host/chez/compile-eval.ss | 17 ++++++++++++++++- host/chez/java/records-interop.ss | 9 +++++++++ test/chez/corpus.edn | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/host/chez/compile-eval.ss b/host/chez/compile-eval.ss index ad3eb4a..38111f8 100644 --- a/host/chez/compile-eval.ss +++ b/host/chez/compile-eval.ss @@ -27,9 +27,24 @@ ;; {:line :column :file?} position map (jolt.host/form-position's shape). ;; Top-level granularity — one set per top-level form, nothing per call. (define jolt-current-source (make-thread-parameter #f)) + +;; clojure.lang.Compiler/LINE and /COLUMN — derefable cells (Vars on the JVM) +;; holding the line/column of the form being compiled. Macros read @Compiler/LINE +;; as a fallback when &form carries no position (jolt's reader stamps :line on list +;; forms, so this is rarely hit). Updated per top-level form, like *current-source*. +(define compiler-line-cell (jolt-atom-new 0)) +(define compiler-column-cell (jolt-atom-new 0)) +(let ((members (list (cons "LINE" compiler-line-cell) (cons "COLUMN" compiler-column-cell)))) + (register-class-statics! "Compiler" members) + (register-class-statics! "clojure.lang.Compiler" members)) + (define (jolt-enter-form! form) (let ((p (hc-form-position form))) - (when (pmap? p) (jolt-current-source p)))) + (when (pmap? p) + (jolt-current-source p) + (let ((line (jolt-get p hc-kw-line jolt-nil)) (col (jolt-get p hc-kw-column jolt-nil))) + (jolt-atom-val-set! compiler-line-cell (if (jolt-nil? line) 0 line)) + (jolt-atom-val-set! compiler-column-cell (if (jolt-nil? col) 0 col)))))) ;; "file:line:col" / "line:col" for the current form, or #f when none is set. (define (jolt-current-source-string) diff --git a/host/chez/java/records-interop.ss b/host/chez/java/records-interop.ss index 356ec28..8b17636 100644 --- a/host/chez/java/records-interop.ss +++ b/host/chez/java/records-interop.ss @@ -87,6 +87,15 @@ (let ((k (chez-condition-exc-class val))) (if k (if (exception-isa? k (last-dot (symbol-t-name type-sym))) #t #f) 'pass)))) +;; Object / java.lang.Object is the root of the type hierarchy: every non-nil +;; value is an instance of Object; nil is not an instance of anything. +(register-instance-check-arm! + (lambda (type-sym val) + (let ((tn (symbol-t-name type-sym))) + (if (or (string=? tn "Object") (string=? tn "java.lang.Object")) + (not (jolt-nil? val)) + 'pass)))) + (define (instance-check-base type-sym val) (let ((tname (symbol-t-name type-sym))) (cond diff --git a/test/chez/corpus.edn b/test/chez/corpus.edn index 93fa003..e6fa363 100644 --- a/test/chez/corpus.edn +++ b/test/chez/corpus.edn @@ -3353,4 +3353,8 @@ {:suite "clojure.core / range" :label "(range 5 5) is the empty seq ()" :expected "true" :actual "(= () (range 5 5))"} {:suite "clojure.core / range" :label "empty range is not nil" :expected "true" :actual "(some? (range 5 0))"} {:suite "clojure.core / range" :label "empty range count" :expected "0" :actual "(count (range 0))"} + {:suite "host-interop / instance? Object" :label "every non-nil value is an Object" :expected "[true true true true]" :actual "[(instance? Object 1) (instance? Object \"x\") (instance? Object []) (instance? Object (fn []))]"} + {:suite "host-interop / instance? Object" :label "nil is not an instance of Object" :expected "false" :actual "(instance? Object nil)"} + {:suite "host-interop / instance? Object" :label "java.lang.Object too" :expected "true" :actual "(instance? java.lang.Object :k)"} + {:suite "host-interop / Compiler" :label "@Compiler/LINE is a number" :expected "true" :actual "(number? @clojure.lang.Compiler/LINE)"} ]