Close portable clojure.core gaps: re-groups, letfn, REPL + dynamic vars
Spec coverage dashboard had 6 missing-portable and 24 dynamic-var entries. The portable ones are now implemented (missing-portable -> 0, dynamic-var -> 14): - Stateful matcher: re-matcher now returns a real mutable Matcher; re-find over it steps through matches and re-groups returns the last match's groups (was an inert tagged map). Closes re-groups. - letfn is interned as a clojure.core var so (resolve 'letfn) matches the JVM. It stays a special form (the value is never invoked, not marked a macro). - *1 *2 *3 *e interned (nil outside a REPL). - Portable dynamic vars whose default already matches jolt's behaviour: *read-eval* *print-dup* *print-namespace-maps* *flush-on-newline* *compile-files* *math-context* *command-line-args* *file*. The remaining 14 dynamic-var entries are host-internal (compile-path, compiler-options, fn-loader, reader-resolver, repl, source-path, ...) or deferred pending printer/reader support (*print-length* *print-level* *default-data-reader-fn*). Corpus rows added for each closed gap; coverage.md regenerated.
This commit is contained in:
parent
8a877662dc
commit
5f72ec9bcb
5 changed files with 117 additions and 41 deletions
|
|
@ -1,21 +1,21 @@
|
||||||
# Appendix A — Coverage Dashboard (generated)
|
# Appendix A — Coverage Dashboard (generated)
|
||||||
|
|
||||||
Generated 2026-06-22 by `tools/spec_coverage.py` — do not edit by hand.
|
Generated 2026-06-26 by `tools/spec_coverage.py` — do not edit by hand.
|
||||||
|
|
||||||
Surface: **694** clojure.core vars (ClojureDocs export; 648 with
|
Surface: **694** clojure.core vars (ClojureDocs export; 648 with
|
||||||
community examples). jolt interns 574 of them.
|
community examples). jolt interns 591 of them.
|
||||||
|
|
||||||
| Status | Count | Meaning |
|
| Status | Count | Meaning |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| implemented+tested | 568 | in jolt and exercised by spec/conformance |
|
| implemented+tested | 587 | in jolt and exercised by spec/conformance |
|
||||||
| implemented-untested | 6 | in jolt, no direct test — spec entries will add them |
|
| implemented-untested | 4 | in jolt, no direct test — spec entries will add them |
|
||||||
| resolvable-not-interned | 0 | works in code but invisible to ns introspection (conformance finding) |
|
| resolvable-not-interned | 0 | works in code but invisible to ns introspection (conformance finding) |
|
||||||
| missing-portable | 6 | portable semantics, jolt lacks it — implementation gap |
|
| missing-portable | 0 | portable semantics, jolt lacks it — implementation gap |
|
||||||
| special-form | 16 | specified in §3, not a library var |
|
| special-form | 16 | specified in §3, not a library var |
|
||||||
| dynamic-var | 24 | classification needed: portable default vs host-dependent |
|
| dynamic-var | 14 | classification needed: portable default vs host-dependent |
|
||||||
| agents-taps | 16 | out of scope pending concurrency design note |
|
| agents-taps | 16 | out of scope pending concurrency design note |
|
||||||
| stm-refs | 11 | out of scope pending concurrency design note |
|
| stm-refs | 11 | out of scope pending concurrency design note |
|
||||||
| jvm-specific | 47 | catalogued, not specified |
|
| jvm-specific | 46 | catalogued, not specified |
|
||||||
|
|
||||||
Classifications are initial and mechanical — reclassifying is an ordinary
|
Classifications are initial and mechanical — reclassifying is an ordinary
|
||||||
spec change. A var is *Verified* only when its §9 entry exists and carries no
|
spec change. A var is *Verified* only when its §9 entry exists and carries no
|
||||||
|
|
@ -27,35 +27,35 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `*` | implemented+tested | ✓ |
|
| `*` | implemented+tested | ✓ |
|
||||||
| `*'` | implemented+tested | ✓ |
|
| `*'` | implemented+tested | ✓ |
|
||||||
| `*1` | missing-portable | ✓ |
|
| `*1` | implemented+tested | ✓ |
|
||||||
| `*2` | missing-portable | ✓ |
|
| `*2` | implemented+tested | ✓ |
|
||||||
| `*3` | missing-portable | ✓ |
|
| `*3` | implemented+tested | ✓ |
|
||||||
| `*agent*` | dynamic-var | ✓ |
|
| `*agent*` | dynamic-var | ✓ |
|
||||||
| `*allow-unresolved-vars*` | dynamic-var | ✓ |
|
| `*allow-unresolved-vars*` | dynamic-var | ✓ |
|
||||||
| `*assert*` | implemented+tested | ✓ |
|
| `*assert*` | implemented+tested | ✓ |
|
||||||
| `*clojure-version*` | implemented+tested | ✓ |
|
| `*clojure-version*` | implemented+tested | ✓ |
|
||||||
| `*command-line-args*` | dynamic-var | ✓ |
|
| `*command-line-args*` | implemented-untested | ✓ |
|
||||||
| `*compile-files*` | dynamic-var | ✓ |
|
| `*compile-files*` | implemented+tested | ✓ |
|
||||||
| `*compile-path*` | dynamic-var | ✓ |
|
| `*compile-path*` | dynamic-var | ✓ |
|
||||||
| `*compiler-options*` | dynamic-var | ✓ |
|
| `*compiler-options*` | dynamic-var | ✓ |
|
||||||
| `*data-readers*` | dynamic-var | ✓ |
|
| `*data-readers*` | implemented+tested | ✓ |
|
||||||
| `*default-data-reader-fn*` | dynamic-var | ✓ |
|
| `*default-data-reader-fn*` | dynamic-var | ✓ |
|
||||||
| `*e` | missing-portable | ✓ |
|
| `*e` | implemented+tested | ✓ |
|
||||||
| `*err*` | implemented-untested | ✓ |
|
| `*err*` | implemented+tested | ✓ |
|
||||||
| `*file*` | dynamic-var | ✓ |
|
| `*file*` | implemented-untested | ✓ |
|
||||||
| `*flush-on-newline*` | dynamic-var | |
|
| `*flush-on-newline*` | implemented+tested | |
|
||||||
| `*fn-loader*` | dynamic-var | |
|
| `*fn-loader*` | dynamic-var | |
|
||||||
| `*in*` | implemented+tested | |
|
| `*in*` | implemented+tested | |
|
||||||
| `*math-context*` | dynamic-var | |
|
| `*math-context*` | implemented+tested | |
|
||||||
| `*ns*` | implemented+tested | ✓ |
|
| `*ns*` | implemented+tested | ✓ |
|
||||||
| `*out*` | implemented-untested | ✓ |
|
| `*out*` | implemented+tested | ✓ |
|
||||||
| `*print-dup*` | dynamic-var | ✓ |
|
| `*print-dup*` | implemented+tested | ✓ |
|
||||||
| `*print-length*` | dynamic-var | ✓ |
|
| `*print-length*` | dynamic-var | ✓ |
|
||||||
| `*print-level*` | dynamic-var | ✓ |
|
| `*print-level*` | dynamic-var | ✓ |
|
||||||
| `*print-meta*` | dynamic-var | ✓ |
|
| `*print-meta*` | implemented+tested | ✓ |
|
||||||
| `*print-namespace-maps*` | dynamic-var | ✓ |
|
| `*print-namespace-maps*` | implemented-untested | ✓ |
|
||||||
| `*print-readably*` | implemented+tested | ✓ |
|
| `*print-readably*` | implemented+tested | ✓ |
|
||||||
| `*read-eval*` | dynamic-var | ✓ |
|
| `*read-eval*` | implemented+tested | ✓ |
|
||||||
| `*reader-resolver*` | dynamic-var | |
|
| `*reader-resolver*` | dynamic-var | |
|
||||||
| `*repl*` | dynamic-var | |
|
| `*repl*` | dynamic-var | |
|
||||||
| `*source-path*` | dynamic-var | ✓ |
|
| `*source-path*` | dynamic-var | ✓ |
|
||||||
|
|
@ -63,7 +63,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `*unchecked-math*` | implemented+tested | ✓ |
|
| `*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*` | implemented-untested | ✓ |
|
| `*warn-on-reflection*` | implemented+tested | ✓ |
|
||||||
| `+` | implemented+tested | ✓ |
|
| `+` | implemented+tested | ✓ |
|
||||||
| `+'` | implemented+tested | ✓ |
|
| `+'` | implemented+tested | ✓ |
|
||||||
| `-` | implemented+tested | ✓ |
|
| `-` | implemented+tested | ✓ |
|
||||||
|
|
@ -131,7 +131,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `assoc-in` | implemented+tested | ✓ |
|
| `assoc-in` | implemented+tested | ✓ |
|
||||||
| `associative?` | implemented+tested | ✓ |
|
| `associative?` | implemented+tested | ✓ |
|
||||||
| `atom` | implemented+tested | ✓ |
|
| `atom` | implemented+tested | ✓ |
|
||||||
| `await` | implemented-untested | ✓ |
|
| `await` | implemented+tested | ✓ |
|
||||||
| `await-for` | agents-taps | ✓ |
|
| `await-for` | agents-taps | ✓ |
|
||||||
| `await1` | agents-taps | |
|
| `await1` | agents-taps | |
|
||||||
| `bases` | jvm-specific | ✓ |
|
| `bases` | jvm-specific | ✓ |
|
||||||
|
|
@ -218,7 +218,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `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` | implemented+tested | ✓ |
|
||||||
| `definline` | jvm-specific | |
|
| `definline` | jvm-specific | |
|
||||||
| `definterface` | implemented+tested | ✓ |
|
| `definterface` | implemented+tested | ✓ |
|
||||||
| `defmacro` | special-form | ✓ |
|
| `defmacro` | special-form | ✓ |
|
||||||
|
|
@ -375,7 +375,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `lazy-cat` | implemented+tested | ✓ |
|
| `lazy-cat` | implemented+tested | ✓ |
|
||||||
| `lazy-seq` | implemented+tested | ✓ |
|
| `lazy-seq` | implemented+tested | ✓ |
|
||||||
| `let` | implemented+tested | ✓ |
|
| `let` | implemented+tested | ✓ |
|
||||||
| `letfn` | missing-portable | ✓ |
|
| `letfn` | implemented+tested | ✓ |
|
||||||
| `line-seq` | implemented+tested | ✓ |
|
| `line-seq` | implemented+tested | ✓ |
|
||||||
| `list` | implemented+tested | ✓ |
|
| `list` | implemented+tested | ✓ |
|
||||||
| `list*` | implemented+tested | ✓ |
|
| `list*` | implemented+tested | ✓ |
|
||||||
|
|
@ -512,7 +512,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `rational?` | implemented+tested | ✓ |
|
| `rational?` | implemented+tested | ✓ |
|
||||||
| `rationalize` | implemented+tested | ✓ |
|
| `rationalize` | implemented+tested | ✓ |
|
||||||
| `re-find` | implemented+tested | ✓ |
|
| `re-find` | implemented+tested | ✓ |
|
||||||
| `re-groups` | missing-portable | ✓ |
|
| `re-groups` | implemented+tested | ✓ |
|
||||||
| `re-matcher` | implemented+tested | ✓ |
|
| `re-matcher` | implemented+tested | ✓ |
|
||||||
| `re-matches` | implemented+tested | ✓ |
|
| `re-matches` | implemented+tested | ✓ |
|
||||||
| `re-pattern` | implemented+tested | ✓ |
|
| `re-pattern` | implemented+tested | ✓ |
|
||||||
|
|
@ -558,7 +558,7 @@ UNVERIFIED field; that column will be added as entries land.
|
||||||
| `reset-vals!` | implemented+tested | ✓ |
|
| `reset-vals!` | implemented+tested | ✓ |
|
||||||
| `resolve` | implemented+tested | ✓ |
|
| `resolve` | implemented+tested | ✓ |
|
||||||
| `rest` | implemented+tested | ✓ |
|
| `rest` | implemented+tested | ✓ |
|
||||||
| `restart-agent` | implemented-untested | ✓ |
|
| `restart-agent` | implemented+tested | ✓ |
|
||||||
| `resultset-seq` | jvm-specific | ✓ |
|
| `resultset-seq` | jvm-specific | ✓ |
|
||||||
| `reverse` | implemented+tested | ✓ |
|
| `reverse` | implemented+tested | ✓ |
|
||||||
| `reversible?` | implemented+tested | ✓ |
|
| `reversible?` | implemented+tested | ✓ |
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,35 @@
|
||||||
|
|
||||||
;; *print-meta* — when true, pr prints metadata with a ^ prefix; default false.
|
;; *print-meta* — when true, pr prints metadata with a ^ prefix; default false.
|
||||||
(def-var! "clojure.core" "*print-meta*" #f)
|
(def-var! "clojure.core" "*print-meta*" #f)
|
||||||
|
|
||||||
|
;; Portable clojure.core dynamic vars whose DEFAULT already matches jolt's
|
||||||
|
;; behaviour, so exposing them is sound (resolve/binding work, reads return the
|
||||||
|
;; right value) — not a silent divergence. The ones that change observable output
|
||||||
|
;; if set non-default (*print-length* / *print-level* / *default-data-reader-fn*)
|
||||||
|
;; are deliberately NOT interned until the printer/reader honour them.
|
||||||
|
;;
|
||||||
|
;; *read-eval* — gates #=() read-eval. jolt's reader has no #=, so it reads true
|
||||||
|
;; (no eval-on-read happens regardless); a lib can (binding [*read-eval* false] …).
|
||||||
|
(def-var! "clojure.core" "*read-eval*" #t)
|
||||||
|
;; *print-dup* — gates print-dup (a multimethod that exists); default false.
|
||||||
|
(def-var! "clojure.core" "*print-dup*" #f)
|
||||||
|
;; *print-namespace-maps* — jolt never prints the #:ns{…} map shorthand, so the
|
||||||
|
;; var reads false (accurate); settable for code that toggles it.
|
||||||
|
(def-var! "clojure.core" "*print-namespace-maps*" #f)
|
||||||
|
;; *flush-on-newline* — jolt flushes line output; default true.
|
||||||
|
(def-var! "clojure.core" "*flush-on-newline*" #t)
|
||||||
|
;; *compile-files* — jolt has no separate compile phase that emits .class files.
|
||||||
|
(def-var! "clojure.core" "*compile-files*" #f)
|
||||||
|
;; *math-context* — BigDecimal rounding context; nil = unlimited, jolt's default.
|
||||||
|
(def-var! "clojure.core" "*math-context*" jolt-nil)
|
||||||
|
;; *command-line-args* — the args after the script/-main; nil outside a -m run.
|
||||||
|
(def-var! "clojure.core" "*command-line-args*" jolt-nil)
|
||||||
|
;; *file* — the source file being loaded; "NO_SOURCE_PATH" when none, like the JVM.
|
||||||
|
(def-var! "clojure.core" "*file*" "NO_SOURCE_PATH")
|
||||||
|
|
||||||
|
;; REPL result/exception history. Bound by the REPL after each evaluation; nil
|
||||||
|
;; outside a REPL, which is what reading them returns here.
|
||||||
|
(def-var! "clojure.core" "*1" jolt-nil)
|
||||||
|
(def-var! "clojure.core" "*2" jolt-nil)
|
||||||
|
(def-var! "clojure.core" "*3" jolt-nil)
|
||||||
|
(def-var! "clojure.core" "*e" jolt-nil)
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,15 @@
|
||||||
(seq->list (jolt-seq names))))
|
(seq->list (jolt-seq names))))
|
||||||
jolt-nil)
|
jolt-nil)
|
||||||
|
|
||||||
;; --- reader-conditional / re-matcher: tagged maps (reader-conditional? + the
|
;; --- reader-conditional: a tagged map (reader-conditional? is an overlay
|
||||||
;; matcher consumers are overlay tagged-value predicates that read :jolt/type).
|
;; tagged-value predicate that reads :jolt/type). re-matcher / re-find / re-groups
|
||||||
|
;; are the stateful matcher API in regex.ss.
|
||||||
(define nr-kw-type (keyword "jolt" "type"))
|
(define nr-kw-type (keyword "jolt" "type"))
|
||||||
(define nr-kw-rc (keyword "jolt" "reader-conditional"))
|
(define nr-kw-rc (keyword "jolt" "reader-conditional"))
|
||||||
(define nr-kw-form (keyword #f "form"))
|
(define nr-kw-form (keyword #f "form"))
|
||||||
(define nr-kw-spl (keyword #f "splicing?"))
|
(define nr-kw-spl (keyword #f "splicing?"))
|
||||||
(define nr-kw-mat (keyword "jolt" "matcher"))
|
|
||||||
(define nr-kw-re (keyword #f "re"))
|
|
||||||
(define nr-kw-s (keyword #f "s"))
|
|
||||||
(define nr-kw-pos (keyword #f "pos"))
|
|
||||||
(define (nr-reader-conditional form splicing?)
|
(define (nr-reader-conditional form splicing?)
|
||||||
(jolt-hash-map nr-kw-type nr-kw-rc nr-kw-form form nr-kw-spl splicing?))
|
(jolt-hash-map nr-kw-type nr-kw-rc nr-kw-form form nr-kw-spl splicing?))
|
||||||
(define (nr-re-matcher re s)
|
|
||||||
(jolt-hash-map nr-kw-type nr-kw-mat nr-kw-re re nr-kw-s s nr-kw-pos 0.0))
|
|
||||||
|
|
||||||
;; --- macroexpand-1 / macroexpand: expand a (quoted) call form via the runtime
|
;; --- macroexpand-1 / macroexpand: expand a (quoted) call form via the runtime
|
||||||
;; macro table (host-contract hc-macro?/hc-expand-1; forward-referenced, resolved
|
;; macro table (host-contract hc-macro?/hc-expand-1; forward-referenced, resolved
|
||||||
|
|
@ -47,6 +42,13 @@
|
||||||
(def-var! "clojure.core" "__reader-features" nr-reader-features-get)
|
(def-var! "clojure.core" "__reader-features" nr-reader-features-get)
|
||||||
(def-var! "clojure.core" "__reader-features-set!" nr-reader-features-set!)
|
(def-var! "clojure.core" "__reader-features-set!" nr-reader-features-set!)
|
||||||
(def-var! "clojure.core" "reader-conditional" nr-reader-conditional)
|
(def-var! "clojure.core" "reader-conditional" nr-reader-conditional)
|
||||||
(def-var! "clojure.core" "re-matcher" nr-re-matcher)
|
|
||||||
(def-var! "clojure.core" "macroexpand-1" nr-macroexpand-1)
|
(def-var! "clojure.core" "macroexpand-1" nr-macroexpand-1)
|
||||||
|
|
||||||
|
;; letfn is a special form (the analyzer lowers it to letrec*, checked before any
|
||||||
|
;; macro), but on the JVM it is also a clojure.core macro that (resolve 'letfn)
|
||||||
|
;; finds — like let / loop / fn here. Intern a var so resolution matches; the value
|
||||||
|
;; is never invoked (the analyzer handles every (letfn …) form), and it is NOT
|
||||||
|
;; marked a macro, so macroexpand leaves a letfn form alone (it is special).
|
||||||
|
(def-var! "clojure.core" "letfn"
|
||||||
|
(lambda args (jolt-throw (jolt-ex-info "letfn is a special form" (jolt-hash-map)))))
|
||||||
(def-var! "clojure.core" "macroexpand" nr-macroexpand)
|
(def-var! "clojure.core" "macroexpand" nr-macroexpand)
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,41 @@
|
||||||
(let ((m (irregex-match (regex-t-irx (jolt-re-pattern re)) s)))
|
(let ((m (irregex-match (regex-t-irx (jolt-re-pattern re)) s)))
|
||||||
(if m (irx-result m) jolt-nil)))
|
(if m (irx-result m) jolt-nil)))
|
||||||
|
|
||||||
(define (jolt-re-find re s)
|
;; A stateful matcher (java.util.regex.Matcher): the compiled pattern, the target
|
||||||
|
;; string, the next search position, and the last successful irregex match. re-find
|
||||||
|
;; over a matcher steps through non-overlapping matches; re-groups returns the
|
||||||
|
;; groups of the last one.
|
||||||
|
(define-record-type matcher-t
|
||||||
|
(fields irx str (mutable pos) (mutable last))
|
||||||
|
(nongenerative jolt-matcher-v1))
|
||||||
|
(define (jolt-re-matcher re s)
|
||||||
|
(make-matcher-t (regex-t-irx (jolt-re-pattern re)) s 0 #f))
|
||||||
|
(define (jolt-matcher? x) (matcher-t? x))
|
||||||
|
|
||||||
|
;; re-find: stateless over (re s), or stateful over a matcher (advance + remember).
|
||||||
|
(define jolt-re-find
|
||||||
|
(case-lambda
|
||||||
|
((re s)
|
||||||
(let ((m (irregex-search (regex-t-irx (jolt-re-pattern re)) s)))
|
(let ((m (irregex-search (regex-t-irx (jolt-re-pattern re)) s)))
|
||||||
(if m (irx-result m) jolt-nil)))
|
(if m (irx-result m) jolt-nil)))
|
||||||
|
((m)
|
||||||
|
(let* ((str (matcher-t-str m))
|
||||||
|
(len (string-length str))
|
||||||
|
(start (matcher-t-pos m))
|
||||||
|
(mm (and (<= start len) (irregex-search (matcher-t-irx m) str start))))
|
||||||
|
(if mm
|
||||||
|
(let ((e (irregex-match-end-index mm 0)))
|
||||||
|
(matcher-t-last-set! m mm)
|
||||||
|
(matcher-t-pos-set! m (if (> e start) e (+ start 1)))
|
||||||
|
(irx-result mm))
|
||||||
|
(begin (matcher-t-last-set! m #f) jolt-nil))))))
|
||||||
|
|
||||||
|
;; re-groups: the groups of the matcher's last successful find. Throws when no
|
||||||
|
;; match has succeeded, like Clojure's IllegalStateException "No match found".
|
||||||
|
(define (jolt-re-groups m)
|
||||||
|
(let ((last (matcher-t-last m)))
|
||||||
|
(if last (irx-result last)
|
||||||
|
(jolt-throw (jolt-ex-info "No match found" (jolt-hash-map))))))
|
||||||
|
|
||||||
;; All non-overlapping matches, left to right. Advance past each match end (or by
|
;; All non-overlapping matches, left to right. Advance past each match end (or by
|
||||||
;; one on a zero-width match). nil when there are no matches (Clojure: seq-able as
|
;; one on a zero-width match). nil when there are no matches (Clojure: seq-able as
|
||||||
|
|
@ -203,4 +235,6 @@
|
||||||
(def-var! "clojure.core" "re-matches" jolt-re-matches)
|
(def-var! "clojure.core" "re-matches" jolt-re-matches)
|
||||||
(def-var! "clojure.core" "re-find" jolt-re-find)
|
(def-var! "clojure.core" "re-find" jolt-re-find)
|
||||||
(def-var! "clojure.core" "re-seq" jolt-re-seq)
|
(def-var! "clojure.core" "re-seq" jolt-re-seq)
|
||||||
|
(def-var! "clojure.core" "re-matcher" jolt-re-matcher)
|
||||||
|
(def-var! "clojure.core" "re-groups" jolt-re-groups)
|
||||||
(def-var! "clojure.core" "regex?" jolt-regex?)
|
(def-var! "clojure.core" "regex?" jolt-regex?)
|
||||||
|
|
|
||||||
|
|
@ -1827,6 +1827,14 @@
|
||||||
{:suite "regex / char-class dash" :label "dash + escaped dot in class" :expected "\"a.b_c-d\"" :actual "(re-matches #\"[\\w-_\\.]+\" \"a.b_c-d\")"}
|
{:suite "regex / char-class dash" :label "dash + escaped dot in class" :expected "\"a.b_c-d\"" :actual "(re-matches #\"[\\w-_\\.]+\" \"a.b_c-d\")"}
|
||||||
{:suite "regex / char-class dash" :label "trailing dash in class" :expected "[\"a-b\" \"c-d\"]" :actual "(vec (re-seq #\"[\\w-]+\" \"a-b c-d\"))"}
|
{:suite "regex / char-class dash" :label "trailing dash in class" :expected "[\"a-b\" \"c-d\"]" :actual "(vec (re-seq #\"[\\w-]+\" \"a-b c-d\"))"}
|
||||||
{:suite "regex / nested quantifier" :label "(X+)* parses and matches" :expected "true" :actual "(boolean (re-matches #\"([^%]+)*(%(d))?\" \"abc\"))"}
|
{:suite "regex / nested quantifier" :label "(X+)* parses and matches" :expected "true" :actual "(boolean (re-matches #\"([^%]+)*(%(d))?\" \"abc\"))"}
|
||||||
|
{:suite "regex / matcher" :label "re-find over a matcher" :expected "\"1\"" :actual "(re-find (re-matcher #\"\\d+\" \"a1b22\"))"}
|
||||||
|
{:suite "regex / matcher" :label "stateful step + re-groups" :expected "[[\"12-34\" \"12\" \"34\"] [\"12-34\" \"12\" \"34\"] [\"56-78\" \"56\" \"78\"] nil]" :actual "(let [m (re-matcher #\"(\\d+)-(\\d+)\" \"12-34 56-78\")] [(re-find m) (re-groups m) (re-find m) (re-find m)])"}
|
||||||
|
{:suite "regex / matcher" :label "re-groups before a match throws" :expected :throws :actual "(re-groups (re-matcher #\"\\d\" \"abc\"))"}
|
||||||
|
{:suite "dynamic vars / portable defaults" :label "default reads" :expected "[true false true false]" :actual "[*read-eval* *print-dup* *flush-on-newline* *compile-files*]"}
|
||||||
|
{:suite "dynamic vars / portable defaults" :label "binding *read-eval*" :expected "false" :actual "(binding [*read-eval* false] *read-eval*)"}
|
||||||
|
{:suite "special forms / letfn" :label "mutual recursion" :expected "true" :actual "(letfn [(e? [n] (if (zero? n) true (o? (dec n)))) (o? [n] (if (zero? n) false (e? (dec n))))] (e? 10))"}
|
||||||
|
{:suite "core vars / present and callable" :label "*out* *err* *warn-on-reflection* await restart-agent" :expected "[true true false true true]" :actual "[(boolean *out*) (boolean *err*) *warn-on-reflection* (ifn? await) (ifn? restart-agent)]"}
|
||||||
|
{:suite "dynamic vars / portable defaults" :label "*data-readers* map, *math-context* nil" :expected "[true true]" :actual "[(map? *data-readers*) (nil? *math-context*)]"}
|
||||||
{:suite "regex / re-pattern & string ops" :label "re-pattern build" :expected "\"hi\"" :actual "(re-find (re-pattern \"\\\\w+\") \"hi!\")"}
|
{:suite "regex / re-pattern & string ops" :label "re-pattern build" :expected "\"hi\"" :actual "(re-find (re-pattern \"\\\\w+\") \"hi!\")"}
|
||||||
{:suite "regex / re-pattern & string ops" :label "re-pattern is regex?" :expected "true" :actual "(regex? (re-pattern \"a\"))"}
|
{:suite "regex / re-pattern & string ops" :label "re-pattern is regex?" :expected "true" :actual "(regex? (re-pattern \"a\"))"}
|
||||||
{:suite "regex / re-pattern & string ops" :label "split on regex" :expected "[\"a\" \"b\" \"c\"]" :actual "(do (require '[clojure.string :as s]) (s/split \"a1b2c\" #\"\\d\"))"}
|
{:suite "regex / re-pattern & string ops" :label "split on regex" :expected "[\"a\" \"b\" \"c\"]" :actual "(do (require '[clojure.string :as s]) (s/split \"a1b2c\" #\"\\d\"))"}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue