///|
/// Demo: a small family database plus list programming, evaluated by the
/// Prolog EDSL. The program is written in plain Prolog syntax and parsed
/// with `parse_program`.
///
/// Run with `moon run cmd/main`.
using @prolog {parse_program, parse_term}
///|
fn main raise {
let family_src =
#|parent(john, mary). parent(john, jane). parent(mary, bob).
#|ancestor(X, Y) :- parent(X, Y).
#|ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
#|
let prog = parse_program(family_src)
println("== family ==")
for ans in prog.solve([parse_term("parent(X, _)")]) {
println(ans)
}
println("ancestors of bob:")
for ans in prog.solve([parse_term("ancestor(Y, bob)")]) {
println(ans)
}
println("== lists ==")
let lib_src =
#|member(X, [X | _]).
#|member(X, [_ | T]) :- member(X, T).
#|append([], L, L).
#|append([H | T], L, [H | R]) :- append(T, L, R).
#|reverse([], []).
#|reverse([H | T], R) :- reverse(T, R1), append(R1, [H], R).
#|
let lib = parse_program(lib_src)
for ans in lib.solve([parse_term("member(E, [1, 2, 3])")]) {
println(ans)
}
for ans in lib.solve([parse_term("append([1, 2], [3, 4], XS)")]) {
println(ans)
}
for ans in lib.solve([parse_term("reverse([1, 2, 3], R)")]) {
println(ans)
}
println("== meta ==")
for ans in lib.solve([parse_term("findall(X, member(X, [1, 2, 3]), L)")]) {
println(ans)
}
for ans in lib.solve([parse_term("(member(X, [1, 2, 3]) -> X = 9 ; X = 0)")]) {
println(ans)
}
for ans in lib.solve([parse_term("(fail -> X = 9 ; X = 0)")]) {
println(ans)
}
for ans in lib.solve([parse_term("sort([3, 1, 2, 1], S)")]) {
println(ans)
}
println("== DCG ==")
let grammar_src =
#|digits([D]) --> [D].
#|digits([D | Ds]) --> [D], digits(Ds).
#|
let grammar = parse_program(grammar_src)
for ans in grammar.solve([parse_term("phrase(digits(Ds), [1, 2, 3])")]) {
println(ans)
}
println("== dif ==")
for ans in lib.solve([parse_term("(dif(X, b), X = a)")]) {
println(ans)
}
let none = lib.solve([parse_term("(dif(X, b), X = b)")]).to_array()
println("dif(X, b), X = b has \{none.length()} solution(s)")
println("== dynamic predicates ==")
let dyn_prog = parse_program(":- dynamic(fact/2).")
for ans in dyn_prog.solve([parse_term("assertz(fact(john, 42))")]) {
println(ans)
}
for ans in dyn_prog.solve([parse_term("assertz(fact(mary, 7))")]) {
println(ans)
}
for ans in dyn_prog.solve([parse_term("fact(X, N)")]) {
println(ans)
}
for
ans in dyn_prog.solve([
parse_term("(fact(john, N), retract(fact(john, N)))"),
]) {
println(ans)
}
println("facts left: \{dyn_prog.solve([parse_term("fact(_, _)")]).count()}")
}