From 16eadc74124225cee473555bd99ebce1f867c29b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 6 Apr 2019 09:46:42 -0600 Subject: [PATCH] correct for issues #88, #89, #90, conformity test #208. --- Cargo.toml | 2 +- src/prolog/codegen.rs | 1 + src/prolog/heap_print.rs | 18 ++++++----- src/prolog/lib/builtins.pl | 40 +++++++++++++----------- src/prolog/lib/reif.pl | 2 +- src/prolog/machine/machine_state_impl.rs | 1 + src/prolog/machine/system_calls.rs | 2 +- src/tests.rs | 12 +++---- 8 files changed, 43 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 647f3da1..352b8bbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.44" +version = "0.8.45" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index f05e8d58..9d84e1d2 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -317,6 +317,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator &InlinedClauseType::IsAtom(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::Char(_)) + | &Term::Constant(_, Constant::EmptyList) | &Term::Constant(_, Constant::Atom(..)) => { code.push(succeed!()); }, diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index b6b93e77..50eafeaa 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -264,7 +264,7 @@ macro_rules! push_space_if_amb { ) } -fn continues_with_append(atom: &str, op: &str) -> bool { +fn requires_space(atom: &str, op: &str) -> bool { match atom.chars().last() { Some(ac) => op.chars().next().map(|oc| { if alpha_char!(ac) { @@ -277,6 +277,8 @@ fn continues_with_append(atom: &str, op: &str) -> bool { alpha_numeric_char!(oc) } else if sign_char!(ac) { sign_char!(oc) || decimal_digit_char!(oc) + } else if ac == '0' { + !non_quoted_token(op.chars()) } else { false } @@ -382,7 +384,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> fn ambiguity_check(&self, atom: &str) -> bool { let tail = self.outputter.range_from(self.last_item_idx ..); - continues_with_append(tail, atom) + requires_space(tail, atom) } // TODO: create a DirectedOp factory method. Use it here, and above. @@ -579,11 +581,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> } fn print_op(&mut self, atom: &str) { - if atom == "," { - self.push_char(','); - } else { - self.print_op_addendum(atom); - } + push_space_if_amb!(self, atom, { + if atom == "," { + self.push_char(','); + } else { + self.print_op_addendum(atom); + } + }); } fn print_char(&mut self, c: char) { diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 6417ac83..e86e305d 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -4,7 +4,7 @@ (+)/2, (**)/2, (*)/2, (-)/1, (-)/2, (/)/2, (/\)/2, (\/)/2, (is)/2, (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2, (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (>=)/2, - (=<)/2, (,)/2, (->)/2, (;)/2, (=..)/2, (==)/2, (\==)/2, + (=<)/2, (',')/2, (->)/2, (;)/2, (=..)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2, (\=@=)/2, (:)/2, abolish/1, asserta/1, assertz/1, atom_chars/2, atom_codes/2, atom_length/2, bagof/3, bb_b_put/2, bb_get/2, bb_put/2, @@ -137,10 +137,10 @@ repeat :- repeat. ','(G1, G2) :- '$get_b_value'(B), '$call_with_default_policy'(comma_errors(G1, G2, B)). :- non_counted_backtracking comma_errors/3. -comma_errors(G1, G2, B) :- var(G1), throw(error(instantiation_error, (,)/2)). +comma_errors(G1, G2, B) :- var(G1), throw(error(instantiation_error, (',')/2)). comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)). -:- non_counted_backtracking (,)/3. +:- non_counted_backtracking (',')/3. ','(!, CF, B) :- compound(CF), '$call_with_default_policy'(CF = ','(G1, G2)), '$set_cp'(B), @@ -256,12 +256,13 @@ expand_term(Term0, Term) :- '$expand_term'(Term0, Term). % term_variables. -can_be(Type, Term) :- error:can_be(Type, Term). +% ensures List is either a variable or a proper list. +can_be_list(List, _) :- var(List), !. +can_be_list(List, _) :- '$skip_max_list'(_, -1, List, Tail), Tail == [], !. +can_be_list(List, PI) :- throw(error(type_error(list, List), PI)). term_variables(Term, Vars) :- - catch(can_be(list, Vars), error(E, Ctx), - ( ( var(Ctx) -> Ctx = term_variables/2 ; true ), - throw(error(E, Ctx)) ) ), + can_be_list(Vars, term_variables/2), '$term_variables'(Term, Vars). % setup_call_cleanup. @@ -721,10 +722,15 @@ current_predicate(Pred) :- '$get_next_op_db_ref'(Ref, NextRef), '$iterate_op_db_refs'(NextRef, Priority, Spec, Op). +can_be_op_priority(Priority) :- var(Priority). +can_be_op_priority(Priority) :- op_priority(Priority). + +can_be_op_specifier(Spec) :- var(Spec). +can_be_op_specifier(Spec) :- op_specifier(Spec). + current_op(Priority, Spec, Op) :- - ( nonvar(Op), \+ atom(Op) - -> throw(error(type_error(atom, Op), current_op/3)) - ; '$get_next_op_db_ref'(Ref, _), + ( can_be_op_priority(Priority), can_be_op_specifier(Spec), error:can_be(atom, Op) + -> '$get_next_op_db_ref'(Ref, _), '$iterate_op_db_refs'(Ref, Priority, Spec, Op) ). @@ -753,7 +759,7 @@ op_specifier(OpSpec) :- atom(OpSpec), op_specifier(OpSpec) :- throw(error(type_error(atom, OpSpec), op/3)). valid_op(Op) :- atom(Op), - ( Op == (,) -> 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)) ; Op == [] -> throw(error(permission_error(create, operator, []), op/3)) ; true @@ -810,24 +816,20 @@ no_var_in_list([]). no_var_in_list([X|Xs]) :- var(X), !, '$fail'. no_var_in_list([_|Xs]) :- no_var_in_list(Xs). -atom_chars(Atom, List) :- - error:can_be(list, List), +atom_chars(Atom, List) :- ( var(Atom) -> ( var(List) -> throw(error(instantiation_error, atom_chars/2)) - ; no_var_in_list(List) -> '$atom_chars'(Atom, List) + ; can_be_list(List, atom_chars/3), no_var_in_list(List) -> '$atom_chars'(Atom, List) ) ; atom(Atom) -> '$atom_chars'(Atom, List) - ; Atom == [] -> '$atom_chars'(Atom, List) ; throw(error(type_error(atom, Atom), atom_chars/2)) ). -atom_codes(Atom, List) :- - error:can_be(list, List), +atom_codes(Atom, List) :- ( var(Atom) -> ( var(List) -> throw(error(instantiation_error, atom_codes/2)) - ; no_var_in_list(List) -> '$atom_codes'(Atom, List) + ; can_be_list(List, atom_codes/3), no_var_in_list(List) -> '$atom_codes'(Atom, List) ) ; atom(Atom) -> '$atom_codes'(Atom, List) - ; Atom == [] -> '$atom_codes'(Atom, List) ; throw(error(type_error(atom, Atom), atom_codes/2)) ). diff --git a/src/prolog/lib/reif.pl b/src/prolog/lib/reif.pl index d57acaf2..0e958356 100644 --- a/src/prolog/lib/reif.pl +++ b/src/prolog/lib/reif.pl @@ -1,4 +1,4 @@ -:- module(reif, [if_/3, (=)/3, (,)/3, (;)/3, cond_t/3, dif/3, +:- module(reif, [if_/3, (=)/3, (',')/3, (;)/3, cond_t/3, dif/3, memberd_t/3, tfilter/3, tmember/2, tmember_t/3, tpartition/4]). diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 5c79e0d0..a59e3f14 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1905,6 +1905,7 @@ impl MachineState { match d { Addr::Con(Constant::Atom(..)) | Addr::Con(Constant::Char(_)) => self.p += 1, + Addr::Con(Constant::EmptyList) => self.p += 1, _ => self.fail = true }; }, diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index f23bd730..f8bbde79 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -362,7 +362,7 @@ impl MachineState { }, ref addr if addr.is_ref() => { let stub = MachineError::functor_stub(clause_name!("atom_chars"), 2); - + match self.try_from_list(temp_v!(2), stub.clone()) { Err(e) => return Err(e), Ok(addrs) => { diff --git a/src/tests.rs b/src/tests.rs index f28ef536..9f3a2eca 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1413,7 +1413,7 @@ fn test_queries_on_builtins() assert_prolog_failure!(&mut wam, "?- atom(X)."); assert_prolog_success!(&mut wam, "?- atom(a)."); assert_prolog_failure!(&mut wam, "?- atom(\"string\")."); - assert_prolog_failure!(&mut wam, "?- atom([])."); + assert_prolog_success!(&mut wam, "?- atom([])."); assert_prolog_failure!(&mut wam, "?- atom(1)."); assert_prolog_failure!(&mut wam, "?- atom(0)."); assert_prolog_failure!(&mut wam, "?- atom(0.0)."); @@ -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 = [_188]", "X = _0", "Y = 1", "Z = _6"]]); + ["L = [_112]", "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(_154)"]]); + [["L = [1, 2]", "X = _0", "Y = f(_78)"]]); 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 = [_188]", "Y = 1", "X = _0", "Y = 1", "Z = _6"]]); + ["L = [_112]", "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"]]); @@ -1794,12 +1794,12 @@ fn test_queries_on_builtins() 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"]]); + [["S = [1, _126, 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"]]); + [["S = [_126, 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, ":- use_module(library(non_iso))."); -- 2.54.0