Commit graph

3 commits

Author SHA1 Message Date
Dmitri Sotnikov
951a3000e6
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>
2026-06-17 03:56:13 +00:00
Dmitri Sotnikov
61d621521b
Library ports: get hiccup running, verify malli (reader + interop fixes) (#127)
* Reader: #() params survive syntax-quote (auto-gensym names)

#(...) named its synthesized params with bare gensyms, so a #() written inside a
syntax-quote had its params qualified to the current ns by sq-symbol — and a
qualified symbol isn't a valid fn param. hiccup's compiler emits
`(let [sb# ..] (iterate! #(.append sb# %) ..)), which broke with "Unable to
resolve symbol: ns/_NNNN".

Name the params with a trailing # (auto-gensym suffix, like Clojure's p1__N#) so
syntax-quote maps them consistently and leaves them unqualified. Harmless outside
a backtick (just a regular symbol name).

* interop: String/valueOf static + String is a CharSequence

Two interop gaps surfaced bringing up hiccup and malli:
- String/valueOf(Object): hiccup's compiler stringifies attribute values with
  (String/valueOf (or arg "")). Added the static — "null" for nil, else core-str.
- (instance? CharSequence s) returned false for a string; String implements
  CharSequence, and malli's :re validator gates on it before matching, so :re
  schemas always failed. instance-check now answers true for strings.

---------

Co-authored-by: Yogthos <yogthos@gmail.com>
2026-06-15 19:36:13 +00:00
Yogthos
7cb86e8f7b Refactor phase 1: split host-interop into a src/jolt/interop/ subdir (jolt-jx5l)
The 813-line host_interop.janet (java.lang statics, java.time, the 458-line
java.io/util/net/sql/text install-io!, and collection interop all in one file)
becomes a 19-line aggregator over src/jolt/interop/:
- java_base.janet  — java.lang statics (Math/Thread/System/Long) + the java.time
                     shim + the shared chr/pad2/formatter coercion helpers
- host_io.janet    — java.io/util/net/sql/text shims; imports java_base for the
                     shared helpers it reuses (it constructs java.time values and
                     formats dates)
- collections.janet— the late-bound .iterator/.nth/.count/.seq interop hooks

host_interop.janet just loads the three and runs install!/install-io!/
install-collections! in order. chr/pad2/formatter become public (they cross the
java_base->host_io boundary now). The registry machinery (class-statics/
tagged-methods/register-*!) stays in the evaluator, which loads first — moving it
out touches the hot dot-dispatch and is left as a separate step.

Pure move, no behavior change. Also fixes a cache footgun the subdir exposed:
source-fingerprint walked src/jolt/ with a non-recursive (os/dir), so an edit to
an interop/ file would not have busted the ctx image cache (stale-image bug) —
made it recurse, keyed by repo-relative path.

Full gate green: host-interop-spec (130+ rows across every JDK area), ctx-image
cold/warm, conformance x3, suite >=4695/88, fixpoint.
2026-06-15 09:37:28 -04:00