Merge pull request #57 from jolt-lang/spec-untested-vars

spec: rows for every untested var (131 -> 0); five real bugs found by the probes
This commit is contained in:
Dmitri Sotnikov 2026-06-10 17:58:28 -04:00 committed by GitHub
commit fef99db6d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 414 additions and 151 deletions

View file

@ -7,9 +7,9 @@ community examples). jolt interns 564 of them.
| Status | Count | Meaning | | Status | Count | Meaning |
|---|---|---| |---|---|---|
| implemented+tested | 433 | in jolt and exercised by spec/conformance | | implemented+tested | 564 | in jolt and exercised by spec/conformance |
| implemented-untested | 131 | in jolt, no direct test — spec entries will add them | | implemented-untested | 0 | in jolt, no direct test — spec entries will add them |
| resolvable-not-interned | 2 | works in code but invisible to ns introspection (conformance finding) | | resolvable-not-interned | 1 | works in code but invisible to ns introspection (conformance finding) |
| missing-portable | 0 | portable semantics, jolt lacks it — implementation gap | | missing-portable | 0 | portable semantics, jolt lacks it — implementation gap |
| special-form | 15 | specified in §3, not a library var | | special-form | 15 | specified in §3, not a library var |
| dynamic-var | 29 | classification needed: portable default vs host-dependent | | dynamic-var | 29 | classification needed: portable default vs host-dependent |
@ -26,28 +26,28 @@ UNVERIFIED field; that column will be added as entries land.
| Var | Status | ClojureDocs examples | | Var | Status | ClojureDocs examples |
|---|---|---| |---|---|---|
| `*` | implemented+tested | ✓ | | `*` | implemented+tested | ✓ |
| `*'` | implemented-untested | ✓ | | `*'` | implemented+tested | ✓ |
| `*1` | implemented-untested | ✓ | | `*1` | implemented+tested | ✓ |
| `*2` | implemented-untested | ✓ | | `*2` | implemented+tested | ✓ |
| `*3` | implemented-untested | ✓ | | `*3` | implemented+tested | ✓ |
| `*agent*` | dynamic-var | ✓ | | `*agent*` | dynamic-var | ✓ |
| `*allow-unresolved-vars*` | dynamic-var | ✓ | | `*allow-unresolved-vars*` | dynamic-var | ✓ |
| `*assert*` | dynamic-var | ✓ | | `*assert*` | dynamic-var | ✓ |
| `*clojure-version*` | implemented-untested | ✓ | | `*clojure-version*` | implemented+tested | ✓ |
| `*command-line-args*` | dynamic-var | ✓ | | `*command-line-args*` | dynamic-var | ✓ |
| `*compile-files*` | dynamic-var | ✓ | | `*compile-files*` | dynamic-var | ✓ |
| `*compile-path*` | dynamic-var | ✓ | | `*compile-path*` | dynamic-var | ✓ |
| `*compiler-options*` | dynamic-var | ✓ | | `*compiler-options*` | dynamic-var | ✓ |
| `*data-readers*` | dynamic-var | ✓ | | `*data-readers*` | dynamic-var | ✓ |
| `*default-data-reader-fn*` | dynamic-var | ✓ | | `*default-data-reader-fn*` | dynamic-var | ✓ |
| `*e` | implemented-untested | ✓ | | `*e` | implemented+tested | ✓ |
| `*err*` | dynamic-var | ✓ | | `*err*` | dynamic-var | ✓ |
| `*file*` | dynamic-var | ✓ | | `*file*` | dynamic-var | ✓ |
| `*flush-on-newline*` | dynamic-var | | | `*flush-on-newline*` | dynamic-var | |
| `*fn-loader*` | dynamic-var | | | `*fn-loader*` | dynamic-var | |
| `*in*` | implemented-untested | | | `*in*` | implemented+tested | |
| `*math-context*` | dynamic-var | | | `*math-context*` | dynamic-var | |
| `*ns*` | implemented-untested | ✓ | | `*ns*` | implemented+tested | ✓ |
| `*out*` | dynamic-var | ✓ | | `*out*` | dynamic-var | ✓ |
| `*print-dup*` | dynamic-var | ✓ | | `*print-dup*` | dynamic-var | ✓ |
| `*print-length*` | dynamic-var | ✓ | | `*print-length*` | dynamic-var | ✓ |
@ -60,26 +60,26 @@ UNVERIFIED field; that column will be added as entries land.
| `*repl*` | dynamic-var | | | `*repl*` | dynamic-var | |
| `*source-path*` | dynamic-var | ✓ | | `*source-path*` | dynamic-var | ✓ |
| `*suppress-read*` | dynamic-var | | | `*suppress-read*` | dynamic-var | |
| `*unchecked-math*` | implemented-untested | ✓ | | `*unchecked-math*` | implemented+tested | ✓ |
| `*use-context-classloader*` | dynamic-var | ✓ | | `*use-context-classloader*` | dynamic-var | ✓ |
| `*verbose-defrecords*` | dynamic-var | | | `*verbose-defrecords*` | dynamic-var | |
| `*warn-on-reflection*` | dynamic-var | ✓ | | `*warn-on-reflection*` | dynamic-var | ✓ |
| `+` | implemented+tested | ✓ | | `+` | implemented+tested | ✓ |
| `+'` | implemented-untested | ✓ | | `+'` | implemented+tested | ✓ |
| `-` | implemented+tested | ✓ | | `-` | implemented+tested | ✓ |
| `-'` | implemented-untested | ✓ | | `-'` | implemented+tested | ✓ |
| `->` | implemented+tested | ✓ | | `->` | implemented+tested | ✓ |
| `->>` | implemented+tested | ✓ | | `->>` | implemented+tested | ✓ |
| `->ArrayChunk` | jvm-specific | | | `->ArrayChunk` | jvm-specific | |
| `->Eduction` | implemented-untested | | | `->Eduction` | implemented+tested | |
| `->Vec` | jvm-specific | | | `->Vec` | jvm-specific | |
| `->VecNode` | jvm-specific | | | `->VecNode` | jvm-specific | |
| `->VecSeq` | jvm-specific | | | `->VecSeq` | jvm-specific | |
| `-cache-protocol-fn` | jvm-specific | | | `-cache-protocol-fn` | jvm-specific | |
| `-reset-methods` | jvm-specific | | | `-reset-methods` | jvm-specific | |
| `.` | implemented-untested | ✓ | | `.` | implemented+tested | ✓ |
| `..` | implemented-untested | ✓ | | `..` | implemented+tested | ✓ |
| `/` | implemented-untested | ✓ | | `/` | implemented+tested | ✓ |
| `<` | implemented+tested | ✓ | | `<` | implemented+tested | ✓ |
| `<=` | implemented+tested | ✓ | | `<=` | implemented+tested | ✓ |
| `=` | implemented+tested | ✓ | | `=` | implemented+tested | ✓ |
@ -94,7 +94,7 @@ UNVERIFIED field; that column will be added as entries land.
| `Throwable->map` | jvm-specific | ✓ | | `Throwable->map` | jvm-specific | ✓ |
| `abs` | implemented+tested | ✓ | | `abs` | implemented+tested | ✓ |
| `accessor` | jvm-specific | ✓ | | `accessor` | jvm-specific | ✓ |
| `aclone` | implemented-untested | ✓ | | `aclone` | implemented+tested | ✓ |
| `add-classpath` | jvm-specific | ✓ | | `add-classpath` | jvm-specific | ✓ |
| `add-tap` | agents-taps | ✓ | | `add-tap` | agents-taps | ✓ |
| `add-watch` | implemented+tested | ✓ | | `add-watch` | implemented+tested | ✓ |
@ -104,7 +104,7 @@ UNVERIFIED field; that column will be added as entries land.
| `aget` | implemented+tested | ✓ | | `aget` | implemented+tested | ✓ |
| `alength` | implemented+tested | ✓ | | `alength` | implemented+tested | ✓ |
| `alias` | implemented+tested | ✓ | | `alias` | implemented+tested | ✓ |
| `all-ns` | implemented-untested | ✓ | | `all-ns` | implemented+tested | ✓ |
| `alter` | stm-refs | ✓ | | `alter` | stm-refs | ✓ |
| `alter-meta!` | implemented+tested | ✓ | | `alter-meta!` | implemented+tested | ✓ |
| `alter-var-root` | implemented+tested | ✓ | | `alter-var-root` | implemented+tested | ✓ |
@ -117,14 +117,14 @@ UNVERIFIED field; that column will be added as entries land.
| `array-map` | implemented+tested | ✓ | | `array-map` | implemented+tested | ✓ |
| `as->` | implemented+tested | ✓ | | `as->` | implemented+tested | ✓ |
| `aset` | implemented+tested | ✓ | | `aset` | implemented+tested | ✓ |
| `aset-boolean` | implemented-untested | ✓ | | `aset-boolean` | implemented+tested | ✓ |
| `aset-byte` | implemented-untested | ✓ | | `aset-byte` | implemented+tested | ✓ |
| `aset-char` | implemented-untested | ✓ | | `aset-char` | implemented+tested | ✓ |
| `aset-double` | implemented-untested | ✓ | | `aset-double` | implemented+tested | ✓ |
| `aset-float` | implemented-untested | ✓ | | `aset-float` | implemented+tested | ✓ |
| `aset-int` | implemented-untested | ✓ | | `aset-int` | implemented+tested | ✓ |
| `aset-long` | implemented-untested | ✓ | | `aset-long` | implemented+tested | ✓ |
| `aset-short` | implemented-untested | ✓ | | `aset-short` | implemented+tested | ✓ |
| `assert` | implemented+tested | ✓ | | `assert` | implemented+tested | ✓ |
| `assoc` | implemented+tested | ✓ | | `assoc` | implemented+tested | ✓ |
| `assoc!` | implemented+tested | ✓ | | `assoc!` | implemented+tested | ✓ |
@ -135,16 +135,16 @@ UNVERIFIED field; that column will be added as entries land.
| `await-for` | agents-taps | ✓ | | `await-for` | agents-taps | ✓ |
| `await1` | agents-taps | | | `await1` | agents-taps | |
| `bases` | jvm-specific | ✓ | | `bases` | jvm-specific | ✓ |
| `bean` | implemented-untested | ✓ | | `bean` | implemented+tested | ✓ |
| `bigdec` | implemented+tested | ✓ | | `bigdec` | implemented+tested | ✓ |
| `bigint` | implemented+tested | ✓ | | `bigint` | implemented+tested | ✓ |
| `biginteger` | implemented-untested | ✓ | | `biginteger` | implemented+tested | ✓ |
| `binding` | implemented+tested | ✓ | | `binding` | implemented+tested | ✓ |
| `bit-and` | implemented+tested | ✓ | | `bit-and` | implemented+tested | ✓ |
| `bit-and-not` | implemented-untested | ✓ | | `bit-and-not` | implemented+tested | ✓ |
| `bit-clear` | implemented+tested | ✓ | | `bit-clear` | implemented+tested | ✓ |
| `bit-flip` | implemented-untested | ✓ | | `bit-flip` | implemented+tested | ✓ |
| `bit-not` | implemented-untested | ✓ | | `bit-not` | implemented+tested | ✓ |
| `bit-or` | implemented+tested | ✓ | | `bit-or` | implemented+tested | ✓ |
| `bit-set` | implemented+tested | ✓ | | `bit-set` | implemented+tested | ✓ |
| `bit-shift-left` | implemented+tested | ✓ | | `bit-shift-left` | implemented+tested | ✓ |
@ -152,37 +152,37 @@ UNVERIFIED field; that column will be added as entries land.
| `bit-test` | implemented+tested | ✓ | | `bit-test` | implemented+tested | ✓ |
| `bit-xor` | implemented+tested | ✓ | | `bit-xor` | implemented+tested | ✓ |
| `boolean` | implemented+tested | ✓ | | `boolean` | implemented+tested | ✓ |
| `boolean-array` | implemented-untested | ✓ | | `boolean-array` | implemented+tested | ✓ |
| `boolean?` | implemented+tested | ✓ | | `boolean?` | implemented+tested | ✓ |
| `booleans` | implemented-untested | ✓ | | `booleans` | implemented+tested | ✓ |
| `bound-fn` | implemented-untested | ✓ | | `bound-fn` | implemented+tested | ✓ |
| `bound-fn*` | implemented+tested | ✓ | | `bound-fn*` | implemented+tested | ✓ |
| `bound?` | implemented+tested | ✓ | | `bound?` | implemented+tested | ✓ |
| `bounded-count` | implemented+tested | ✓ | | `bounded-count` | implemented+tested | ✓ |
| `butlast` | implemented+tested | ✓ | | `butlast` | implemented+tested | ✓ |
| `byte` | implemented-untested | ✓ | | `byte` | implemented+tested | ✓ |
| `byte-array` | implemented-untested | ✓ | | `byte-array` | implemented+tested | ✓ |
| `bytes` | implemented-untested | ✓ | | `bytes` | implemented+tested | ✓ |
| `bytes?` | implemented-untested | ✓ | | `bytes?` | implemented+tested | ✓ |
| `case` | implemented+tested | ✓ | | `case` | implemented+tested | ✓ |
| `cast` | jvm-specific | ✓ | | `cast` | jvm-specific | ✓ |
| `cat` | implemented-untested | ✓ | | `cat` | implemented+tested | ✓ |
| `catch` | special-form | ✓ | | `catch` | special-form | ✓ |
| `char` | implemented+tested | ✓ | | `char` | implemented+tested | ✓ |
| `char-array` | implemented-untested | ✓ | | `char-array` | implemented+tested | ✓ |
| `char-escape-string` | implemented+tested | ✓ | | `char-escape-string` | implemented+tested | ✓ |
| `char-name-string` | implemented+tested | ✓ | | `char-name-string` | implemented+tested | ✓ |
| `char?` | implemented+tested | ✓ | | `char?` | implemented+tested | ✓ |
| `chars` | implemented-untested | ✓ | | `chars` | implemented+tested | ✓ |
| `chunk` | implemented-untested | ✓ | | `chunk` | implemented+tested | ✓ |
| `chunk-append` | implemented-untested | ✓ | | `chunk-append` | implemented+tested | ✓ |
| `chunk-buffer` | implemented-untested | ✓ | | `chunk-buffer` | implemented+tested | ✓ |
| `chunk-cons` | implemented-untested | ✓ | | `chunk-cons` | implemented+tested | ✓ |
| `chunk-first` | implemented-untested | ✓ | | `chunk-first` | implemented+tested | ✓ |
| `chunk-next` | implemented-untested | ✓ | | `chunk-next` | implemented+tested | ✓ |
| `chunk-rest` | implemented-untested | ✓ | | `chunk-rest` | implemented+tested | ✓ |
| `chunked-seq?` | implemented+tested | ✓ | | `chunked-seq?` | implemented+tested | ✓ |
| `class` | implemented-untested | ✓ | | `class` | implemented+tested | ✓ |
| `class?` | jvm-specific | ✓ | | `class?` | jvm-specific | ✓ |
| `clear-agent-errors` | agents-taps | | | `clear-agent-errors` | agents-taps | |
| `clojure-version` | implemented+tested | ✓ | | `clojure-version` | implemented+tested | ✓ |
@ -205,7 +205,7 @@ UNVERIFIED field; that column will be added as entries land.
| `conj!` | implemented+tested | ✓ | | `conj!` | implemented+tested | ✓ |
| `cons` | implemented+tested | ✓ | | `cons` | implemented+tested | ✓ |
| `constantly` | implemented+tested | ✓ | | `constantly` | implemented+tested | ✓ |
| `construct-proxy` | implemented-untested | ✓ | | `construct-proxy` | implemented+tested | ✓ |
| `contains?` | implemented+tested | ✓ | | `contains?` | implemented+tested | ✓ |
| `count` | implemented+tested | ✓ | | `count` | implemented+tested | ✓ |
| `counted?` | implemented+tested | ✓ | | `counted?` | implemented+tested | ✓ |
@ -213,14 +213,14 @@ UNVERIFIED field; that column will be added as entries land.
| `create-struct` | jvm-specific | ✓ | | `create-struct` | jvm-specific | ✓ |
| `cycle` | implemented+tested | ✓ | | `cycle` | implemented+tested | ✓ |
| `dec` | implemented+tested | ✓ | | `dec` | implemented+tested | ✓ |
| `dec'` | implemented-untested | ✓ | | `dec'` | implemented+tested | ✓ |
| `decimal?` | implemented+tested | ✓ | | `decimal?` | implemented+tested | ✓ |
| `declare` | implemented+tested | ✓ | | `declare` | implemented+tested | ✓ |
| `dedupe` | implemented+tested | ✓ | | `dedupe` | implemented+tested | ✓ |
| `def` | special-form | ✓ | | `def` | special-form | ✓ |
| `default-data-readers` | jvm-specific | ✓ | | `default-data-readers` | jvm-specific | ✓ |
| `definline` | jvm-specific | | | `definline` | jvm-specific | |
| `definterface` | implemented-untested | ✓ | | `definterface` | implemented+tested | ✓ |
| `defmacro` | special-form | ✓ | | `defmacro` | special-form | ✓ |
| `defmethod` | implemented+tested | ✓ | | `defmethod` | implemented+tested | ✓ |
| `defmulti` | implemented+tested | ✓ | | `defmulti` | implemented+tested | ✓ |
@ -232,13 +232,13 @@ UNVERIFIED field; that column will be added as entries land.
| `defstruct` | jvm-specific | ✓ | | `defstruct` | jvm-specific | ✓ |
| `deftype` | implemented+tested | ✓ | | `deftype` | implemented+tested | ✓ |
| `delay` | implemented+tested | ✓ | | `delay` | implemented+tested | ✓ |
| `delay?` | implemented-untested | ✓ | | `delay?` | implemented+tested | ✓ |
| `deliver` | implemented+tested | ✓ | | `deliver` | implemented+tested | ✓ |
| `denominator` | implemented+tested | ✓ | | `denominator` | implemented+tested | ✓ |
| `deref` | implemented+tested | ✓ | | `deref` | implemented+tested | ✓ |
| `derive` | implemented+tested | ✓ | | `derive` | implemented+tested | ✓ |
| `descendants` | implemented+tested | ✓ | | `descendants` | implemented+tested | ✓ |
| `destructure` | implemented-untested | ✓ | | `destructure` | implemented+tested | ✓ |
| `disj` | implemented+tested | ✓ | | `disj` | implemented+tested | ✓ |
| `disj!` | implemented+tested | ✓ | | `disj!` | implemented+tested | ✓ |
| `dissoc` | implemented+tested | ✓ | | `dissoc` | implemented+tested | ✓ |
@ -252,10 +252,10 @@ UNVERIFIED field; that column will be added as entries land.
| `dosync` | stm-refs | ✓ | | `dosync` | stm-refs | ✓ |
| `dotimes` | implemented+tested | ✓ | | `dotimes` | implemented+tested | ✓ |
| `doto` | implemented+tested | ✓ | | `doto` | implemented+tested | ✓ |
| `double` | implemented-untested | ✓ | | `double` | implemented+tested | ✓ |
| `double-array` | implemented-untested | ✓ | | `double-array` | implemented+tested | ✓ |
| `double?` | implemented+tested | ✓ | | `double?` | implemented+tested | ✓ |
| `doubles` | implemented-untested | ✓ | | `doubles` | implemented+tested | ✓ |
| `drop` | implemented+tested | ✓ | | `drop` | implemented+tested | ✓ |
| `drop-last` | implemented+tested | ✓ | | `drop-last` | implemented+tested | ✓ |
| `drop-while` | implemented+tested | ✓ | | `drop-while` | implemented+tested | ✓ |
@ -263,8 +263,8 @@ UNVERIFIED field; that column will be added as entries land.
| `empty` | implemented+tested | ✓ | | `empty` | implemented+tested | ✓ |
| `empty?` | implemented+tested | ✓ | | `empty?` | implemented+tested | ✓ |
| `ensure` | stm-refs | ✓ | | `ensure` | stm-refs | ✓ |
| `ensure-reduced` | implemented-untested | ✓ | | `ensure-reduced` | implemented+tested | ✓ |
| `enumeration-seq` | implemented-untested | ✓ | | `enumeration-seq` | implemented+tested | ✓ |
| `error-handler` | agents-taps | ✓ | | `error-handler` | agents-taps | ✓ |
| `error-mode` | agents-taps | ✓ | | `error-mode` | agents-taps | ✓ |
| `eval` | implemented+tested | ✓ | | `eval` | implemented+tested | ✓ |
@ -275,11 +275,11 @@ UNVERIFIED field; that column will be added as entries land.
| `ex-data` | implemented+tested | ✓ | | `ex-data` | implemented+tested | ✓ |
| `ex-info` | implemented+tested | ✓ | | `ex-info` | implemented+tested | ✓ |
| `ex-message` | implemented+tested | ✓ | | `ex-message` | implemented+tested | ✓ |
| `extend` | implemented-untested | ✓ | | `extend` | implemented+tested | ✓ |
| `extend-protocol` | implemented+tested | ✓ | | `extend-protocol` | implemented+tested | ✓ |
| `extend-type` | implemented+tested | ✓ | | `extend-type` | implemented+tested | ✓ |
| `extenders` | implemented+tested | ✓ | | `extenders` | implemented+tested | ✓ |
| `extends?` | implemented-untested | ✓ | | `extends?` | implemented+tested | ✓ |
| `false?` | implemented+tested | ✓ | | `false?` | implemented+tested | ✓ |
| `ffirst` | implemented+tested | ✓ | | `ffirst` | implemented+tested | ✓ |
| `file-seq` | implemented+tested | ✓ | | `file-seq` | implemented+tested | ✓ |
@ -294,10 +294,10 @@ UNVERIFIED field; that column will be added as entries land.
| `find-var` | implemented+tested | ✓ | | `find-var` | implemented+tested | ✓ |
| `first` | implemented+tested | ✓ | | `first` | implemented+tested | ✓ |
| `flatten` | implemented+tested | ✓ | | `flatten` | implemented+tested | ✓ |
| `float` | implemented-untested | ✓ | | `float` | implemented+tested | ✓ |
| `float-array` | implemented-untested | ✓ | | `float-array` | implemented+tested | ✓ |
| `float?` | implemented+tested | ✓ | | `float?` | implemented+tested | ✓ |
| `floats` | implemented-untested | ✓ | | `floats` | implemented+tested | ✓ |
| `flush` | implemented+tested | ✓ | | `flush` | implemented+tested | ✓ |
| `fn` | implemented+tested | ✓ | | `fn` | implemented+tested | ✓ |
| `fn?` | implemented+tested | ✓ | | `fn?` | implemented+tested | ✓ |
@ -308,7 +308,7 @@ UNVERIFIED field; that column will be added as entries land.
| `format` | implemented+tested | ✓ | | `format` | implemented+tested | ✓ |
| `frequencies` | implemented+tested | ✓ | | `frequencies` | implemented+tested | ✓ |
| `future` | implemented+tested | ✓ | | `future` | implemented+tested | ✓ |
| `future-call` | implemented-untested | ✓ | | `future-call` | implemented+tested | ✓ |
| `future-cancel` | implemented+tested | ✓ | | `future-cancel` | implemented+tested | ✓ |
| `future-cancelled?` | implemented+tested | ✓ | | `future-cancelled?` | implemented+tested | ✓ |
| `future-done?` | implemented+tested | ✓ | | `future-done?` | implemented+tested | ✓ |
@ -319,17 +319,17 @@ UNVERIFIED field; that column will be added as entries land.
| `get` | implemented+tested | ✓ | | `get` | implemented+tested | ✓ |
| `get-in` | implemented+tested | ✓ | | `get-in` | implemented+tested | ✓ |
| `get-method` | implemented+tested | ✓ | | `get-method` | implemented+tested | ✓ |
| `get-proxy-class` | implemented-untested | ✓ | | `get-proxy-class` | implemented+tested | ✓ |
| `get-thread-bindings` | implemented+tested | ✓ | | `get-thread-bindings` | implemented+tested | ✓ |
| `get-validator` | implemented+tested | ✓ | | `get-validator` | implemented+tested | ✓ |
| `group-by` | implemented+tested | ✓ | | `group-by` | implemented+tested | ✓ |
| `halt-when` | implemented-untested | ✓ | | `halt-when` | implemented+tested | ✓ |
| `hash` | implemented-untested | ✓ | | `hash` | implemented+tested | ✓ |
| `hash-combine` | implemented-untested | ✓ | | `hash-combine` | implemented+tested | ✓ |
| `hash-map` | implemented+tested | ✓ | | `hash-map` | implemented+tested | ✓ |
| `hash-ordered-coll` | implemented-untested | ✓ | | `hash-ordered-coll` | implemented+tested | ✓ |
| `hash-set` | implemented+tested | ✓ | | `hash-set` | implemented+tested | ✓ |
| `hash-unordered-coll` | implemented-untested | ✓ | | `hash-unordered-coll` | implemented+tested | ✓ |
| `ident?` | implemented+tested | ✓ | | `ident?` | implemented+tested | ✓ |
| `identical?` | implemented+tested | ✓ | | `identical?` | implemented+tested | ✓ |
| `identity` | implemented+tested | ✓ | | `identity` | implemented+tested | ✓ |
@ -341,29 +341,29 @@ UNVERIFIED field; that column will be added as entries land.
| `import` | implemented+tested | ✓ | | `import` | implemented+tested | ✓ |
| `in-ns` | implemented+tested | ✓ | | `in-ns` | implemented+tested | ✓ |
| `inc` | implemented+tested | ✓ | | `inc` | implemented+tested | ✓ |
| `inc'` | implemented-untested | ✓ | | `inc'` | implemented+tested | ✓ |
| `indexed?` | implemented+tested | ✓ | | `indexed?` | implemented+tested | ✓ |
| `infinite?` | implemented+tested | ✓ | | `infinite?` | implemented+tested | ✓ |
| `init-proxy` | implemented-untested | ✓ | | `init-proxy` | implemented+tested | ✓ |
| `inst-ms` | implemented+tested | ✓ | | `inst-ms` | implemented+tested | ✓ |
| `inst-ms*` | implemented+tested | | | `inst-ms*` | implemented+tested | |
| `inst?` | implemented+tested | ✓ | | `inst?` | implemented+tested | ✓ |
| `instance?` | implemented+tested | ✓ | | `instance?` | implemented+tested | ✓ |
| `int` | implemented+tested | ✓ | | `int` | implemented+tested | ✓ |
| `int-array` | implemented-untested | ✓ | | `int-array` | implemented+tested | ✓ |
| `int?` | implemented+tested | ✓ | | `int?` | implemented+tested | ✓ |
| `integer?` | implemented+tested | ✓ | | `integer?` | implemented+tested | ✓ |
| `interleave` | implemented+tested | ✓ | | `interleave` | implemented+tested | ✓ |
| `intern` | implemented+tested | ✓ | | `intern` | implemented+tested | ✓ |
| `interpose` | implemented+tested | ✓ | | `interpose` | implemented+tested | ✓ |
| `into` | implemented+tested | ✓ | | `into` | implemented+tested | ✓ |
| `into-array` | implemented-untested | ✓ | | `into-array` | implemented+tested | ✓ |
| `ints` | implemented-untested | ✓ | | `ints` | implemented+tested | ✓ |
| `io!` | stm-refs | ✓ | | `io!` | stm-refs | ✓ |
| `isa?` | implemented+tested | ✓ | | `isa?` | implemented+tested | ✓ |
| `iterate` | implemented+tested | ✓ | | `iterate` | implemented+tested | ✓ |
| `iteration` | jvm-specific | ✓ | | `iteration` | jvm-specific | ✓ |
| `iterator-seq` | implemented-untested | ✓ | | `iterator-seq` | implemented+tested | ✓ |
| `juxt` | implemented+tested | ✓ | | `juxt` | implemented+tested | ✓ |
| `keep` | implemented+tested | ✓ | | `keep` | implemented+tested | ✓ |
| `keep-indexed` | implemented+tested | ✓ | | `keep-indexed` | implemented+tested | ✓ |
@ -386,13 +386,13 @@ UNVERIFIED field; that column will be added as entries land.
| `load-string` | implemented+tested | ✓ | | `load-string` | implemented+tested | ✓ |
| `loaded-libs` | jvm-specific | ✓ | | `loaded-libs` | jvm-specific | ✓ |
| `locking` | implemented+tested | ✓ | | `locking` | implemented+tested | ✓ |
| `long` | implemented-untested | ✓ | | `long` | implemented+tested | ✓ |
| `long-array` | implemented-untested | ✓ | | `long-array` | implemented+tested | ✓ |
| `longs` | implemented-untested | ✓ | | `longs` | implemented+tested | ✓ |
| `loop` | implemented+tested | ✓ | | `loop` | implemented+tested | ✓ |
| `macroexpand` | implemented+tested | ✓ | | `macroexpand` | implemented+tested | ✓ |
| `macroexpand-1` | implemented+tested | ✓ | | `macroexpand-1` | implemented+tested | ✓ |
| `make-array` | implemented-untested | ✓ | | `make-array` | implemented+tested | ✓ |
| `make-hierarchy` | implemented+tested | ✓ | | `make-hierarchy` | implemented+tested | ✓ |
| `map` | implemented+tested | ✓ | | `map` | implemented+tested | ✓ |
| `map-entry?` | implemented+tested | ✓ | | `map-entry?` | implemented+tested | ✓ |
@ -402,7 +402,7 @@ UNVERIFIED field; that column will be added as entries land.
| `mapv` | implemented+tested | ✓ | | `mapv` | implemented+tested | ✓ |
| `max` | implemented+tested | ✓ | | `max` | implemented+tested | ✓ |
| `max-key` | implemented+tested | ✓ | | `max-key` | implemented+tested | ✓ |
| `memfn` | implemented-untested | ✓ | | `memfn` | implemented+tested | ✓ |
| `memoize` | implemented+tested | ✓ | | `memoize` | implemented+tested | ✓ |
| `merge` | implemented+tested | ✓ | | `merge` | implemented+tested | ✓ |
| `merge-with` | implemented+tested | ✓ | | `merge-with` | implemented+tested | ✓ |
@ -425,7 +425,7 @@ UNVERIFIED field; that column will be added as entries land.
| `new` | special-form | ✓ | | `new` | special-form | ✓ |
| `newline` | implemented+tested | ✓ | | `newline` | implemented+tested | ✓ |
| `next` | implemented+tested | ✓ | | `next` | implemented+tested | ✓ |
| `nfirst` | implemented-untested | ✓ | | `nfirst` | implemented+tested | ✓ |
| `nil?` | implemented+tested | ✓ | | `nil?` | implemented+tested | ✓ |
| `nnext` | implemented+tested | ✓ | | `nnext` | implemented+tested | ✓ |
| `not` | implemented+tested | ✓ | | `not` | implemented+tested | ✓ |
@ -435,8 +435,8 @@ UNVERIFIED field; that column will be added as entries land.
| `not=` | implemented+tested | ✓ | | `not=` | implemented+tested | ✓ |
| `ns` | implemented+tested | ✓ | | `ns` | implemented+tested | ✓ |
| `ns-aliases` | implemented+tested | ✓ | | `ns-aliases` | implemented+tested | ✓ |
| `ns-imports` | implemented-untested | ✓ | | `ns-imports` | implemented+tested | ✓ |
| `ns-interns` | implemented-untested | ✓ | | `ns-interns` | implemented+tested | ✓ |
| `ns-map` | implemented+tested | ✓ | | `ns-map` | implemented+tested | ✓ |
| `ns-name` | implemented+tested | ✓ | | `ns-name` | implemented+tested | ✓ |
| `ns-publics` | implemented+tested | ✓ | | `ns-publics` | implemented+tested | ✓ |
@ -470,18 +470,18 @@ UNVERIFIED field; that column will be added as entries land.
| `pmap` | jvm-specific | ✓ | | `pmap` | jvm-specific | ✓ |
| `pop` | implemented+tested | ✓ | | `pop` | implemented+tested | ✓ |
| `pop!` | implemented+tested | ✓ | | `pop!` | implemented+tested | ✓ |
| `pop-thread-bindings` | implemented-untested | | | `pop-thread-bindings` | implemented+tested | |
| `pos-int?` | implemented+tested | ✓ | | `pos-int?` | implemented+tested | ✓ |
| `pos?` | implemented+tested | ✓ | | `pos?` | implemented+tested | ✓ |
| `pr` | implemented+tested | ✓ | | `pr` | implemented+tested | ✓ |
| `pr-str` | implemented+tested | ✓ | | `pr-str` | implemented+tested | ✓ |
| `prefer-method` | implemented+tested | ✓ | | `prefer-method` | implemented+tested | ✓ |
| `prefers` | implemented-untested | ✓ | | `prefers` | implemented+tested | ✓ |
| `primitives-classnames` | jvm-specific | ✓ | | `primitives-classnames` | jvm-specific | ✓ |
| `print` | implemented+tested | ✓ | | `print` | implemented+tested | ✓ |
| `print-ctor` | jvm-specific | ✓ | | `print-ctor` | jvm-specific | ✓ |
| `print-dup` | implemented-untested | ✓ | | `print-dup` | implemented+tested | ✓ |
| `print-method` | implemented-untested | ✓ | | `print-method` | implemented+tested | ✓ |
| `print-simple` | jvm-specific | ✓ | | `print-simple` | jvm-specific | ✓ |
| `print-str` | implemented+tested | ✓ | | `print-str` | implemented+tested | ✓ |
| `printf` | implemented+tested | ✓ | | `printf` | implemented+tested | ✓ |
@ -490,12 +490,12 @@ UNVERIFIED field; that column will be added as entries land.
| `prn` | implemented+tested | ✓ | | `prn` | implemented+tested | ✓ |
| `prn-str` | implemented+tested | ✓ | | `prn-str` | implemented+tested | ✓ |
| `promise` | implemented+tested | ✓ | | `promise` | implemented+tested | ✓ |
| `proxy` | implemented-untested | ✓ | | `proxy` | implemented+tested | ✓ |
| `proxy-call-with-super` | implemented-untested | | | `proxy-call-with-super` | implemented+tested | |
| `proxy-mappings` | implemented-untested | ✓ | | `proxy-mappings` | implemented+tested | ✓ |
| `proxy-name` | jvm-specific | | | `proxy-name` | jvm-specific | |
| `proxy-super` | implemented-untested | ✓ | | `proxy-super` | implemented+tested | ✓ |
| `push-thread-bindings` | implemented-untested | | | `push-thread-bindings` | implemented+tested | |
| `pvalues` | jvm-specific | ✓ | | `pvalues` | jvm-specific | ✓ |
| `qualified-ident?` | implemented+tested | ✓ | | `qualified-ident?` | implemented+tested | ✓ |
| `qualified-keyword?` | implemented+tested | ✓ | | `qualified-keyword?` | implemented+tested | ✓ |
@ -505,15 +505,15 @@ UNVERIFIED field; that column will be added as entries land.
| `rand` | implemented+tested | ✓ | | `rand` | implemented+tested | ✓ |
| `rand-int` | implemented+tested | ✓ | | `rand-int` | implemented+tested | ✓ |
| `rand-nth` | implemented+tested | ✓ | | `rand-nth` | implemented+tested | ✓ |
| `random-sample` | implemented-untested | ✓ | | `random-sample` | implemented+tested | ✓ |
| `random-uuid` | implemented+tested | ✓ | | `random-uuid` | implemented+tested | ✓ |
| `range` | implemented+tested | ✓ | | `range` | implemented+tested | ✓ |
| `ratio?` | implemented+tested | ✓ | | `ratio?` | implemented+tested | ✓ |
| `rational?` | implemented+tested | ✓ | | `rational?` | implemented+tested | ✓ |
| `rationalize` | implemented+tested | ✓ | | `rationalize` | implemented+tested | ✓ |
| `re-find` | implemented+tested | ✓ | | `re-find` | implemented+tested | ✓ |
| `re-groups` | implemented-untested | ✓ | | `re-groups` | implemented+tested | ✓ |
| `re-matcher` | implemented-untested | ✓ | | `re-matcher` | implemented+tested | ✓ |
| `re-matches` | implemented+tested | ✓ | | `re-matches` | implemented+tested | ✓ |
| `re-pattern` | implemented+tested | ✓ | | `re-pattern` | implemented+tested | ✓ |
| `re-seq` | implemented+tested | ✓ | | `re-seq` | implemented+tested | ✓ |
@ -521,7 +521,7 @@ UNVERIFIED field; that column will be added as entries land.
| `read+string` | implemented+tested | ✓ | | `read+string` | implemented+tested | ✓ |
| `read-line` | implemented+tested | ✓ | | `read-line` | implemented+tested | ✓ |
| `read-string` | implemented+tested | ✓ | | `read-string` | implemented+tested | ✓ |
| `reader-conditional` | implemented-untested | ✓ | | `reader-conditional` | implemented+tested | ✓ |
| `reader-conditional?` | implemented+tested | ✓ | | `reader-conditional?` | implemented+tested | ✓ |
| `realized?` | implemented+tested | ✓ | | `realized?` | implemented+tested | ✓ |
| `record?` | implemented+tested | ✓ | | `record?` | implemented+tested | ✓ |
@ -537,7 +537,7 @@ UNVERIFIED field; that column will be added as entries land.
| `ref-min-history` | stm-refs | ✓ | | `ref-min-history` | stm-refs | ✓ |
| `ref-set` | stm-refs | ✓ | | `ref-set` | stm-refs | ✓ |
| `refer` | implemented+tested | ✓ | | `refer` | implemented+tested | ✓ |
| `refer-clojure` | implemented-untested | ✓ | | `refer-clojure` | implemented+tested | ✓ |
| `reify` | implemented+tested | ✓ | | `reify` | implemented+tested | ✓ |
| `release-pending-sends` | agents-taps | ✓ | | `release-pending-sends` | agents-taps | ✓ |
| `rem` | implemented+tested | ✓ | | `rem` | implemented+tested | ✓ |
@ -554,7 +554,7 @@ UNVERIFIED field; that column will be added as entries land.
| `require` | implemented+tested | ✓ | | `require` | implemented+tested | ✓ |
| `requiring-resolve` | jvm-specific | ✓ | | `requiring-resolve` | jvm-specific | ✓ |
| `reset!` | implemented+tested | ✓ | | `reset!` | implemented+tested | ✓ |
| `reset-meta!` | implemented-untested | ✓ | | `reset-meta!` | implemented+tested | ✓ |
| `reset-vals!` | implemented+tested | ✓ | | `reset-vals!` | implemented+tested | ✓ |
| `resolve` | implemented+tested | ✓ | | `resolve` | implemented+tested | ✓ |
| `rest` | implemented+tested | ✓ | | `rest` | implemented+tested | ✓ |
@ -572,10 +572,10 @@ UNVERIFIED field; that column will be added as entries land.
| `send-off` | agents-taps | ✓ | | `send-off` | agents-taps | ✓ |
| `send-via` | agents-taps | ✓ | | `send-via` | agents-taps | ✓ |
| `seq` | implemented+tested | ✓ | | `seq` | implemented+tested | ✓ |
| `seq-to-map-for-destructuring` | implemented-untested | ✓ | | `seq-to-map-for-destructuring` | implemented+tested | ✓ |
| `seq?` | implemented+tested | ✓ | | `seq?` | implemented+tested | ✓ |
| `seqable?` | implemented+tested | ✓ | | `seqable?` | implemented+tested | ✓ |
| `seque` | implemented-untested | ✓ | | `seque` | implemented+tested | ✓ |
| `sequence` | implemented+tested | ✓ | | `sequence` | implemented+tested | ✓ |
| `sequential?` | implemented+tested | ✓ | | `sequential?` | implemented+tested | ✓ |
| `set` | implemented+tested | ✓ | | `set` | implemented+tested | ✓ |
@ -586,9 +586,9 @@ UNVERIFIED field; that column will be added as entries land.
| `set-error-mode!` | agents-taps | ✓ | | `set-error-mode!` | agents-taps | ✓ |
| `set-validator!` | implemented+tested | ✓ | | `set-validator!` | implemented+tested | ✓ |
| `set?` | implemented+tested | ✓ | | `set?` | implemented+tested | ✓ |
| `short` | implemented-untested | ✓ | | `short` | implemented+tested | ✓ |
| `short-array` | implemented-untested | ✓ | | `short-array` | implemented+tested | ✓ |
| `shorts` | implemented-untested | ✓ | | `shorts` | implemented+tested | ✓ |
| `shuffle` | implemented+tested | ✓ | | `shuffle` | implemented+tested | ✓ |
| `shutdown-agents` | agents-taps | ✓ | | `shutdown-agents` | agents-taps | ✓ |
| `simple-ident?` | implemented+tested | ✓ | | `simple-ident?` | implemented+tested | ✓ |
@ -607,7 +607,7 @@ UNVERIFIED field; that column will be added as entries land.
| `sorted-set` | implemented+tested | ✓ | | `sorted-set` | implemented+tested | ✓ |
| `sorted-set-by` | implemented+tested | ✓ | | `sorted-set-by` | implemented+tested | ✓ |
| `sorted?` | implemented+tested | ✓ | | `sorted?` | implemented+tested | ✓ |
| `special-symbol?` | implemented-untested | ✓ | | `special-symbol?` | implemented+tested | ✓ |
| `spit` | implemented+tested | ✓ | | `spit` | implemented+tested | ✓ |
| `split-at` | implemented+tested | ✓ | | `split-at` | implemented+tested | ✓ |
| `split-with` | implemented+tested | ✓ | | `split-with` | implemented+tested | ✓ |
@ -641,7 +641,7 @@ UNVERIFIED field; that column will be added as entries land.
| `thread-bound?` | implemented+tested | ✓ | | `thread-bound?` | implemented+tested | ✓ |
| `throw` | special-form | ✓ | | `throw` | special-form | ✓ |
| `time` | implemented+tested | ✓ | | `time` | implemented+tested | ✓ |
| `to-array` | implemented-untested | ✓ | | `to-array` | implemented+tested | ✓ |
| `to-array-2d` | implemented+tested | ✓ | | `to-array-2d` | implemented+tested | ✓ |
| `trampoline` | implemented+tested | ✓ | | `trampoline` | implemented+tested | ✓ |
| `transduce` | implemented+tested | ✓ | | `transduce` | implemented+tested | ✓ |
@ -650,38 +650,38 @@ UNVERIFIED field; that column will be added as entries land.
| `true?` | implemented+tested | ✓ | | `true?` | implemented+tested | ✓ |
| `try` | special-form | ✓ | | `try` | special-form | ✓ |
| `type` | implemented+tested | ✓ | | `type` | implemented+tested | ✓ |
| `unchecked-add` | implemented-untested | ✓ | | `unchecked-add` | implemented+tested | ✓ |
| `unchecked-add-int` | implemented-untested | ✓ | | `unchecked-add-int` | implemented+tested | ✓ |
| `unchecked-byte` | implemented-untested | ✓ | | `unchecked-byte` | implemented+tested | ✓ |
| `unchecked-char` | implemented-untested | | | `unchecked-char` | implemented+tested | |
| `unchecked-dec` | implemented-untested | ✓ | | `unchecked-dec` | implemented+tested | ✓ |
| `unchecked-dec-int` | implemented-untested | ✓ | | `unchecked-dec-int` | implemented+tested | ✓ |
| `unchecked-divide-int` | implemented-untested | ✓ | | `unchecked-divide-int` | implemented+tested | ✓ |
| `unchecked-double` | implemented-untested | ✓ | | `unchecked-double` | implemented+tested | ✓ |
| `unchecked-float` | implemented-untested | ✓ | | `unchecked-float` | implemented+tested | ✓ |
| `unchecked-inc` | implemented-untested | ✓ | | `unchecked-inc` | implemented+tested | ✓ |
| `unchecked-inc-int` | implemented-untested | ✓ | | `unchecked-inc-int` | implemented+tested | ✓ |
| `unchecked-int` | implemented-untested | ✓ | | `unchecked-int` | implemented+tested | ✓ |
| `unchecked-long` | implemented-untested | ✓ | | `unchecked-long` | implemented+tested | ✓ |
| `unchecked-multiply` | implemented-untested | ✓ | | `unchecked-multiply` | implemented+tested | ✓ |
| `unchecked-multiply-int` | implemented-untested | | | `unchecked-multiply-int` | implemented+tested | |
| `unchecked-negate` | implemented-untested | ✓ | | `unchecked-negate` | implemented+tested | ✓ |
| `unchecked-negate-int` | implemented-untested | ✓ | | `unchecked-negate-int` | implemented+tested | ✓ |
| `unchecked-remainder-int` | implemented-untested | | | `unchecked-remainder-int` | implemented+tested | |
| `unchecked-short` | implemented-untested | ✓ | | `unchecked-short` | implemented+tested | ✓ |
| `unchecked-subtract` | implemented-untested | ✓ | | `unchecked-subtract` | implemented+tested | ✓ |
| `unchecked-subtract-int` | implemented-untested | ✓ | | `unchecked-subtract-int` | implemented+tested | ✓ |
| `underive` | implemented+tested | ✓ | | `underive` | implemented+tested | ✓ |
| `unquote` | jvm-specific | ✓ | | `unquote` | jvm-specific | ✓ |
| `unquote-splicing` | jvm-specific | ✓ | | `unquote-splicing` | jvm-specific | ✓ |
| `unreduced` | implemented+tested | ✓ | | `unreduced` | implemented+tested | ✓ |
| `unsigned-bit-shift-right` | implemented-untested | ✓ | | `unsigned-bit-shift-right` | implemented+tested | ✓ |
| `update` | implemented+tested | ✓ | | `update` | implemented+tested | ✓ |
| `update-in` | implemented+tested | ✓ | | `update-in` | implemented+tested | ✓ |
| `update-keys` | implemented+tested | ✓ | | `update-keys` | implemented+tested | ✓ |
| `update-proxy` | implemented-untested | ✓ | | `update-proxy` | implemented+tested | ✓ |
| `update-vals` | implemented+tested | ✓ | | `update-vals` | implemented+tested | ✓ |
| `uri?` | implemented-untested | ✓ | | `uri?` | implemented+tested | ✓ |
| `use` | implemented+tested | ✓ | | `use` | implemented+tested | ✓ |
| `uuid?` | implemented+tested | ✓ | | `uuid?` | implemented+tested | ✓ |
| `val` | implemented+tested | ✓ | | `val` | implemented+tested | ✓ |
@ -716,6 +716,6 @@ UNVERIFIED field; that column will be added as entries land.
| `with-precision` | implemented+tested | ✓ | | `with-precision` | implemented+tested | ✓ |
| `with-redefs` | implemented+tested | ✓ | | `with-redefs` | implemented+tested | ✓ |
| `with-redefs-fn` | implemented+tested | ✓ | | `with-redefs-fn` | implemented+tested | ✓ |
| `xml-seq` | implemented-untested | ✓ | | `xml-seq` | implemented+tested | ✓ |
| `zero?` | implemented+tested | ✓ | | `zero?` | implemented+tested | ✓ |
| `zipmap` | implemented+tested | ✓ | | `zipmap` | implemented+tested | ✓ |

