# 04dec23 Software Lab. Alexander Burger
(private) (CL Q R L Prg)
(de be CL
(clause CL) )
(de clause (CL)
(with (++ CL)
(if (== *Rule This)
(queue (:: T) CL)
(=: T (list CL))
(setq *Rule This) )
(def This T (: T)) ) )
(de repeat ()
(conc (get *Rule T) (get *Rule T)) )
(de asserta (CL)
(push (prop CL 1 T) (cdr CL)) )
(de assertz (CL)
(queue (prop CL 1 T) (cdr CL)) )
(de retract (X)
(if (sym? X)
(put X T)
(put (car X) T
(delete (cdr X) (get (car X) T)) ) ) )
(de rules @
(while (args)
(let S (next)
(for ((N . L) (get S T) L)
(prin N " (be ")
(print S)
(for X (++ L)
(space)
(print X) )
(prinl ")")
(T (== L (get S T))
(println '(repeat)) ) )
S ) ) )
### Pilog Interpreter ###
(private) (Env Dbg *R)
(de goal (CL . @)
(let Env '(T)
(while (args)
(push 'Env
(cons (cons 0 (next)) 1 (next)) ) )
(while (and CL (pat? (car CL)))
(push 'Env
(cons
(cons 0 (++ CL))
(cons 1 (eval (++ CL))) ) ) )
(cons
(cons
(conc (list 1 (0) NIL CL NIL) Env) ) ) ) )
(de fail ()
(goal '((NIL))) )
(de pilog (CL . Prg)
(for (Q (goal CL) (prove Q))
(bind @ (run Prg)) ) )
(de solve (CL . Prg)
(make
(if Prg
(for (Q (goal CL) (prove Q))
(link (bind @ (run Prg))) )
(for (Q (goal CL) (prove Q))
(link @) ) ) ) )
(de query (Q Dbg)
(use R
(loop
(NIL (prove Q Dbg))
(T (=T (setq R @)) T)
(for X R
(space)
(print (car X))
(print '=)
(print (cdr X)) )
(prinl)
(T (= "\e" (key)) T) ) ) )
(de ? CL
(let L
(make
(while (nor (pat? (car CL)) (lst? (car CL)))
(link (++ CL)) ) )
(query (goal CL) L) ) )
### Basic Rules ###
(private) (_or _for)
(be repeat)
(repeat)
(be true)
(be not @P (1 @P) T (fail))
(be not @P)
(be call @P (2 (cons @P)))
(be or @L (^ @C (box @L)) (_or @C))
(be _or (@C) (3 (pop @C)))
(be _or (@C) (^ @ (not (val @C))) T (fail))
(repeat)
(be nil (@X) (^ @ (not @X)))
(be equal (@X @X))
(be different (@X @X) T (fail))
(be different (@ @))
(be append (NIL @X @X))
(be append ((@A . @X) @Y (@A . @Z)) (append @X @Y @Z))
(be member (@X (@X . @)))
(be member (@X (@ . @Y)) (member @X @Y))
(be delete (@A (@A . @Z) @Z))
(be delete (@A (@X . @Y) (@X . @Z))
(delete @A @Y @Z) )
(be permute ((@X) (@X)))
(be permute (@L (@X . @Y))
(delete @X @L @D)
(permute @D @Y) )
(be uniq (@B @X)
(^ @
(not (idx @B (cons (hash @X) @X) T)) ) )
(be asserta (@C) (^ @ (asserta @C)))
(be assertz (@C) (^ @ (assertz @C)))
(be retract (@C)
(2 (cons @C))
(^ @ (retract (list (car @C) (cdr @C)))) )
(be clause (@H @B)
(^ @A (get @H T))
(member @B @A) )
(be show (@X) (^ @ (show @X)))
(be for (@N @End) (for @N 1 @End 1))
(be for (@N @Beg @End) (for @N @Beg @End 1))
(be for (@N @Beg @End @Step) (equal @N @Beg))
(be for (@N @Beg @End @Step)
(^ @I (box @Beg))
(_for @N @I @End @Step) )
(be _for (@N @I @End @Step)
(^ @
(if (>= @End (val @I))
(> (inc @I @Step) @End)
(> @End (dec @I @Step)) ) )
T
(fail) )
(be _for (@N @I @End @Step)
(^ @N (val @I)) )
(repeat)
### DB ###
(de initQuery (Var Cls Hook Val)
(let (Tree (tree Var Cls Hook) Rel (get Cls Var))
(when (find '((B) (isa '+index B)) (get Rel 'bag))
(setq Rel @) )
(when (or (isa '+Fold Rel) (isa '+IdxFold Rel))
(setq Val (fold Val)) )
(cond
((pair Val)
(cond
((and (pair (cdr Val)) (; Rel aux))
(cond
((atom (car Val))
(and (; Rel ub) (setq Val (ubZval Val)))
(init Tree Val (append Val T)) )
((; Rel ub)
(init Tree
(ubZval (car Val))
(ubZval (cdr Val) T) ) )
((>= (cdr Val) (car Val))
(init Tree (car Val) (append (cdr Val) T)) )
(T (init Tree (append (car Val) T) (cdr Val))) ) )
((isa '+Key Rel)
(init Tree (car Val) (cdr Val)) )
((>= (cdr Val) (car Val))
(init Tree
(cons (car Val))
(cons (cdr Val) T) ) )
(T
(init Tree
(cons (car Val) T)
(cons (cdr Val)) ) ) ) )
((or (num? Val) (ext? Val))
(if (isa '+Key Rel)
(init Tree Val Val)
(init Tree (cons Val) (cons Val T)) ) )
((=T Val) (init Tree))
((isa '+Key Rel)
(init Tree Val (pack Val `(char T))) )
((isa '+Idx Rel)
(let Q (init Tree (cons Val) (cons (pack Val `(char T)) T))
(if (cdr Q)
Q
(setq Val (pack (car (split (chop Val) " "))))
(init Tree (cons Val) (cons (pack Val `(char T)) T)) ) ) )
(T (init Tree (cons Val) (cons (pack Val `(char T)) T))) ) ) )
(private) _db
# (db var cls obj)
(be db (@Var @Cls @Obj)
(^ @C (box)) # (obj ..)
(^ @Q
(box
(with (or (get @Cls @Var) (meta @Cls @Var))
(initQuery (: var) (: cls) NIL '(NIL . T)) ) ) )
(_db @Obj) )
# (db var cls hook|val obj)
(be db (@Var @Cls @X @Obj)
(^ @C (box)) # (obj ..)
(^ @Q
(box
(with (or (get @Cls @Var) (meta @Cls @Var))
(if (: hook)
(initQuery (: var) (: cls) @X '(NIL . T))
(initQuery (: var) (: cls) NIL @X) ) ) ) )
(_db @Obj) )
# (db var cls hook val obj)
(be db (@Var @Cls @Hook @Val @Obj)
(^ @C (box)) # (obj ..)
(^ @Q
(box
(with (or (get @Cls @Var) (meta @Cls @Var))
(initQuery (: var) (: cls) @Hook @Val) ) ) )
(_db @Obj) )
(be _db (@Obj)
(^ @
(let (Q (val (-> @Q 2)) Cls (-> @Cls 2))
(loop
(NIL (step Q (= '(NIL) (caaar Q))) T)
(T
(and
(isa Cls (setq *R @))
(not (idx (-> @C 2) *R T)) ) ) ) ) )
T
(fail) )
(be _db (@Obj) (^ @Obj *R))
(repeat)
(private) (_lst _map)
(be val (@V . @L)
(^ @V (apply get @L))
T )
(be lst (@V . @L)
(^ @Lst (box (apply get @L)))
(_lst @V @Lst) )
(be _lst (@Val @Lst) (^ @ (not (val @Lst))) T (fail))
(be _lst (@Val @Lst) (^ @Val (pop @Lst)))
(repeat)
(be map (@V . @L)
(^ @Lst (box (apply get @L)))
(_map @V @Lst) )
(be _map (@Val @Lst) (^ @ (not (val @Lst))) T (fail))
(be _map (@Val @Lst) (^ @Val (prog1 (val @Lst) (pop @Lst))))
(repeat)
(private) (_same _range _head _hold _fold _part _tolr)
(be isa (@Typ . @L)
(^ @
(or
(not @Typ)
(isa @Typ (apply get @L)) ) ) )
(be same (@V . @L)
(^ @
(or (not @V) (_same (car @L) (cdr @L))) ) )
(de _same (X L)
(cond
((not L)
(if (atom X)
(= @V X)
(member @V X) ) )
((atom X)
(_same (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_same (get Y (car L)) (cdr L)))
X ) )
(T (_same (apply get (car L) X) (cdr L))) ) )
(be bool (@F . @L)
(^ @
(or (not @F) (bool (apply get @L))) ) )
(be ub (@A @R . @L)
(^ @
(or
(not @R)
(let X (apply get @L)
(fully
'((K V1 V2)
(>= V2 (get X K) V1) )
@A
(car @R)
(cdr @R) ) ) ) ) )
(be range (@R . @L)
(^ @
(or (not @R) (_range (car @L) (cdr @L))) ) )
(de _range (X L)
(cond
((not L)
(if (atom X)
(or
(<= (car @R) X (cdr @R))
(>= (car @R) X (cdr @R)) )
(find
'((Y)
(or
(<= (car @R) Y (cdr @R))
(>= (car @R) Y (cdr @R)) ) )
X ) ) )
((atom X)
(_range (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_range (get Y (car L)) (cdr L)))
X ) )
(T (_range (apply get (car L) X) (cdr L))) ) )
(be head (@S . @L)
(^ @
(or (not @S) (_head (car @L) (cdr @L))) ) )
(de _head (X L)
(cond
((not L)
(if (atom X)
(pre? @S X)
(find '((Y) (pre? @S Y)) X) ) )
((atom X)
(_head (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_head (get Y (car L)) (cdr L)))
X ) )
(T (_head (apply get (car L) X) (cdr L))) ) )
(be hold (@S . @L)
(^ @
(or (not @S) (_hold (car @L) (cdr @L))) ) )
(de _hold (X L)
(cond
((not L)
(if (atom X)
(sub? @S X)
(find '((Y) (sub? @S Y)) X) ) )
((atom X)
(_hold (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_hold (get Y (car L)) (cdr L)))
X ) )
(T (_hold (apply get (car L) X) (cdr L))) ) )
(be fold (@S . @L)
(^ @
(or
(not (setq @S (fold @S)))
(_fold (car @L) (cdr @L)) ) ) )
(de _fold (X L)
(cond
((not L)
(if (atom X)
(pre? @S (fold X))
(find '((Y) (pre? @S (fold Y))) X) ) )
((atom X)
(_fold (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_fold (get Y (car L)) (cdr L)))
X ) )
(T (_fold (apply get (car L) X) (cdr L))) ) )
(be part (@S . @L)
(^ @
(or
(not (setq @S (fold @S)))
(_part (car @L) (cdr @L)) ) ) )
(de _part (X L)
(cond
((not L)
(if (atom X)
(sub? @S (fold X))
(find '((Y) (sub? @S (fold Y))) X) ) )
((atom X)
(_part (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_part (get Y (car L)) (cdr L)))
X ) )
(T (_part (apply get (car L) X) (cdr L))) ) )
(be tolr (@S . @L)
(^ @
(or
(not (setq @S (fold @S)))
(_tolr (car @L) (cdr @L)) ) ) )
(de _tolr (X L)
(cond
((not L)
(if (atom X)
(or (sub? @S (fold X)) (pre? (ext:Snx @S) (ext:Snx X)))
(let P (ext:Snx @S)
(find
'((Y)
(or (sub? @S (fold Y)) (pre? P (ext:Snx Y))) )
X ) ) ) )
((atom X)
(_tolr (get X (car L)) (cdr L)) )
((atom (car L))
(pick
'((Y) (_tolr (get Y (car L)) (cdr L)))
X ) )
(T (_tolr (apply get (car L) X) (cdr L))) ) )
(private) (_select _initSel _gen _sel)
(de _select (Lst Flg)
(let? X
(nond
((atom (car Lst))
(make
(for (L (++ Lst) L)
(let
(Var (++ L)
Cls (++ L)
Hook (and (get Cls Var 'hook) (++ L))
Val (++ L) )
(and (or Val Flg) (chain (_initSel))) ) ) ) )
((pat? (car Lst))
(let
(Var (++ Lst)
Cls (++ Lst)
Hook (and (get Cls Var 'hook) (++ Lst))
Val (++ Lst) )
(and (or Val Flg) (_initSel)) ) )
(NIL
(let (Var (++ Lst) Val (++ Lst))
(and
(or Flg (apply or Val))
(cons Var (goal (++ Lst))) ) ) ) )
(cons
(cons
(for (L NIL Lst)
(push 'L (++ Lst) NIL)
L )
X ) ) ) )
(de _initSel ()
(with (treeRel Var Cls)
(let Tree (tree Var (: cls) Hook)
(conc
(and
(isa '+IdxFold This)
(<> Val (fold Val))
(init Tree (cons Val) (cons (pack Val `(char T)) T)) )
(initQuery Var (: cls) Hook Val)
(and
(isa '+Sn This)
(init Tree
(cons (setq Val (ext:Snx Val)))
(cons (pack Val `(char T)) T) ) ) ) ) ) )
(de _gen (Lst Q)
(cond
(Lst
(use X
(loop
(T
(cond
((atom (car Lst))
(prog1 (car Lst) (set Lst)) )
((atom (caar Lst)) (pop Lst))
(T
(prog1
(step (car Lst) (= '(NIL) (caar (caar Lst))))
(or (cdaar Lst) (set Lst)) ) ) )
@ )
(NIL (setq X (_gen (cddr Lst) Q)))
(set Lst
(let Y (cadr Lst)
(cond
((atom Y) (get X Y))
((=T (caddr Y))
(initQuery (car Y) (cadr Y) X (cadddr Y)) ) # X = Hook
(T
(initQuery
(car Y)
(cadr Y)
(caddr Y)
(if (cadddr Y)
(cons
(cons X (car @))
(cons X (cdr @)) )
X ) ) ) ) ) ) ) ) )
((pat? (car Q)) (get (prove (cdr Q)) @))
(T (step Q (= '(NIL) (caaar Q)))) ) )
(private) (@Obj @X @Lst @P @C)
(be select ((@Obj . @X) . @Lst)
(^ @ (unify @X))
(^ @P (box (cdr @Lst)))
(^ @C
(box # ((obj ..) curr . lst)
(let L
(or
(mapcan _select (car @Lst))
(_select (caar @Lst) T) )
(cons NIL L L) ) ) )
(_gen @Obj)
(^ @ (unify 2))
(_sel) )
(be _gen (@Obj)
(^ @
(let C (caadr (val (-> @C 2)))
(not (setq *R (_gen (car C) (cdr C)))) ) )
T
(fail) )
(be _gen (@Obj) (^ @Obj *R))
(repeat)
(be _sel ()
(2 (val (-> @P 2)))
(^ @
(let C (val (-> @C 2))
(unless (idx C *R T)
(rot (cddr C) (offset (cadr C) (cddr C)))
(set (cdr C) (cddr C)) ) ) )
T )
(be _sel ()
(^ @
(let C (cdr (val (-> @C 2)))
(set C (or (cdar C) (cdr C))) ) )
(fail) )
### Remote queries ###
(de rqry Args
(for (Q (goal (cdr Args)) (prove Q))
(pr (get @ (car Args)))
(NIL (flush)) )
(bye) )
(be remote (@Lst . @CL)
(^ @Sockets
(box
(prog1
(cdr @Lst)
(for X @ # (out . in)
((car X)
(cons 'rqry (car @Lst) @CL) ) ) ) ) )
(^ @ (unify (car @Lst)))
(_remote @Lst) )
(be _remote ((@Obj . @))
(^ @ (not (val (-> @Sockets 2))))
T
(fail) )
(be _remote ((@Obj . @))
(^ @Obj
(let (Box (-> @Sockets 2) Lst (val Box))
(rot Lst)
(loop
(T ((cdr (++ Lst))) @)
(NIL (set Box Lst)) ) ) ) )
(repeat)
(be revolve (@Lst . @CL)
(^ @Gen
(prog1 (box)
(for X (cddr @Lst)
(push @
(goal
(cons (cadr @Lst) (lit X) @CL) ) ) )
(push @ (car @Lst)) ) )
(^ @ (unify (car @Lst)))
(_revolve @Lst) )
(be _revolve ((@Val . @))
(^ @ (not (cdar (-> @Gen 2))))
T
(fail) )
(be _revolve ((@Val . @))
(^ @Val
(let L (val (-> @Gen 2))
(rot (cdr L))
(loop
(T (prove (cadr L))
(get @ (car L)) )
(NIL (con L (cddr L))) ) ) ) )
(repeat)