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)"} ]