From b6a5254e350e30c8040ed0b2b1e3d0b85a80dd5b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 1 Apr 2019 22:05:30 -0600 Subject: [PATCH] re: #80, #52 --- Cargo.toml | 4 ++-- src/prolog/lib/builtins.pl | 33 ++++++++++++++++++++++++++------- src/prolog/machine/mod.rs | 6 +++--- src/tests.rs | 18 +++++++++++++++--- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7adce29d..5a10a986 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.35" +version = "0.8.36" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." @@ -14,7 +14,7 @@ cfg-if = "0.1.7" downcast = "0.10.0" num = "0.2" ordered-float = "0.5.0" -prolog_parser = "0.8.11" +prolog_parser = "0.8.12" readline_rs_compat = { version = "0.1.7", optional = true } ref_thread_local = "0.0.0" diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 3639baf7..7357d230 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -110,7 +110,7 @@ set_prolog_flag(double_quotes, chars) :- set_prolog_flag(double_quotes, atom) :- !, '$set_double_quotes'(atom). % 7.11.2.5, list of char codes (UTF8). set_prolog_flag(double_quotes, codes) :- - !, '$set_double_quotes'(codes). + !, '$set_double_quotes'(codes). set_prolog_flag(double_quotes, Value) :- throw(error(domain_error(flag_value, double_quotes + Value), set_prolog_flag/2)). % 8.17.1.3 e @@ -427,14 +427,32 @@ iterate_variants([V-Solution|GroupSolutions], V, Solution). iterate_variants([_|GroupSolutions], Ws, Solution) :- iterate_variants(GroupSolutions, Ws, Solution). +rightmost_power(Term, FinalTerm, Xs) :- + ( Term = X ^ Y + -> ( var(Y) -> FinalTerm = Y, Xs = [X] + ; Xs = [X | Xss], rightmost_power(Y, FinalTerm, Xss) + ) + ; Xs = [], FinalTerm = Term + ). + +findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) :- + ( nonvar(Goal), Goal = _ ^ _ -> + rightmost_power(Goal, Goal1, ExistentialVars0), + term_variables(ExistentialVars0, ExistentialVars), + set_difference(Witnesses0, ExistentialVars, Witnesses), + findall(Witnesses-Template, Goal1, PairedSolutions) + ; Witnesses = Witnesses0, + findall(Witnesses-Template, Goal, PairedSolutions) + ). + bagof(Template, Goal, Solution) :- error:can_be(list, Solution), term_variables(Template, TemplateVars0), term_variables(Goal, GoalVars0), sort(TemplateVars0, TemplateVars), sort(GoalVars0, GoalVars), - set_difference(GoalVars, TemplateVars, Witnesses), - findall(Witnesses-Template, Goal, PairedSolutions0), + set_difference(GoalVars, TemplateVars, Witnesses0), + findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses), keysort(PairedSolutions0, PairedSolutions), group_by_variants(PairedSolutions, GroupedSolutions), iterate_variants(GroupedSolutions, Witnesses, Solution). @@ -450,8 +468,8 @@ setof(Template, Goal, Solution) :- term_variables(Goal, GoalVars0), sort(TemplateVars0, TemplateVars), sort(GoalVars0, GoalVars), - set_difference(GoalVars, TemplateVars, Witnesses), - findall(Witnesses-Template, Goal, PairedSolutions0), + set_difference(GoalVars, TemplateVars, Witnesses0), + findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses), keysort(PairedSolutions0, PairedSolutions), group_by_variants(PairedSolutions, GroupedSolutions), iterate_variants_and_sort(GroupedSolutions, Witnesses, Solution). @@ -721,8 +739,9 @@ op_specifier(OpSpec) :- atom(OpSpec), op_specifier(OpSpec) :- throw(error(type_error(atom, OpSpec), op/3)). valid_op(Op) :- atom(Op), - ( Op \== (,) -> true - ; throw(error(permission_error(modify, operator, (,)), op/3)) % 8.14.3.3 j), k). + ( Op == (,) -> throw(error(permission_error(modify, operator, (,)), op/3)) % 8.14.3.3 j), k). + ; Op == '|' -> throw(error(permission_error(create, operator, (|)), op/3)) % www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing#72 + ; true ). op_(Priority, OpSpec, Op) :- '$op'(Priority, OpSpec, Op). diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 5b7dc287..4bc5c852 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -427,9 +427,9 @@ impl Machine { for (var, addr) in sorted_vars { let addr = self.machine_st.store(self.machine_st.deref(addr.clone())); - if addr.is_ref() { - continue; - } +// if addr.is_ref() { +// continue; +// } output = self.machine_st.print_var_eq(var.clone(), addr, var_dir, output); } diff --git a/src/tests.rs b/src/tests.rs index e854f153..ab71c485 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1750,12 +1750,12 @@ fn test_queries_on_builtins() assert_prolog_success!(&mut wam, "?- bagof(X, (X=Y; X=Z; Y=1), L).", [["L = [_3, _6]", "X = _0", "Y = _3", "Z = _6"], - ["L = [_184]", "X = _0", "Y = 1", "Z = _6"]]); + ["L = [_188]", "X = _0", "Y = 1", "Z = _6"]]); submit(&mut wam, "a(1, f(_)). a(2, f(_))."); assert_prolog_success!(&mut wam, "?- bagof(X, a(X, Y), L).", - [["L = [1, 2]", "X = _0", "Y = f(_150)"]]); + [["L = [1, 2]", "X = _0", "Y = f(_154)"]]); assert_prolog_success!(&mut wam, "?- setof(X, (X = 1 ; X = 2), S).", [["S = [1, 2]", "X = _0"]]); @@ -1767,7 +1767,7 @@ fn test_queries_on_builtins() ["L = [1]", "Y = 2"]]); assert_prolog_success!(&mut wam, "?- setof(X, (X=Y; X=Z; Y=1), L).", [["L = [_3, _6]", "X = _0", "Y = _3", "Z = _6"], - ["L = [_184]", "X = _0", "Y = 1", "Z = _6"]]); + ["L = [_188]", "Y = 1", "X = _0", "Y = 1", "Z = _6"]]); assert_prolog_failure!(&mut wam, "?- setof(X, member(X, [f(U,b),f(V,c)]), [f(a,c),f(a,b)])."); assert_prolog_success!(&mut wam, "?- setof(X, member(X, [f(U,b),f(V,c)]), [f(a,b),f(a,c)]).", [["U = a", "V = a", "X = _0"]]); @@ -1790,6 +1790,18 @@ fn test_queries_on_builtins() assert_prolog_success!(&mut wam, "?- catch(findall(X, 4, S0, S1), error(type_error(callable, 4), _), true).", [["S0 = _3", "S1 = _4", "X = _1"]]); + // bagof & setof with existential variables. + assert_prolog_success!(&mut wam, "?- bagof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", + [["S = [1, 2]", "X = _0", "Y = _5"]]); + assert_prolog_success!(&mut wam, "?- bagof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", + [["S = [1, _240, 2]", "X = _0", "Y = _5"]]); + + assert_prolog_success!(&mut wam, "?- setof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", + [["S = [1, 2]", "X = _0", "Y = _5"]]); + assert_prolog_success!(&mut wam, "?- setof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", + [["S = [_240, 1, 2]", "X = _0", "Y = _5"]]); + assert_prolog_success!(&mut wam, "?- setof(X, (exists(U,V) ^ member(X, [V,U,f(U),f(V)])), [a,b,f(b),f(a)])."); + submit(&mut wam, " :- dynamic(cat/0). cat. -- 2.54.0