Move `hs-prolog-hook` / `hs-set-prolog-hook!` / `prolog` out of
`lib/hyperscript/runtime.sx` into a self-contained plugin file at
`lib/hyperscript/plugins/prolog.sx`. The API surface is preserved —
`lib/prolog/hs-bridge.sx::pl-install-hs-hook!` still calls
`hs-set-prolog-hook!` exactly as before, just resolved to the plugin
file's binding rather than runtime.sx's.
Move the E39 worker stub registration out of `lib/hyperscript/parser.sx`
into `lib/hyperscript/plugins/worker.sx`. The plugin calls
`(hs-register-feature! "worker" ...)` at file load time. Behaviour is
identical — `worker MyWorker ...` raises the same helpful "plugin not
installed" error, just routed through the registry from a separate
file. The pre-existing `behavioral` test for the helpful error
("raises a helpful error when the worker plugin is not installed")
still passes via the new path.
Wire-up:
- OCaml `bin/run_tests.ml`: load `plugins/worker.sx` and
`plugins/prolog.sx` after `runtime.sx`, before `integration.sx`.
- JS `tests/hs-kernel-eval.js`: extend HS module list with
`hs-worker` / `hs-prolog`; add `HS_PLUGINS` resolver branch so the
`hs-` prefix maps to `lib/hyperscript/plugins/`.
- WASM `hosts/ocaml/browser/bundle.sh`: copy plugin files into
`dist/sx/hs-<name>.sx`.
- WASM `hosts/ocaml/browser/compile-modules.js`: add `hs-worker` /
`hs-prolog` to `FILES`, `HS_DEPS`, and `HS_LAZY` so the lazy loader
resolves them on first reference.
- Worker plugin carries a sentinel `(define hs-worker-loaded? true)`
so `extractDefines` indexes it in the module manifest (the lazy
loader skips files with no defines).
Mirrors `shared/static/wasm/sx/hs-{parser,runtime}.sx` are byte-identical
to source; new mirrors `hs-{prolog,worker}.sx` written via sx_write_file.
OCaml: 4545 passed, 1339 failed — matches baseline.
JS: 2591 passed, 2465 failed — matches baseline.
Smoke tests: `(prolog ...)` raises "prolog hook not installed" cleanly,
`(hs-set-prolog-hook! ...)` then `(prolog ...)` returns the hook result,
`(hs-compile "worker MyWorker def noop() end end")` raises the worker
stub error via the registry path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
85 lines
2.6 KiB
Plaintext
85 lines
2.6 KiB
Plaintext
;; lib/prolog/hs-bridge.sx — Prolog ↔ Hyperscript bridge
|
|
;;
|
|
;; Two complementary integration styles:
|
|
;;
|
|
;; 1. Hook style — for `prolog(db, "goal(args)")` call syntax in Hyperscript:
|
|
;; (pl-install-hs-hook!) ;; call once at startup
|
|
;; Requires lib/hyperscript/plugins/prolog.sx (provides hs-set-prolog-hook!)
|
|
;;
|
|
;; 2. Factory style — for named conditions like `when allowed(user, action)`:
|
|
;; (define allowed (pl-hs-predicate/2 pl-db "allowed"))
|
|
;; No parser/compiler changes needed: Hyperscript compiles
|
|
;; `allowed(user, action)` to `(allowed user action)` — a plain SX call.
|
|
;;
|
|
;; Requires tokenizer.sx, parser.sx, runtime.sx, query.sx loaded first.
|
|
|
|
;; --- Hook style ---
|
|
|
|
(define
|
|
pl-install-hs-hook!
|
|
(fn
|
|
()
|
|
(hs-set-prolog-hook!
|
|
(fn (db goal) (not (= nil (pl-query-one db goal)))))))
|
|
|
|
;; --- Factory style ---
|
|
|
|
;; Test whether a ground Prolog goal succeeds against db.
|
|
;; Returns true/false (not a solution dict).
|
|
(define
|
|
pl-hs-query
|
|
(fn (db goal-str) (not (nil? (pl-query-one db goal-str)))))
|
|
|
|
;; Build a Prolog goal string from a predicate name and arg list.
|
|
;; SX values: strings/keywords pass through; numbers are stringified via str.
|
|
(define
|
|
pl-hs-build-goal
|
|
(fn
|
|
(pred-name args)
|
|
(str pred-name "(" (join ", " (map (fn (a) (str a)) args)) ")")))
|
|
|
|
;; Return a 1-arg SX function that succeeds iff pred(a) holds in db.
|
|
(define
|
|
pl-hs-predicate/1
|
|
(fn
|
|
(db pred-name)
|
|
(fn (a) (pl-hs-query db (pl-hs-build-goal pred-name (list a))))))
|
|
|
|
;; Return a 2-arg SX function that succeeds iff pred(a, b) holds in db.
|
|
(define
|
|
pl-hs-predicate/2
|
|
(fn
|
|
(db pred-name)
|
|
(fn (a b) (pl-hs-query db (pl-hs-build-goal pred-name (list a b))))))
|
|
|
|
;; Return a 3-arg SX function that succeeds iff pred(a, b, c) holds in db.
|
|
(define
|
|
pl-hs-predicate/3
|
|
(fn
|
|
(db pred-name)
|
|
(fn (a b c) (pl-hs-query db (pl-hs-build-goal pred-name (list a b c))))))
|
|
|
|
;; Install every predicate in install-list as a named SX function backed by db.
|
|
;; install-list: list of (name arity) pairs.
|
|
;; Returns a dict {name → fn} for the caller to destructure.
|
|
(define
|
|
pl-hs-install
|
|
(fn
|
|
(db install-list)
|
|
(reduce
|
|
(fn
|
|
(acc entry)
|
|
(let
|
|
((pred-name (first entry)) (arity (nth entry 1)))
|
|
(dict-set!
|
|
acc
|
|
pred-name
|
|
(cond
|
|
((= arity 1) (pl-hs-predicate/1 db pred-name))
|
|
((= arity 2) (pl-hs-predicate/2 db pred-name))
|
|
((= arity 3) (pl-hs-predicate/3 db pred-name))
|
|
(true (fn (a b) false))))
|
|
acc))
|
|
{}
|
|
install-list)))
|