Files
rose-ash/lib/prolog/hs-bridge.sx
giles f07b6e497e
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s
prolog: Hyperscript bridge (+19)
pl-hs-query, pl-hs-predicate/1,2,3, pl-hs-install in hs-bridge.sx.
No parser/compiler changes: Hyperscript already compiles
`when allowed(user, action)` to (allowed user action).
Total 590/590.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 08:30:46 +00:00

73 lines
2.3 KiB
Plaintext

;; lib/prolog/hs-bridge.sx — Prolog↔Hyperscript bridge
;;
;; Creates SX functions backed by a Prolog DB, callable directly from
;; Hyperscript DSL conditions. No parser/compiler changes needed:
;; when allowed(user, action) then …
;; compiles to (allowed user action) — a plain SX call.
;;
;; Setup:
;; (define pl-db (pl-load "role(alice,admin). permission(admin,edit). allowed(U,A) :- role(U,R), permission(R,A)."))
;; (define allowed (pl-hs-predicate/2 pl-db "allowed"))
;;
;; Requires tokenizer.sx, parser.sx, runtime.sx, query.sx loaded first.
;; 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 (already strings in SX) 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 def in the caller's
;; environment. 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)))