Commit Graph

1251 Commits

Author SHA1 Message Date
17d6f58cc5 datalog: dl-magic-rewrite worklist now drains across rule chains (239/239)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Real bug: the worklist used (set! queue (rest queue)) to pop the
head, which left queue bound to a fresh empty list as soon as the
last item was popped. Subsequent (append! queue ...) was a no-op
on the empty list — so when the head's rewrite generated new
(rel, adn) pairs to enqueue, they vanished. Multi-relation
programs (e.g. shortest -> path -> edge, or chained derived
relations) only had their head's rules rewritten; downstream
rules silently dropped.

Fix: use an index-based loop (idx 0 → len queue), with append!
adding to the same list. Items added after the current pointer
are picked up in subsequent iterations.

2 new regression tests:
- 4-level chain (a → r1 → r2 → r3 → r4) under magic returns 2
- shortest-path demo via magic equals dl-query (1 result)
2026-05-08 14:41:05 +00:00
e981368dcf datalog: magic ≡ semi on federation foaf demo (237/237)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 54s
2026-05-08 14:29:18 +00:00
59bec68dcc perf: Phase 6 — substrate perf-regression alarm (perf-smoke)
Replaces the watchdog-bump approach with an automated check. The next 5× (or
worse) substrate regression will trip the alarm at build time instead of
hiding behind a deadline bump and only being noticed weeks later.

Components:

* lib/perf-smoke.sx — four micro-benchmarks chosen for distinct substrate
  failure modes: function-call dispatch (fib), env construction (let-chain),
  HO-form dispatch + lambda creation (map-sq), TCO + primitive dispatch
  (tail-loop). Warm-up pass populates JIT cache before the timed pass so we
  measure the steady state.

* scripts/perf-smoke.sh — pipes lib/perf-smoke.sx to sx_server.exe, parses
  per-bench wall-time, asserts each is within FACTOR× of the recorded
  reference (default 5×). `--update` rewrites the reference in-place.

* scripts/sx-build-all.sh — perf-smoke wired in as a post-step after JS
  tests. Hard fail if any benchmark regressed beyond budget.

Reference numbers: minimum across 6 back-to-back runs on this dev machine
under typical concurrent-loop contention (load ~9, 2 vCPU, 7.6 GiB RAM,
OCaml 5.2.0, architecture @ 92f6f187). Documented in
plans/jit-perf-regression.md including how to update them.

The 5× factor is chosen so contention noise (~1–2× variance) doesn't trigger
false alarms but a real ≥5× substrate regression — the kind that motivated
this whole investigation — fails the build immediately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:23:45 +00:00
4a7cff2f6b datalog: built-in-only query goals (236/236)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 47s
2026-05-08 14:19:25 +00:00
21c541bd1b datalog: parser rejection tests for invalid relation names (233/233)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 56s
2026-05-08 14:16:31 +00:00
0985dc6386 datalog: disjunction via multiple rules test (231/231)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 52s
2026-05-08 14:12:34 +00:00
f12edc8fd9 datalog: indirect aggregate cycle rejected (230/230)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
2026-05-08 14:08:02 +00:00
92f6f187b7 merge: architecture into bugs/jit-perf — Phase 1 deadline tweaks
Conflict in lib/tcl/test.sh: architecture had bumped `timeout 2400 → 7200`,
this branch had restored it to `timeout 300` based on the Phase 1
quiet-machine measurement (376/376 in 57.8s wall, 16.3s user). Resolved by
keeping `timeout 300` — the 7200s bump was preemptive against contention,
not against an actual substrate regression. Phase 1 confirms the original
180s deadline is comfortable; 300s gives 5× headroom for moderate noise.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:07:14 +00:00
c361946974 perf: deadline tweaks (tcl 2400→300s, erlang 120→600s); plan + Phase 1 findings
Phase 1 of the jit-perf-regression plan reproduced and quantified the alleged
30× substrate slowdown across 5 guests (tcl, lua, erlang, prolog, haskell). On
a quiet machine all five suites pass cleanly:

  tcl test.sh         57.8s wall, 16.3s user, 376/376 ✓
  lua test.sh         27.3s wall,  4.2s user, 185/185 ✓
  erlang conformance  3m25s wall, 36.8s user, 530/530 ✓ (needs ≥600s budget)
  prolog conformance  3m54s wall, 1m08s user, 590/590 ✓
  haskell conformance 6m59s wall, 2m37s user, 156/156 ✓

