;; 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)))