View file

@ -821,3 +821,20 @@
;; The raw Inst protocol method; jolt insts have one representation, so it is ;; The raw Inst protocol method; jolt insts have one representation, so it is
;; inst-ms itself. ;; inst-ms itself.
(defn inst-ms* [i] (inst-ms i)) (defn inst-ms* [i] (inst-ms i))
;; Canonical comp — here rather than the seed so each stage is invoked with
;; jolt call semantics: (comp seq :content) works because the keyword stage
;; goes through IFn dispatch (raw Janet keyword application does not).
(defn comp
([] identity)
([f] f)
([f g]
;; fixed arities first (Clojure's own shape): the 1-arg path — every
;; map/filter stage — is two direct calls, no rest-seq, no apply.
(fn
([] (f (g)))
([x] (f (g x)))
([x y] (f (g x y)))
([x y z] (f (g x y z)))
([x y z & args] (f (apply g x y z args)))))
([f g & fs] (reduce comp (comp f g) fs)))

View file

@ -295,6 +295,43 @@
(protocol-dispatch ~(name pname) ~(name (first sig)) this# rest#)))) (protocol-dispatch ~(name pname) ~(name (first sig)) this# rest#))))
sigs)))) sigs))))
;; Member threading: (.. x f g) => (. (. x f) g); a parenthesized member
;; carries args. Canonical Clojure shape, single-arity defmacro.
(defmacro .. [x form & more]
(let [step (if (seq? form)
`(. ~x ~(first form) ~@(rest form))
`(. ~x ~form))]
(if (seq more)
`(.. ~step ~@more)
step)))
;; True when atype's methods were registered for this protocol (via extend /
;; extend-type). Tags are canonical host names or ns-qualified record names,
;; so a bare record name also matches its "ns.Name" tag.
(defn extends? [protocol atype]
(let [want (name atype)
dotted (str "." want)
dlen (count dotted)]
(boolean (some (fn [t]
(let [tn (name t)]
(or (= tn want)
(and (> (count tn) dlen)
(= (subs tn (- (count tn) dlen)) dotted)))))
(extenders protocol)))))
;; extend, the FUNCTION (extend-type's runtime sibling): protocol + method-map
;; pairs, methods registered under the type's (canonicalized) name — so
;; (extend 'String P {:m (fn [x] ...)}) dispatches exactly like extend-type.
(defn extend [atype & proto+mmaps]
(loop [s (seq proto+mmaps)]
(when s
(let [proto (first s)
mmap (second s)
pname (name (get proto :name))]
(doseq [[k f] mmap]
(register-method (name atype) pname (name k) f)))
(recur (nnext s)))))
(defmacro extend-type [tsym psym & impls] (defmacro extend-type [tsym psym & impls]
;; register-method is a fn (clojure.core); pass type/protocol/method NAMES as ;; register-method is a fn (clojure.core); pass type/protocol/method NAMES as
;; strings (not the symbols) so the call compiles as a plain invoke. ;; strings (not the symbols) so the call compiles as a plain invoke.
@ -308,7 +345,7 @@
(group-by-head type-impls)))) (group-by-head type-impls))))
;; extend (the fn form) is not supported — stub to nil, as before. ;; extend (the fn form) is not supported — stub to nil, as before.
(defmacro extend [& args] nil) ;; extend is a real FUNCTION now — defined above extend-type.
;; JVM proxies are unsupported. ;; JVM proxies are unsupported.
(defmacro proxy [& args] nil) (defmacro proxy [& args] nil)
;; definterface is JVM-only; bind the name to an empty marker. ;; definterface is JVM-only; bind the name to an empty marker.

View file

@ -1402,7 +1402,12 @@
# every-pred now lives in the Clojure collection tier (core/20-coll.clj). # every-pred now lives in the Clojure collection tier (core/20-coll.clj).
(def core-comp # Public comp lives in the overlay now (20-coll) — its stages can be any jolt
# IFn (keyword/map/set/vector), which raw Janet calls mishandle ((comp seq
# :content) returned nil: janet keyword-apply is not jolt invoke). This
# private composer remains ONLY for the transducer machinery below, where the
# stages are always real fns.
(def- td-comp
(fn [& fs] (fn [& fs]
(case (length fs) (case (length fs)
0 identity 0 identity
@ -1852,7 +1857,10 @@
# below stay native (they build the mutable backing). # below stay native (they build the mutable backing).
(defn core-aclone [arr] (defn core-aclone [arr]
(if (buffer? arr) (buffer/slice arr) (array/slice arr))) (cond
(buffer? arr) (buffer/slice arr)
(pvec? arr) (array ;(pv->array arr))
(array/slice arr)))
# Numeric / object arrays: (T-array size) | (T-array size init) | (T-array seq) # Numeric / object arrays: (T-array size) | (T-array size init) | (T-array seq)
(defn- make-num-array [a rest init] (defn- make-num-array [a rest init]
@ -2284,7 +2292,7 @@
(def core-satisfies? (fn [proto-sym obj] false)) (def core-satisfies? (fn [proto-sym obj] false))
(def core-extends? (fn [& args] false)) # extends? is a real overlay fn now (30-macros, over extenders).
(def core-implements? (fn [& args] false)) (def core-implements? (fn [& args] false))
(def core-type->str (fn [& args] "")) (def core-type->str (fn [& args] ""))
@ -2419,7 +2427,7 @@
(let [n (length args) (let [n (length args)
coll (in args (- n 1)) coll (in args (- n 1))
xforms (array/slice args 0 (- n 1)) xforms (array/slice args 0 (- n 1))
xform (if (= 0 (length xforms)) (fn [rf] rf) (apply core-comp xforms))] xform (if (= 0 (length xforms)) (fn [rf] rf) (apply td-comp xforms))]
(core-into (make-vec @[]) xform coll))) (core-into (make-vec @[]) xform coll)))
(defn core->Eduction [xform coll] (core-into (make-vec @[]) xform coll)) (defn core->Eduction [xform coll] (core-into (make-vec @[]) xform coll))
(defn core-proxy-super [& args] (error "proxy-super: JVM proxies are not supported in Jolt")) (defn core-proxy-super [& args] (error "proxy-super: JVM proxies are not supported in Jolt"))
@ -2800,7 +2808,6 @@
"range" core-range "range" core-range
"identity" core-identity "identity" core-identity
"constantly" core-constantly "constantly" core-constantly
"comp" core-comp
"vector" core-vector "vector" core-vector
"hash-map" core-hash-map "hash-map" core-hash-map
"array-map" core-array-map "array-map" core-array-map
@ -2948,7 +2955,6 @@
"Object" core-Object "Object" core-Object
"make-protocol" core-make-protocol "make-protocol" core-make-protocol
"satisfies?" core-satisfies? "satisfies?" core-satisfies?
"extends?" core-extends?
"implements?" core-implements? "implements?" core-implements?
"type->str" core-type->str "type->str" core-type->str
"volatile!" core-volatile! "volatile!" core-volatile!

View file

@ -417,12 +417,23 @@
"PI" math/pi "E" math/e "PI" math/pi "E" math/e
"random" (fn [&] (math/random))}) "random" (fn [&] (math/random))})
# Thread statics (the JVM shapes portable code actually uses). sleep parks the
# CURRENT thread's event loop — inside a future body that's the worker OS
# thread (ev/spawn-thread gives each worker its own loop), so a sleeping
# future doesn't block the parent.
(def- thread-statics
{"sleep" (fn [ms] (ev/sleep (/ ms 1000)) nil)
"yield" (fn [] (ev/sleep 0) nil)})
(defn- resolve-sym (defn- resolve-sym
[ctx bindings sym-s] [ctx bindings sym-s]
(let [name (sym-s :name) ns (sym-s :ns)] (let [name (sym-s :name) ns (sym-s :ns)]
(if (= ns "Math") (if (= ns "Math")
(let [v (get math-statics name)] (let [v (get math-statics name)]
(if (nil? v) (error (string "Unsupported Math member: Math/" name)) v)) (if (nil? v) (error (string "Unsupported Math member: Math/" name)) v))
(if (= ns "Thread")
(let [v (get thread-statics name)]
(if (nil? v) (error (string "Unsupported Thread member: Thread/" name)) v))
(if (not (nil? ns)) (if (not (nil? ns))
(let [current-ns (ctx-find-ns ctx (ctx-current-ns ctx)) (let [current-ns (ctx-find-ns ctx (ctx-current-ns ctx))
aliased-ns (ns-import-lookup current-ns ns) aliased-ns (ns-import-lookup current-ns ns)
@ -472,8 +483,7 @@
# No implicit Janet fallback (Stage 3): an unresolved # No implicit Janet fallback (Stage 3): an unresolved
# Clojure symbol is an error. Host access is the explicit # Clojure symbol is an error. Host access is the explicit
# janet/ prefix above. # janet/ prefix above.
(error (string "Unable to resolve symbol: " name)))))))))))))) (error (string "Unable to resolve symbol: " name)))))))))))))))
(defn- parse-arg-names (defn- parse-arg-names
"Parse a parameter vector, handling & rest args. "Parse a parameter vector, handling & rest args.
Returns {:fixed [names...] :rest name-or-nil :all [names...]}" Returns {:fixed [names...] :rest name-or-nil :all [names...]}"
@ -1013,9 +1023,11 @@
(ns-intern core "remove-ns" (fn [x] (remove-ns ctx (ns-name-of x)))) (ns-intern core "remove-ns" (fn [x] (remove-ns ctx (ns-name-of x))))
(ns-intern core "all-ns" (fn [] (all-ns ctx))) (ns-intern core "all-ns" (fn [] (all-ns ctx)))
(ns-intern core "the-ns" (fn [&opt x] (ns-or-current x))) (ns-intern core "the-ns" (fn [&opt x] (ns-or-current x)))
(ns-intern core "ns-interns" (fn [&opt x] ((ns-or-current x) :mappings))) # interns/imports return a jolt MAP (struct), not the live host table — so
# count/seq/keys work on them, and callers can't mutate the ns through them.
(ns-intern core "ns-interns" (fn [&opt x] (table/to-struct ((ns-or-current x) :mappings))))
(ns-intern core "ns-aliases" (fn [&opt x] ((ns-or-current x) :aliases))) (ns-intern core "ns-aliases" (fn [&opt x] ((ns-or-current x) :aliases)))
(ns-intern core "ns-imports" (fn [&opt x] ((ns-or-current x) :imports))) (ns-intern core "ns-imports" (fn [&opt x] (table/to-struct ((ns-or-current x) :imports))))
# (ns-resolve ns sym) -> the var or nil. Unqualified syms look in ns's own # (ns-resolve ns sym) -> the var or nil. Unqualified syms look in ns's own
# mappings; ns-qualified syms resolve through ns's aliases. (types/ns-resolve # mappings; ns-qualified syms resolve through ns's aliases. (types/ns-resolve
# keys ns-find with the symbol struct instead of its name string, so it never # keys ns-find with the symbol struct instead of its name string, so it never
@ -1678,8 +1690,10 @@
(let [field-name (string/slice sym-name 2) (let [field-name (string/slice sym-name 2)
target (eval-form ctx bindings (in form 1))] target (eval-form ctx bindings (in form 1))]
(get target (keyword field-name))) (get target (keyword field-name)))
# Handle ClassName. constructor syntax # Handle ClassName. constructor syntax (".." is the member-threading
(if (and (> (length sym-name) 0) (= (sym-name (- (length sym-name) 1)) 46)) # macro, not a constructor named ".")
(if (and (> (length sym-name) 1) (not= sym-name "..")
(= (sym-name (- (length sym-name) 1)) 46))
(let [type-name (string/slice sym-name 0 (- (length sym-name) 1)) (let [type-name (string/slice sym-name 0 (- (length sym-name) 1))
type-sym {:jolt/type :symbol :ns (first-form :ns) :name type-name} type-sym {:jolt/type :symbol :ns (first-form :ns) :name type-name}
ctor (eval-form ctx bindings type-sym) ctor (eval-form ctx bindings type-sym)

View file

@ -16,7 +16,13 @@
["future returns a map" "{:a 1}" "(deref (future {:a 1}))"] ["future returns a map" "{:a 1}" "(deref (future {:a 1}))"]
["deref is cached/idempotent" "[2 2]" "(let [f (future (+ 1 1))] [(deref f) (deref f)])"] ["deref is cached/idempotent" "[2 2]" "(let [f (future (+ 1 1))] [(deref f) (deref f)])"]
["timed deref of ready future" "42" "(let [f (future 42)] (deref f) (deref f 1000 :nope))"] ["timed deref of ready future" "42" "(let [f (future 42)] (deref f) (deref f 1000 :nope))"]
["body error re-raised on deref" :throws "(deref (future (throw \"boom\")))"]) ["body error re-raised on deref" :throws "(deref (future (throw \"boom\")))"]
# Thread/sleep parks the WORKER's own event loop (each future thread has one),
# so a sleeping future doesn't block the parent — and timed deref can fire.
["timed deref times out" ":timed-out" "(deref (future (do (Thread/sleep 300) :late)) 10 :timed-out)"]
["Thread/sleep in body" ":slept" "(deref (future (do (Thread/sleep 5) :slept)))"]
["timed-out future still completes" ":late"
"(let [f (future (do (Thread/sleep 30) :late))] (deref f 5 :early) (deref f))"])
(defspec "clojure.core / futures — predicates" (defspec "clojure.core / futures — predicates"
["future? true" "true" "(future? (future 1))"] ["future? true" "true" "(future? (future 1))"]

View file

@ -0,0 +1,177 @@
# Specification: spec rows for every previously-untested implemented var
# (jolt-brh follow-up — promotes the dashboard's implemented-untested category).
# Rows assert jolt's ACTUAL documented behavior, including the stub families:
# arrays are vectors/host buffers, proxies/JVM reflection are resolve-only,
# unchecked-* are plain double ops, chunks are eager equivalents.
(use ../support/harness)
(defspec "untested / primed + division + bit ops"
["+'" "3" "(+' 1 2)"]
["-'" "3" "(-' 5 2)"]
["*'" "12" "(*' 3 4)"]
["inc'" "2.5" "(inc' 1.5)"]
["dec'" "1.5" "(dec' 2.5)"]
["/" "2" "(/ 6 3)"]
["/ ratio-as-double" "0.5" "(/ 1 2)"]
["bit-not" "-6" "(bit-not 5)"]
["bit-and-not" "4" "(bit-and-not 12 10)"]
["bit-flip" "3" "(bit-flip 2 0)"]
["unsigned-bit-shift-right" "2" "(unsigned-bit-shift-right 8 2)"])
(defspec "untested / hash family"
["hash stable" "true" "(= (hash :a) (hash :a))"]
["hash int" "true" "(int? (hash [1 2]))"]
["hash-combine" "true" "(int? (hash-combine 1 2))"]
["hash-ordered-coll" "true" "(int? (hash-ordered-coll [1 2]))"]
["hash-unordered-coll" "true" "(int? (hash-unordered-coll #{1}))"])
(defspec "untested / array stubs (vectors + host buffers)"
["make-array" "(quote (nil nil nil))" "(make-array 3)"]
["into-array" "(quote (1 2))" "(into-array [1 2])"]
["to-array" "(quote (1 2))" "(to-array [1 2])"]
["aclone vec" "(quote (1 2))" "(aclone [1 2])"]
["aclone independent" "(quote (9 2))" "(let [a (aclone (to-array [1 2]))] (aset a 0 9) (seq a))"]
["aset/aget" "9" "(let [a (to-array [1 2 3])] (aset a 0 9) (aget a 0))"]
["aset-int" "7" "(let [a (to-array [1 2])] (aset-int a 0 7) (aget a 0))"]
["aset-boolean" "true" "(let [a (to-array [1])] (aset-boolean a 0 true) (aget a 0))"]
["aset-byte" "9" "(let [a (to-array [0])] (aset-byte a 0 9) (aget a 0))"]
["aset-char" "\\a" "(let [a (to-array [0])] (aset-char a 0 \\a) (aget a 0))"]
["aset-double" "1.5" "(let [a (to-array [0])] (aset-double a 0 1.5) (aget a 0))"]
["aset-float" "2.5" "(let [a (to-array [0])] (aset-float a 0 2.5) (aget a 0))"]
["aset-long" "3" "(let [a (to-array [0])] (aset-long a 0 3) (aget a 0))"]
["aset-short" "4" "(let [a (to-array [0])] (aset-short a 0 4) (aget a 0))"]
["boolean-array" "(quote (false false))" "(boolean-array 2)"]
["int-array" "(quote (1 2))" "(int-array [1 2])"]
["long-array" "(quote (0 0))" "(long-array 2)"]
["double-array" "(quote (0 0))" "(double-array 2)"]
["float-array" "(quote (0 0))" "(float-array 2)"]
["short-array" "(quote (0 0))" "(short-array 2)"]
["char-array count" "2" "(count (char-array 2))"]
["byte-array bytes?" "true" "(bytes? (byte-array 2))"]
["bytes? not vec" "false" "(bytes? [1])"])
(defspec "untested / typed coercion views"
["booleans" "(quote (true))" "(booleans [true])"]
["doubles" "(quote (1))" "(doubles [1.0])"]
["floats" "(quote (1))" "(floats [1.0])"]
["ints" "(quote (1))" "(ints [1])"]
["longs" "(quote (1))" "(longs [1])"]
["shorts" "(quote (1))" "(shorts [1])"]
["chars first" "\\a" "(first (chars [\\a]))"]
["bytes view" "true" "(bytes? (bytes [65]))"]
["byte" "65" "(byte 65)"]
["short" "1" "(short 1)"]
["long truncates" "1" "(long 1.7)"]
["double" "3" "(double 3)"]
["float" "3" "(float 3)"])
(defspec "untested / unchecked-* are plain ops"
["unchecked-add" "3" "(unchecked-add 1 2)"]
["unchecked-add-int" "3" "(unchecked-add-int 1 2)"]
["unchecked-subtract" "3" "(unchecked-subtract 5 2)"]
["unchecked-subtract-int" "3" "(unchecked-subtract-int 5 2)"]
["unchecked-multiply" "6" "(unchecked-multiply 2 3)"]
["unchecked-multiply-int" "6" "(unchecked-multiply-int 2 3)"]
["unchecked-inc" "2" "(unchecked-inc 1)"]
["unchecked-inc-int" "2" "(unchecked-inc-int 1)"]
["unchecked-dec" "2" "(unchecked-dec 3)"]
["unchecked-dec-int" "2" "(unchecked-dec-int 3)"]
["unchecked-negate" "-4" "(unchecked-negate 4)"]
["unchecked-negate-int" "-4" "(unchecked-negate-int 4)"]
["unchecked-divide-int" "3" "(unchecked-divide-int 7 2)"]
["unchecked-remainder-int" "1" "(unchecked-remainder-int 7 2)"]
["unchecked-int" "3" "(unchecked-int 3.7)"]
["unchecked-long" "3" "(unchecked-long 3.7)"]
["unchecked-double" "3" "(unchecked-double 3)"]
["unchecked-float" "3" "(unchecked-float 3)"]
["unchecked-byte" "65" "(unchecked-byte 65)"]
["unchecked-char" "97" "(unchecked-char 97)"]
["unchecked-short" "5" "(unchecked-short 5)"])
(defspec "untested / chunk family (eager equivalents) + cat"
["chunk round-trip" "1"
"(let [cb (chunk-buffer 4)] (chunk-append cb 1) (chunk-first (chunk-cons (chunk cb) nil)))"]
["cat transducer" "[1 2 3]" "(into [] cat [[1] [2 3]])"]
["ensure-reduced wraps" "true" "(reduced? (ensure-reduced 5))"]
["ensure-reduced keeps reduced" "true" "(reduced? (ensure-reduced (reduced 5)))"]
["halt-when" "4" "(transduce (halt-when even?) conj [] [1 3 4 5])"]
["chunk-next exhausted" "nil"
"(let [cb (chunk-buffer 2)] (chunk-append cb 1) (chunk-next (chunk-cons (chunk cb) nil)))"]
["chunk-rest seqable" "()"
"(let [cb (chunk-buffer 2)] (chunk-append cb 1) (vec (chunk-rest (chunk-cons (chunk cb) nil))))"])
(defspec "untested / JVM-shape stubs (documented jolt behavior)"
["class number" "\"java.lang.Number\"" "(class 1)"]
["class string" "\"java.lang.String\"" "(class \"s\")"]
["class keyword" "\"clojure.lang.Keyword\"" "(class :k)"]
["class nil" "nil" "(class nil)"]
["bean is the map" "{:a 1}" "(bean {:a 1})"]
["biginteger" "\"5\"" "(str (biginteger 5))"]
["proxy resolves nil" "nil" "(proxy [Object] [] (toString [] \"x\"))"]
["construct-proxy throws" :throws "(construct-proxy nil)"]
["get-proxy-class throws" :throws "(get-proxy-class)"]
["init-proxy" "nil" "(init-proxy nil {})"]
["update-proxy" "nil" "(update-proxy nil {})"]
["proxy-mappings" "{}" "(proxy-mappings nil)"]
["proxy-call-with-super calls" "1" "(proxy-call-with-super (fn [] 1) nil \"m\")"]
["memfn throws" :throws "((memfn count) \"abc\")"]
["proxy-super throws" :throws "(proxy-super count [1])"]
["re-groups throws" :throws "(re-groups (re-matcher #\"a\" \"b\"))"]
["re-matcher builds" "false" "(nil? (re-matcher #\"a\" \"abc\"))"]
["print-dup" "nil" "(print-dup 1 nil)"]
["print-method" "nil" "(print-method 1 nil)"]
["uri? string" "false" "(uri? \"http://x\")"]
["uri? nil" "false" "(uri? nil)"]
["definterface defines" "true" "(var? (definterface IFoo (foo [x])))"]
["enumeration-seq" "(quote (1 2))" "(enumeration-seq [1 2])"]
["iterator-seq" "(quote (1 2))" "(iterator-seq [1 2])"]
["seque passthrough" "(quote (1 2))" "(seque [1 2])"]
["delay? true" "true" "(delay? (delay 1))"]
["delay? false" "false" "(delay? 1)"]
["future-call" "42" "(deref (future-call (fn [] 42)))"]
[". member resolves nil" "nil" "(. \"abc\" count)"]
[".. threads members" "nil" "(.. \"abc\" count)"])
(defspec "untested / protocols: extend + extends?"
["extend registers" ":str"
"(do (defprotocol Pe (pe [x])) (extend (quote String) Pe {:pe (fn [x] :str)}) (pe \"s\"))"]
["extend two methods" "[1 2]"
"(do (defprotocol P3 (pa [x]) (pb [x])) (extend (quote Long) P3 {:pa (fn [x] 1) :pb (fn [x] 2)}) [(pa 0) (pb 0)])"]
["extends? after extend" "true"
"(do (defprotocol P4 (pc [x])) (extend (quote Long) P4 {:pc (fn [x] 1)}) (extends? P4 (quote Long)))"]
["extends? without" "false" "(do (defprotocol P5 (pd [x])) (extends? P5 (quote Long)))"])
(defspec "untested / ns + REPL machinery"
["all-ns non-empty" "true" "(pos? (count (all-ns)))"]
["ns-interns sees def" "true" "(do (def zz 1) (pos? (count (ns-interns (quote user)))))"]
["ns-interns countable" "true" "(map? (ns-interns (quote user)))"]
["ns-imports empty user" "0" "(count (ns-imports (quote user)))"]
["reset-meta!" "{:doc \"d\"}" "(do (def vv 1) (reset-meta! (var vv) {:doc \"d\"}))"]
["prefers empty" "{}" "(do (defmulti mm identity) (prefers mm))"]
["refer-clojure" "nil" "(refer-clojure)"]
["special-symbol? if" "true" "(special-symbol? (quote if))"]
["special-symbol? fn name" "false" "(special-symbol? (quote foo))"]
["destructure expands" "true" "(pos? (count (destructure (quote [[a b] x]))))"]
["seq-to-map-for-destructuring" "{:a 1}" "(seq-to-map-for-destructuring (quote (:a 1)) nil)"]
["*clojure-version* major" "1" "(:major *clojure-version*)"]
["*ns* user" "\"user\"" "(str *ns*)"]
["*1 nil outside repl" "nil" "*1"]
["*2 nil" "nil" "*2"]
["*3 nil" "nil" "*3"]
["*e nil" "nil" "*e"]
["*unchecked-math*" "false" "*unchecked-math*"]
["*in* bound" "true" "(map? *in*)"])
(defspec "untested / misc seqs + binding machinery"
["nfirst" "(quote (2))" "(nfirst [[1 2] [3]])"]
["xml-seq root" "1" "(count (xml-seq {:tag :a :content []}))"]
["xml-seq walks" "2" "(count (xml-seq {:tag :a :content [{:tag :b :content []}]}))"]
# regression: comp with a keyword stage must use jolt IFn dispatch
["comp keyword stage" "(quote (1 2))" "((comp seq :content) {:content [1 2]})"]
["comp three stages" "4" "((comp inc inc :n) {:n 2})"]
["random-sample all" "(quote (1 2))" "(random-sample 1.0 [1 2])"]
["random-sample none" "()" "(random-sample 0.0 [1 2])"]
["reader-conditional builds" "true" "(reader-conditional? (reader-conditional (quote (:clj 1)) false))"]
["->Eduction" "[2 3]" "(vec (->Eduction (map inc) [1 2]))"]
["bound-fn calls" "42" "((bound-fn [] 42))"]
["push/pop-thread-bindings" ":ok" "(do (push-thread-bindings {}) (pop-thread-bindings) :ok)"])

View file

@ -42,9 +42,15 @@ jolt = interned | resolvable
# --- 3. what the tests exercise -------------------------------------------- # --- 3. what the tests exercise --------------------------------------------
tested = set() tested = set()
sym = re.compile(r'\(([a-zA-Z*+!?<>=_-][a-zA-Z0-9*+!?<>=_./-]*)') test_text = ''
# A var counts as tested when its name appears as a WHOLE TOKEN anywhere in
# the test sources (assertions live inside strings, so call-position-only
# matching missed *1, +', ., .., /, and bare transducer refs like cat).
SYMCHARS = r"\w*+!?<>=_.'/-"
def token_re(name):
return re.compile('(?<![' + re.escape(SYMCHARS) + '])' + re.escape(name) + '(?![' + re.escape(SYMCHARS) + '])')
for f in glob.glob('test/spec/*.janet') + ['test/integration/conformance-test.janet']: for f in glob.glob('test/spec/*.janet') + ['test/integration/conformance-test.janet']:
tested |= set(sym.findall(open(f).read())) test_text += open(f).read()
# --- classification --------------------------------------------------------- # --- classification ---------------------------------------------------------
SPECIAL = {'catch','finally','do','def','defmacro','fn','if','let','loop','quote', SPECIAL = {'catch','finally','do','def','defmacro','fn','if','let','loop','quote',
@ -72,7 +78,7 @@ JVM = {'class','class?','cast','bases','supers','compile','add-classpath',
def classify(n): def classify(n):
if n in jolt: if n in jolt:
return 'implemented+tested' if n in tested else 'implemented-untested' return 'implemented+tested' if token_re(n).search(test_text) else 'implemented-untested'
if re.match(r'^\*.*\*$', n): return 'dynamic-var' if re.match(r'^\*.*\*$', n): return 'dynamic-var'
if n in SPECIAL: return 'special-form' if n in SPECIAL: return 'special-form'
if n in AGENTS: return 'agents-taps' if n in AGENTS: return 'agents-taps'