Commit graph

6 commits

Author SHA1 Message Date
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
cf1fdfdb24 feat: run the real clojure.tools.logging (defmacro/syntax-quote/ns + host shims)
Pivot from a jolt reimplementation to running the upstream library verbatim.
Vendors the real clojure/tools/logging.clj; jolt provides the backend and the
host primitives it needs. Language features (broadly useful for real Clojure
libs), all covered in 3-mode conformance + spec suites:

- defmacro: multi-arity dispatch (jolt-q8l) and a docstring + attr-map + params
  head (jolt-qnr) — the 4-arity log macro and every level macro need these.
- syntax-quote resolves an alias-qualified symbol to its target ns (jolt-9av),
  so a macro template (impl/get-logger) resolves at the use site.
- the ns macro unwraps ^{:map} metadata on the ns name (jolt-8w2 workaround,
  matching def/defn/defmacro).
- a namespace object self-evaluates, so ~*ns* can be spliced into a template.

Host shims (ported from / modeled on clojure where applicable):
- clojure.string/trim-newline (ported, CharSequence interop -> count/subs)
- agent/send-off/send (minimal synchronous stubs; jolt has no thread pool/STM)
- clojure.lang.LockingTransaction/isRunning -> false
- a minimal clojure.pprint (pprint/with-pprint-dispatch/code-dispatch, for spy)
- clojure.tools.logging.impl: a jolt stderr LoggerFactory backend (the library's
  designed pluggable extension point)

docs/libraries.md lists tools.logging; grammar.ebnf metadata note clarified.
Conformance 355/355 x3 modes; full jpm test gate green.
2026-06-13 18:50:53 -04:00
Yogthos
72e36f46de test+docs: spec coverage for migratus-enablement fixes; list migratus
Adds spec/conformance coverage for everything landed enabling migratus:
- conformance corpus (runs interpret/compile/self-host): def 3-arg docstring,
  def/defn ^{:map} name meta, defmacro arity-clause + docstring, defmulti
  docstring, assoc-nil/assoc-in real maps, try multi-body + finally-on-success,
  current-ns restore after a caught throw, cross-ns methods visibility.
- spec suites: host-interop (exception ctors, Character/Thread/Long, Timestamp/
  SimpleDateFormat, java.io.File model + File-aware file-seq, clojure.tools.logging),
  regex (Pattern statics + MULTILINE + quote, String .matches/.replaceAll/
  .replaceFirst), maps (assoc on nil), multimethods (defmulti docstring +
  value-based methods/get-method), macros (defmacro arity-clause + name meta).

Rewrote clojure.tools.logging/spy as a single variadic arity (jolt defmacro
takes only the first clause of a multi-arity macro — jolt-q8l).

docs/libraries.md: add migratus and the next.jdbc compatibility layer, with the
janet-lang/sqlite3 int64 caveat for 14-digit timestamp ids.

Full gate green; conformance 350/350 x3 modes.
2026-06-13 17:45:05 -04:00
Yogthos
eb7a9f1b20 core: spec 35-var batch A — 1.11 parsers, map/partition variants, with-redefs, ns fns
Fifteen vars from the spec coverage gap (docs/spec/coverage.md):
parse-long/parse-double/parse-boolean (strict validation; scan-number alone
accepts 0x10), newline, current-time-ms (host clock for time), update-keys/
update-vals (PHM base, collisions last-wins), partitionv/partitionv-all/
splitv-at (lazy seqs of vectors; splitv-at's tail stays a seq, matching the
reference), with-redefs/with-redefs-fn (roots restored on throw), time,
macroexpand (expand-1 to fixpoint), alias/ns-unalias (write BOTH alias stores
— require :as uses string-keyed :imports while ns-aliases reads :aliases;
split filed), ns-publics (symbol-keyed map; publics == interns, no privacy).

Three pre-existing bugs fixed along the way:
- (partition n step pad coll) misparsed pad as the coll and returned ()
- (require 'bare.symbol) rejected — only vector specs were accepted
- analyze-form leaked the interpreted analyzer's ns on a punt: a throw out of
  the analyzer left current-ns=jolt.analyzer and :compile-ns set, so the
  fallback interpretation resolved user vars against the wrong namespace
  (bit (var user-sym) under compile mode)

And one overlay-authoring landmine documented in-code: a 20-coll fn must not
use 30-macros macros (with-redefs-fn's dotimes compiled as a forward ref that
resolved to the macro fn at runtime) — loop/recur instead.

Gate: conformance 316x3 (+14 rows), suite 4324 pass / 78 clean (was 4081/72;
parse_*/update_* files now contribute), baselines raised, all specs+unit,
fixpoint, self-host, sci, staged. Coverage: missing-portable 35 -> 20.
2026-06-10 11:16:54 -04:00
Dmitri Sotnikov
d3194aae59
Compiler research (#10)
adds self-hosted compiler is functionally:
 
- The default compile path is the portable pipeline using jolt.analyzer (Clojure) → host-neutral IR → backend.janet.
- The analyzer is itself Clojure, compiled by jolt for true self-hosting.
- bootstrap-fixpoint passes (stage1 == stage2 == stage3): rebuilding the compiler on its own output.
- clojure.core is now self-hosted in the overlay.
- Stateful forms (defmacro/ns/deftype/defmulti/require/in-ns) are interpreted by design.
2026-06-09 07:30:25 +08:00
Yogthos
ad5539b0de test(spec): macros, reader, host-interop, namespaces — fix def-doc, resolve, %&
Final spec areas. Bugs caught and fixed:
- (def name docstring value) used the docstring as the value; now the 3-arg
  docstring form binds the value and records :doc meta
- resolve was a nil stub; now a special form resolving a symbol to its var
  (nil if unresolved). Added find-ns (non-creating lookup) and ns-name.
- in-ns didn't evaluate its arg, so (in-ns 'foo) failed; now evaluates it per
  Clojure (the integration test's unquoted form updated to the quoted idiom)
- #(... %& ...) built %& as a positional param instead of a & rest param;
  now emits (fn* [... & gen] ...) so %& captures the rest

Full public-API spec layer now in place. conformance 218/218, jpm test green.
2026-06-05 00:35:48 -04:00