Per-test user-time at architecture HEAD vs pre-substrate-merge baseline
(83dbb595) is essentially flat (tcl 0.83×, lua 1.4×, prolog 0.82×). The
symptoms reported in the plan (test timeouts, OOMs, 30-min hangs) were heavy
CPU contention from concurrent loops + one undersized internal `timeout 120`
in erlang's conformance script. There is no substrate regression to bisect.

Changes:

* lib/tcl/test.sh: `timeout 2400` → `timeout 300`. The original 180s deadline
  is comfortable on a quiet machine (3.1× headroom); 300s gives some safety
  margin for moderate contention without masking real regressions.
* lib/erlang/conformance.sh: `timeout 120` → `timeout 600`. The 120s budget
  was actually too tight for the full 9-suite chain even before this work.
* lib/erlang/scoreboard.{json,md}: 0/0 → 530/530 — populated by a successful
  conformance run with the new deadline. The previous 0/0 was a stale
  artefact of the run timing out before parsing any markers.
* plans/jit-perf-regression.md: full Phase 1 progress log including
  per-guest perf table, quiet-machine re-measurement, and conclusion.

Phases 2–4 (bisect, diagnose, fix) skipped — there is no substrate regression
to find. Phase 6 (perf-regression alarm) still planned to catch the next
quadratic blow-up early instead of via watchdog bumps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:05:29 +00:00
9f539ab392 ocaml: phase 3 polymorphic variants (+4 tests, 382 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 46s
Tokenizer recognises backtick followed by an upper ident, emitting a
ctor token identical to a nominal ctor. Parser and evaluator treat
polyvariants as ctors — same tagged-list runtime. So:

  `Red                   -> ("Red")
  `Some 42               -> ("Some" 42)
  match `Red with | `Red -> 1 | `Green -> 2 | `Blue -> 3
                          -> 1
  `Pair (1,2)            -> ("Pair" 1 2) (with tuple-arg flatten)

Proper row types in HM deferred.
2026-05-08 14:03:09 +00:00
986b15c0e5 ocaml: phase 6 Float module: sqrt/sin/cos/pow/floor/ceil/round/pi (+6 tests, 378 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Wraps host SX math primitives via _float_* builtins. Float.pi is a
Float literal in the OCaml-side module.
2026-05-08 13:58:52 +00:00
0b4f5e1df9 js-on-sx: top-level this resolves to the global object
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 15s
Per ES non-strict script semantics, top-level this is the global
object (window/global/globalThis). Was throwing "Undefined symbol:
this". Two-part fix:
1. js-global-this runtime variable set to js-global after globals
   are defined; js-this falls back to it when no this is active.
2. js-eval wraps transpiled body in (let ((this (js-this))) ...)
   so JS this resolves to bound this, or top-level to global.
Fixes String(this), this.Object === Object, etc.
built-ins/Object: 46/50 → 47/50. conformance.sh: 148/148.
2026-05-08 13:55:12 +00:00
ee002f2e02 ocaml: phase 1/5/6 float arithmetic +./-./*./. (+5 tests, 372 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 27s
Tokenizer: +. -. *. /. (with -. avoiding clash with negative float
literals). Parser table places dotted ops at int-precedence levels.
Eval routes to host SX +/-/*//. HM types them Float->Float->Float;
literal floats now infer as Float (was Int).

OCaml-style 1.5 +. 2.5 : Float works end-to-end through tokenize +
parse + eval + infer.
2026-05-08 13:55:04 +00:00
16df48ff74 ocaml: phase 6 List.combine/split/iter2/fold_left2/map2 (+4, 367 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
Mechanical pair-walk OCaml implementations. failwith on length
mismatch matches Stdlib semantics. List module now covers 30+
functions.
2026-05-08 13:48:48 +00:00
dac9cf124f ocaml: refresh scoreboard (364/364 across 14 suites)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
2026-05-08 13:45:29 +00:00
46d0eb258e ocaml: phase 5.1 baseline 8/8 — quicksort + exceptions + closures
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 38s
Added 3 baseline programs:
- closures.ml — curried make_adder; verifies closure capture
- quicksort.ml — recursive sort using List.filter + List.append, sums result
- exception_handle.ml — exception NegArg of int + raise + try/with

All 8/8 baseline programs pass through ocaml-run-program. Combined the
suite exercises: let-rec, modules, refs, for-loops, pattern matching,
exceptions, lambdas, list ops (map/filter/append/fold), arithmetic.

run.sh streamlined to one sx_server invocation per program. End-to-end
runtime ≈2 min.
2026-05-08 13:44:28 +00:00
de7be332c8 ocaml: phase 5.1 baseline OCaml programs (5/5 pass) + lookahead boundary
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 33s
lib/ocaml/baseline/{factorial,list_ops,option_match,module_use,sum_squares}.ml
exercised through ocaml-run-program (file-read F). lib/ocaml/baseline/
run.sh runs them and compares against expected.json — all 5 pass.

To make module_use.ml (with nested let-in) parse, parser's
skip-let-rhs-boundary! now uses has-matching-in? lookahead: a let at
depth 0 in a let-decl rhs opens a nested block IFF a matching in
exists before any decl-keyword. Without that in, the let is a new
top-level decl (preserves test 274 'let x = 1 let y = 2').

This is the first piece of Phase 5.1 'vendor a slice of OCaml
testsuite' — handcrafted fixtures for now, real testsuite TBD.
2026-05-08 13:33:24 +00:00
4ab79f5758 js-on-sx: parser handles comma operator (a, b, c)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s
Was failing with "Expected punct ')' got punct ','" because the
paren handler only consumed a single assignment. Added
jp-parse-comma-seq helpers that build a js-comma AST node with
the expression list; transpiler emits (begin ...) so each is
evaluated in order and the last value is returned.
built-ins/Object: 44/50 → 46/50. conformance.sh: 148/148.
2026-05-08 13:20:53 +00:00
756d5fba64 ocaml: phase 5 HM with user type declarations (+6 tests, 363 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
ocaml-hm-ctors is now a mutable list cell; user type-defs register
their constructors via ocaml-hm-register-type-def!. New
ocaml-type-of-program processes top-level decls in order:
- type-def: register ctors with the scheme inferred from PARAMS+CTORS
- def/def-rec: generalize and bind in the type env
- exception-def: no-op for typing
- expr: return inferred type

Examples:
  type color = Red | Green | Blue;; Red : color
  type shape = Circle of int | Square of int;;
  let area s = match s with
    | Circle r -> r * r
    | Square s -> s * s;;
  area : shape -> Int

Caveat: ctor arg types parsed as raw source strings; registry defaults
to int for any single-arg ctor. Proper type-source parsing pending.
2026-05-08 13:12:07 +00:00
5bc7895ce0 ocaml: phase 5 HM let-rec + cons / append op types (+6 tests, 357 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
ocaml-infer-let-rec pre-binds the function name to a fresh tv before
inferring rhs (which may recursively call the name), unifies the
inferred rhs type with the tv, generalizes, then infers body.

Builtin env types :: : 'a -> 'a list -> 'a list and @ : 'a list ->
'a list -> 'a list — needed because :op compiles to (:app (:app (:var
OP) L) R) and previously these var lookups failed.

Examples now infer:
  let rec fact n = if ... in fact : Int -> Int
  let rec len lst = ... in len    : 'a list -> Int
  let rec map f xs = ... in map   : ('a -> 'b) -> 'a list -> 'b list
  1 :: [2; 3]                      : Int list
  let rec sum lst = ... in sum [1;2;3] : Int

Scoreboard refreshed: 358/358 across 14 suites.
2026-05-08 13:08:51 +00:00
81247eb6ea ocaml: phase 5 HM ctor inference for option/result (+7 tests, 351 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
ocaml-hm-ctor-env registers None/Some : 'a -> 'a option, Ok/Error :
'a -> ('a, 'b) result. :con NAME instantiates the scheme; :pcon NAME
ARG-PATS walks arg patterns through the constructor's arrow type,
unifying each.

Pretty-printer renders 'Int option' and '(Int, 'b) result'.

Examples now infer:
  fun x -> Some x : 'a -> 'a option
  match Some 5 with | None -> 0 | Some n -> n : Int
  fun o -> match o with | None -> 0 | Some n -> n : Int option -> Int
  Ok 1 : (Int, 'b) result
  Error "oops" : ('a, String) result

User type-defs would extend the registry — pending.
2026-05-08 13:05:22 +00:00
d2bf0c0d00 ocaml: phase 5 HM pattern-match inference (+5 tests, 344 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
ocaml-infer-pat covers :pwild, :pvar, :plit, :pcons, :plist, :ptuple,
:pas. Returns {:type T :env ENV2 :subst S} where ENV2 has the pattern's
bound names threaded through.

ocaml-infer-match unifies each clause's pattern type with the scrutinee,
runs the body in the env extended with pattern bindings, and unifies
all body types via a fresh result tv.

Examples:
  fun lst -> match lst with | [] -> 0 | h :: _ -> h : Int list -> Int
  match (1, 2) with | (a, b) -> a + b              : Int

Constructor patterns (:pcon) fall through to a fresh tv for now —
proper handling needs a ctor type registry from 'type' declarations.
2026-05-08 13:02:15 +00:00
202ea9cf5f ocaml: phase 6 List.sort + compare (+7 tests, 339 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
compare is a host builtin returning -1/0/1 (Stdlib.compare semantics)
deferred to host SX </>. List.sort is insertion-sort in OCaml: O(n²)
but works correctly. List.stable_sort = sort.

Tested: ascending int sort, descending via custom comparator (b - a),
empty list, string sort.
2026-05-08 12:59:50 +00:00
812aa75d43 ocaml: phase 6 Hashtbl (+6 tests, 332 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 32s
Backing store is a one-element list cell holding a SX dict; keys
coerced to strings via str so int/string keys work uniformly. API:
create, add, replace, find, find_opt, mem, length.

_hashtbl_create / _hashtbl_add / _hashtbl_replace / _hashtbl_find_opt /
_hashtbl_mem / _hashtbl_length primitives wired in eval.sx; OCaml-side
Hashtbl module wraps them in lib/ocaml/runtime.sx.
2026-05-08 12:57:22 +00:00
6d7197182e ocaml: phase 5 HM tuple + list types (+7 tests, 326 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 29s
Tuple type (hm-con "*" TYPES); list type (hm-con "list" (TYPE)).
ocaml-infer-tuple threads substitution through each item left-to-right.
ocaml-infer-list unifies all items with a fresh 'a (giving 'a list for
empty []).

Pretty-printer renders 'Int * Int' for tuples and 'Int list' for lists,
matching standard OCaml notation.

Examples:
  fun x y -> (x, y) : 'a -> 'b -> 'a * 'b
  fun x -> [x; x] : 'a -> 'a list
  []                : 'a list
2026-05-08 12:54:15 +00:00
b7627b4102 js-on-sx: ToPrimitive treats functions as non-primitive
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Per ES, ToPrimitive only accepts strings/numbers/booleans/null
/undefined as primitives — objects AND functions trigger the next
step. Was treating function returns from toString/valueOf as
primitives (recursing to extract a string), so toString returning
a function didn't fall through to valueOf. Widened the dict-only
check to (or (= type "dict") (js-function? result)) in both
js-to-string and js-to-number ToPrimitive paths.
built-ins/String: 85/99 → 86/99. conformance.sh: 148/148.
2026-05-08 12:50:40 +00:00
a0abdcf520 ocaml: refresh scoreboard (320/320 across 14 suites)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
2026-05-08 12:50:39 +00:00
88c02c7c73 ocaml: phase 6 expanded stdlib (+15 tests, 319 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 54s
List: concat/flatten, init, find/find_opt, partition, mapi/iteri,
assoc/assoc_opt. Option: iter/fold/to_list. Result: get_ok/get_error/
map_error/to_option.

Fixed skip-to-boundary! in parser to track let..in / begin..end /
struct..end / for/while..done nesting via a depth counter — without
this, nested-let inside a top-level decl body trips over the
decl-boundary detector. Stdlib functions like List.init / mapi / iteri
use begin..end to make their nested-let intent explicit.
2026-05-08 12:49:23 +00:00
9edccb8f33 datalog: bipartite friends-with-hobby join test (229/229)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s
2026-05-08 12:39:04 +00:00
bc557a5ad2 ocaml: phase 3 exception declarations (+4 tests, 304 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 50s
exception NAME [of TYPE] parses to (:exception-def NAME [ARG-SRC]).
Runtime is a no-op: raise/match already work on tagged ctor values, so
'exception E of int;; try raise (E 5) with | E n -> n' end-to-end with
zero new eval logic.
2026-05-08 12:37:58 +00:00
8e508bc90f datalog: magic existence check (bb-adornment) regression test (228/228)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 54s
2026-05-08 12:35:33 +00:00
d8f6250962 ocaml: phase 3 type declarations (+5 tests, 300 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 52s
Parser: type [PARAMS] NAME = | Ctor [of T1 [* T2]*] | ...
- PARAMS: optional 'a or ('a, 'b) tyvar list
- AST: (:type-def NAME PARAMS CTORS) with each CTOR (NAME ARG-SOURCES)
- Argument types captured as raw source strings (treated opaquely at
  runtime since ctor dispatch is dynamic)

Runtime is a no-op — constructors and pattern matching already work
dynamically. Phase 5 will use these decls to register ctor types for
HM checking.
2026-05-08 12:32:39 +00:00
5f4defe99e datalog: magic over rule with negation regression test (227/227)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
2026-05-08 12:31:50 +00:00
d20df7aa8c datalog: magic over rule with aggregate body literal (226/226)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
2026-05-08 12:28:52 +00:00
851e0585cf ocaml: phase 3 'as' alias + 'when' guard in match (+6 tests, 295 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 50s
Pattern parser top wraps cons-pat with 'as ident' -> (:pas PAT NAME).
Match clause parser consumes optional 'when GUARD-EXPR' before -> and
emits (:case-when PAT GUARD BODY) instead of :case.

Eval: :pas matches inner pattern then binds the alias name; case-when
checks the guard after a successful match and falls through to the next
clause if the guard is false.

Or-patterns deferred — ambiguous with clause separator without
parens-only support.
2026-05-08 12:28:07 +00:00
d51ae65bbb js-on-sx: fn.toString honours Function.prototype.toString overrides
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 41s
Two hardcoded paths returned the native marker regardless of user
override: js-invoke-function-method and the lambda branch of
js-to-string. Both now look up Function.prototype.toString via
js-dict-get-walk and invoke it on the function, falling back to
the native marker only if no override exists.
built-ins/String: 84/99 → 85/99. conformance.sh: 148/148.
2026-05-08 12:07:55 +00:00
e97bdc4602 js-on-sx: native prototypes carry wrapped primitive marker
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 32s
Per ES, Boolean.prototype is a Boolean wrapper around false,
Number.prototype wraps 0, String.prototype wraps "". So
Boolean.prototype == false (loose-eq unwraps), and
Object.prototype.toString.call(Number.prototype) ===
"[object Number]". Set __js_*_value__ on each in post-init.
built-ins/Boolean: 23/27 → 24/27, String: 80/99 → 84/99.
conformance.sh: 148/148.
2026-05-08 11:27:18 +00:00
f03aa3056d js-on-sx: js-to-number throws TypeError on non-primitive
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 49s
Mirrors the earlier js-to-string fix. Number(obj) must throw
if ToPrimitive cannot extract a primitive (both valueOf and
toString return objects). Was returning NaN silently. Replaced
the inner (js-nan-value) fallback with (raise (js-new-call
TypeError ...)).
built-ins/Number: 45/50 → 46/50. conformance.sh: 148/148.
2026-05-08 10:53:58 +00:00
96f66d3596 datalog: dl-magic-query handles mixed EDB+IDB relations (225/225)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s
Bug: dl-magic-query was skipping EDB facts for relations that had
rules ("rule-headed"). When a single relation has both EDB facts
and rules deriving more (mixed EDB+IDB), the rewritten run would
miss the EDB portion entirely, producing too few or zero results.

Fix: copy ALL existing facts to the internal mdb regardless of
whether the relation has rules. EDB-only relations bring their
tuples; mixed relations bring both EDB and any pre-saturated IDB
(which the rewritten rules would re-derive anyway).

1 new test: link relation seeded with 3 EDB tuples plus a
recursive rule via via/2. dl-magic-query rooted at `a` returns
2 results (a→b direct, a→c via via(a,e), link(e,c)).
2026-05-08 10:41:36 +00:00
ec7e4dd5c4 datalog: bounded-successor regression test (224/224)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
2026-05-08 10:36:13 +00:00
370df5b8e5 datalog: diagonal query (repeated var) regression test (223/223)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
2026-05-08 10:33:45 +00:00
a648247ae4 datalog: dl-magic-query falls back on built-in/agg/neg goals (222/222)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Bug: dl-magic-query was always trying to seed a magic_<rel>^<adn>
fact for the query goal. For aggregate goals like (count N X (p X))
this produced a non-ground "fact" (magic_count^... N X (p X)) and
dl-add-fact! correctly rejected it, surfacing as an error.

Fix: dl-magic-query now detects built-in / aggregate / negation
goals up front and dispatches to plain dl-query for those cases —
magic-sets only applies to positive non-builtin literals against
rule-defined relations. Other shapes don't benefit from the
rewrite anyway.

1 new test confirms (count N X (p X)) returns the expected
{:N 3} via dl-magic-query.
2026-05-08 10:32:01 +00:00
5a3db1a458 datalog: magic preserves arithmetic test (221/221)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
2026-05-08 10:29:14 +00:00
549cb5ea84 datalog: mixed-EDB+IDB-same-relation regression test (220/220)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
2026-05-08 10:27:45 +00:00
e0c7de1a1c datalog: org-chart + transitive headcount demo (219/219)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 27s
Adds dl-demo-org-rules: (subordinate Mgr Emp) over a (manager
EMP MGR) graph, and (headcount Mgr N) using count aggregation
grouped by manager. Demonstrates real-world hierarchy queries
(e.g. "everyone reporting up to the CEO") + per-manager rollup.

3 new demo tests: transitive subordinates of CEO (5 entries),
CEO headcount, and direct manager headcount.
2026-05-08 10:24:10 +00:00
de734b27b8 datalog: group-by-via-aggregate-in-rule test (216/216)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
2026-05-08 10:22:03 +00:00
4c11c4e1b9 js-on-sx: native prototypes inherit from Object.prototype
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 39s
Per ES, every native prototype's [[Prototype]] is Object.prototype
(and Function.prototype.[[Prototype]] is too). Was missing those
links, so Object.prototype.isPrototypeOf(Boolean.prototype)
returned false (the explicit isPrototypeOf walks __proto__, not
the recent fallback). Added 5 dict-set! lines to the post-init.
built-ins/Boolean: 22/27 → 23/27, built-ins/Number: 44/50 → 45/50.
conformance.sh: 148/148.
2026-05-08 10:21:05 +00:00
7a64be22d8 datalog: dl-eval ≡ dl-eval-magic equivalence test (215/215)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 46s
2026-05-08 10:19:58 +00:00
9695d31dab datalog: dl-rules-of relation-inspection helper (214/214)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 49s
(dl-rules-of db rel-name) → list of rules with head matching
the given relation name. Useful for tooling and debugging
("show me how this relation is derived") without exposing the
internal :rules list directly.

2 new api tests cover hit and miss cases.
2026-05-08 10:17:44 +00:00
fc6979a371 datalog: dl-saturated? fixpoint predicate (212/212)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 43s
Returns true iff one more saturation step would derive no new
tuples. Walks every rule under the current bindings and short-
circuits as soon as one derivation would add a fresh tuple.
Useful in tests that want to assert "no work left" after a call,
or for tooling that wants to know whether `dl-saturate!` would
do anything.

3 new eval tests cover the after-saturation, before-saturation,
and after-assert states.
2026-05-08 10:15:29 +00:00