Fix five bugs surfaced by commonmark-app (jolt-3xur, dl4s, ik3a, w2wf, xtss) (#158)

* Fix four bugs surfaced by the commonmark-app example

- regex: bounded quantifiers {n,m} no longer expand exponentially. The
  desugaring inlined the continuation per optional level, doubling it each
  time, so {0,61} built a PEG the compiler expanded to ~2^61 nodes and hung.
  Each level is now its own grammar rule referenced by name (jolt-3xur).

- strings are a seqable of chars for vec/set/into, matching seq. They went
  through realize-for-iteration, which had no string case, so into/set got
  raw bytes (code points) and set threw; vec used string/from-bytes (1-char
  strings). realize-for-iteration now maps make-char over the bytes, and
  core-vec matches (jolt-dl4s).

- clojure.string/split takes Java Pattern.split limit semantics: negative
  keeps trailing empties, 0/omitted drops them (a no-match result stays
  [input]), positive caps the part count with the remainder unsplit. It used
  to delegate the limit to take, so a negative limit returned [] and the
  2-arg form never trimmed trailing empties (jolt-ik3a).

- System/exit is registered (maps to os/exit), so (System/exit n) works
  (jolt-w2wf).

* regex: single-digit backreferences \1..\9 (jolt-xtss)

\1..\9 now match the text captured by the corresponding group, so
patterns like ([-*_])\1\1 or (\w+) \1 work. The parser records which
groups are referenced; a referenced group additionally captures its text
under a tag and the backref compiles to a PEG (backmatch). Only referenced
groups change — they match possessively (the CPS-over-possessive-PEG engine
can't backtrack into a tagged capture), so backtracking back into a
backreferenced group isn't supported (rare). Unreferenced groups keep full
backtracking and position-based result capture unchanged.

---------

Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
Dmitri Sotnikov 2026-06-17 03:56:13 +00:00 committed by GitHub
parent 8192fc9541
commit 951a3000e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 111 additions and 25 deletions

View file

@ -20,6 +20,22 @@
["pr-str of a defn" "\"#'user/gg\"" "(pr-str (defn gg [x] x))"]
["seq of string" "[\\a \\b]" "(seq \"ab\")"])
(defspec "string as a seqable of chars (jolt-dl4s)"
["vec of string" "[\\a \\b]" "(vec \"ab\")"]
["into [] of string" "[\\a \\b]" "(into [] \"ab\")"]
["set of string" "true" "(= #{\\a \\b} (set \"ab\"))"]
["into #{} of string" "true" "(= #{\\a \\b} (into #{} \"ab\"))"]
["set dedups chars" "2" "(count (set \"aab\"))"]
["mapv over string" "[\\a \\b]" "(mapv identity \"ab\")"])
(defspec "clojure.string / split limit (jolt-ik3a)"
["neg keeps trailing" "[\"a\" \"\" \"\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,,\" #\",\" -1))"]
["zero trims trailing" "[\"a\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,,\" #\",\" 0))"]
["omitted trims" "[\"a\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,,\" #\",\"))"]
["positive caps parts" "[\"a\" \"b,c\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,b,c\" #\",\" 2))"]
["empty string" "[\"\"]" "(do (require (quote [clojure.string :as s])) (s/split \"\" #\",\"))"]
["interior empties kept" "[\"a\" \"\" \"b\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,,b\" #\",\"))"])
(defspec "clojure.string"
["join" "\"a,b,c\"" "(do (require (quote [clojure.string :as s])) (s/join \",\" [\"a\" \"b\" \"c\"]))"]
["join no sep" "\"abc\"" "(do (require (quote [clojure.string :as s])) (s/join [\"a\" \"b\" \"c\"]))"]