[package]
name = "scryer-prolog"
-version = "0.8.76"
+version = "0.8.77"
repository = "https://github.com/mthom/scryer-prolog"
description = "A modern Prolog implementation written mostly in Rust."
downcast = "0.10.0"
num = "0.2"
ordered-float = "0.5.0"
-prolog_parser = "0.8.24"
+prolog_parser = "0.8.26"
readline_rs_compat = { version = "0.1.9", optional = true }
ref_thread_local = "0.0.0"
* `(@>=)/2`
* `(@=<)/2`
* `(@<)/2`
-* `(=@=)/2`
-* `(\=@=)/2`
* `(\+)/1`
* `(==)/2`
* `(\==)/2`
* `user:goal_expansion/2`
* `user:term_expansion/2`
* `var/1`
+* `variant/2`
* `write/1`
* `write_canonical/1`
* `writeq/1`
pub enum CompareTermQT {
LessThan,
LessThanOrEqual,
- Equal,
GreaterThanOrEqual,
GreaterThan,
- NotEqual,
}
impl CompareTermQT {
CompareTermQT::LessThan => "@<",
CompareTermQT::GreaterThanOrEqual => "@>=",
CompareTermQT::LessThanOrEqual => "@=<",
- CompareTermQT::NotEqual => "\\=@=",
- CompareTermQT::Equal => "=@="
}
}
}
m.insert(("@<", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::LessThan)));
m.insert(("@>=", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual)));
m.insert(("@=<", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)));
- m.insert(("\\=@=", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)));
- m.insert(("=@=", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)));
m.insert(("copy_term", 2), ClauseType::BuiltIn(BuiltInClauseType::CopyTerm));
m.insert(("cyclic_term", 1), ClauseType::BuiltIn(BuiltInClauseType::CyclicTerm));
m.insert(("==", 2), ClauseType::BuiltIn(BuiltInClauseType::Eq));
ModuleAssertDynamicPredicateToBack,
CharCode,
CharsToNumber,
+ CodesToNumber,
CheckCutPoint,
CopyToLiftedHeap,
DeleteAttribute,
ModuleRetractClause,
NoSuchPredicate,
NumberToChars,
+ NumberToCodes,
OpDeclaration,
REPL(REPLCodePtr),
ReadTerm,
TermVariables,
TruncateLiftedHeapTo,
UnifyWithOccursCheck,
- UnwindStack,
+ UnwindStack,
+ Variant,
WriteTerm
}
&SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"),
&SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
+ &SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
&SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults) =>
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
+ &SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"),
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
&SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"),
&SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
+ &SystemClauseType::Variant => clause_name!("$variant"),
&SystemClauseType::WriteTerm => clause_name!("$write_term"),
}
}
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
+ ("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber),
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
("$number_to_chars", 2) => Some(SystemClauseType::NumberToChars),
+ ("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
("$op", 3) => Some(SystemClauseType::OpDeclaration),
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
+ ("$variant", 2) => Some(SystemClauseType::Variant),
("$write_term", 4) => Some(SystemClauseType::WriteTerm),
_ => None
}
self.lists.push(Self::add_index(is_initial_index, index));
},
&Term::Constant(_, Constant::String(_))
- if self.flags.double_quotes.is_chars() => { // strings are lists in this case.
+ if !self.flags.double_quotes.is_atom() => { // strings are lists in this case.
let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index));
},
(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,
- abolish/1, asserta/1, assertz/1, atom_chars/2, atom_codes/2,
+ (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (:)/2, abolish/1, asserta/1,
+ assertz/1, atom_chars/2, atom_codes/2, atom_concat/3,
atom_length/2, bagof/3, catch/3, char_code/2, clause/2,
current_op/3, current_predicate/1, current_prolog_flag/2,
expand_goal/2, expand_term/2, false/0, findall/3, findall/4,
- get_char/1, halt/0, number_chars/2, once/1, op/3, read_term/2,
- repeat/0, retract/1, set_prolog_flag/2, setof/3,
- subsumes_term/2, term_variables/2, throw/1, true/0,
- unify_with_occurs_check/2, write/1, write_canonical/1,
- write_term/2, writeq/1]).
+ get_char/1, halt/0, number_chars/2, number_codes/2, once/1,
+ op/3, read_term/2, repeat/0, retract/1, set_prolog_flag/2,
+ setof/3, sub_atom/5, subsumes_term/2, term_variables/2,
+ throw/1, true/0, unify_with_occurs_check/2, write/1,
+ write_canonical/1, write_term/2, writeq/1]).
% module resolution operator.
:- op(600, xfy, :).
:- op(700, xfx, [>, <, =\=, =:=, >=, =<]).
% term comparison.
-:- op(700, xfx, [==, \==, @=<, @>=, @<, @>, =@=, \=@=]).
+:- op(700, xfx, [==, \==, @=<, @>=, @<, @>]).
% the maximum arity flag. needs to be replaced with current_prolog_flag(max_arity, MAX_ARITY).
max_arity(63).
set_difference(Xs, [], Xs).
group_by_variant([V2-S2 | Pairs], V1-S1, [S2 | Solutions], Pairs0) :-
- V1 =@= V2, !, V1 = V2, group_by_variant(Pairs, V2-S2, Solutions, Pairs0).
+ non_iso:variant(V1, V2), !, V1 = V2, group_by_variant(Pairs, V2-S2, Solutions, Pairs0).
group_by_variant(Pairs, _, [], Pairs).
group_by_variants([V-S|Pairs], [V-Solution|Solutions]) :-
; throw(error(type_error(atom, Atom), atom_codes/2))
).
+atom_concat(Atom_1, Atom_2, Atom_12) :-
+ error:can_be(atom, Atom_1),
+ error:can_be(atom, Atom_2),
+ error:can_be(atom, Atom_12),
+ ( var(Atom_1) ->
+ ( var(Atom_12) -> throw(error(instantiation_error, atom_concat/3))
+ ; atom_chars(Atom_12, Atom_12_Chars),
+ lists:append(BeforeChars, AfterChars, Atom_12_Chars),
+ atom_chars(Atom_1, BeforeChars),
+ atom_chars(Atom_2, AfterChars)
+ )
+ ; var(Atom_2) ->
+ ( var(Atom_12) -> throw(error(instantiation_error, atom_concat/3))
+ ; atom_chars(Atom_1, Atom_1_Chars),
+ atom_chars(Atom_12, Atom_12_Chars),
+ lists:append(Atom_1_Chars, Atom_2_Chars, Atom_12_Chars),
+ atom_chars(Atom_2, Atom_2_Chars)
+ )
+ ; atom_chars(Atom_1, Atom_1_Chars),
+ atom_chars(Atom_2, Atom_2_Chars),
+ lists:append(Atom_1_Chars, Atom_2_Chars, Atom_12_Chars),
+ atom_chars(Atom_12, Atom_12_Chars)
+ ).
+
+sub_atom(Atom, Before, Length, After, Sub_atom) :-
+ error:must_be(atom, Atom),
+ error:can_be(atom, Sub_atom),
+ error:can_be(integer, Before),
+ error:can_be(integer, Length),
+ error:can_be(integer, After),
+ ( integer(Before), Before < 0 -> throw(error(domain_error(not_less_than_zero, Before), sub_atom/5))
+ ; integer(Length), Length < 0 -> throw(error(domain_error(not_less_than_zero, Length), sub_atom/5))
+ ; integer(After), After < 0 -> throw(error(domain_error(not_less_than_zero, After), sub_atom/5))
+ ; atom_chars(Atom, AtomChars),
+ lists:append(BeforeChars, LengthAndAfterChars, AtomChars),
+ lists:append(LengthChars, AfterChars, LengthAndAfterChars),
+ '$skip_max_list'(Before, -1, BeforeChars, []),
+ '$skip_max_list'(Length, -1, LengthChars, []),
+ '$skip_max_list'(After, -1, AfterChars, []),
+ atom_chars(Sub_atom, LengthChars)
+ ).
+
char_code(Char, Code) :-
( var(Char) ->
( var(Code) -> throw(error(instantiation_error, char_code/2))
Chsx = Chs
).
+number_codes(N, Chs) :-
+ ( ground(Chs)
+ -> can_be_number(N, number_codes/2),
+ can_be_list(Chs, number_codes/2),
+ '$codes_to_number'(Chs, Nx),
+ Nx = N
+ ; must_be_number(N, number_codes/2),
+ ( var(Chs) -> true
+ ; can_be_list(Chs, number_codes/2)
+ , codes_or_vars(Chs, number_codes/2)
+ ),
+ '$number_to_codes'(N, Chsx),
+ Chsx = Chs
+ ).
+
subsumes_term(General, Specific) :-
\+ \+ (
term_variables(Specific, SVs1),
:- module(non_iso, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
call_with_inference_limit/3, forall/2,
- setup_call_cleanup/3]).
+ setup_call_cleanup/3, variant/2]).
forall(Generate, Test) :-
\+ (Generate, \+ Test).
; '$remove_call_policy_check'(B), '$fail' ),
'$erase_ball',
'$call_with_default_policy'(handle_ile(B, Ball, R)).
+
+variant(X, Y) :- '$variant'(X, Y).
use prolog::machine::machine_indices::*;
use prolog::machine::modules::*;
use prolog::machine::or_stack::*;
-use prolog::num::{BigInt, BigUint, Zero, One};
+use prolog::num::{BigInt, BigUint, One, ToPrimitive, Zero};
use prolog::read::PrologStream;
use downcast::Any;
{
let mut chars = String::new();
let mut iter = addrs.iter();
-
+
while let Some(addr) = iter.next() {
match addr {
&Addr::Con(Constant::String(ref s))
Ok(chars)
}
+ pub(super)
+ fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError>
+ {
+ let mut codes = vec![];
+ let mut iter = addrs.iter();
+
+ while let Some(addr) = iter.next() {
+ match addr {
+ &Addr::Con(Constant::String(ref s))
+ if self.flags.double_quotes.is_codes() => {
+ codes.extend(s.borrow().chars().map(|c| c as u8));
+
+ if iter.next().is_some() {
+ return Err(MachineError::representation_error(RepFlag::CharacterCode));
+ }
+ },
+ &Addr::Con(Constant::CharCode(c)) =>
+ codes.push(c),
+ &Addr::Con(Constant::Number(Number::Integer(ref n))) =>
+ if let Some(c) = n.to_u8() {
+ codes.push(c);
+ } else {
+ return Err(MachineError::representation_error(RepFlag::CharacterCode));
+ },
+ _ =>
+ return Err(MachineError::representation_error(RepFlag::CharacterCode))
+ }
+ }
+
+ Ok(codes)
+ }
+
fn call_at_index(&mut self, arity: usize, p: usize)
{
self.cp.assign_if_local(self.p.clone() + 1);
return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CompareTerm(qt) => {
- match qt {
- CompareTermQT::Equal =>
- machine_st.fail = machine_st.structural_eq_test(),
- CompareTermQT::NotEqual =>
- machine_st.fail = !machine_st.structural_eq_test(),
- _ => machine_st.compare_term(qt)
- };
-
+ machine_st.compare_term(qt);
return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CyclicTerm => {
self.fail = true;
},
Addr::Con(Constant::String(ref s))
- if self.flags.double_quotes.is_chars() && !s.is_empty() => {
+ if !self.flags.double_quotes.is_atom() && !s.is_empty() => {
if n == 1 || n == 2 {
let a3 = self[temp_v!(3)].clone();
let h_a = if n == 1 {
- Addr::Con(Constant::Char(s.head().unwrap()))
+ if self.flags.double_quotes.is_chars() {
+ Addr::Con(Constant::Char(s.head().unwrap()))
+ } else {
+ Addr::Con(Constant::CharCode(s.head().unwrap() as u8))
+ }
} else {
Addr::Con(Constant::String(s.tail()))
};
Addr::DBRef(_) =>
self.fail = true,
Addr::Con(Constant::String(ref s))
- if self.flags.double_quotes.is_chars() && !s.is_empty() => {
+ if !self.flags.double_quotes.is_atom() && !s.is_empty() => {
let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc)
},
l = hcp + 1;
},
Addr::Con(Constant::String(ref s))
- if self.flags.double_quotes.is_chars() => {
+ if !self.flags.double_quotes.is_atom() => {
result.push(Addr::Con(Constant::String(s.clone())));
break;
},
Ok(result)
},
- Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() =>
+ Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() =>
Ok(vec![Addr::Con(Constant::String(s.clone()))]),
Addr::HeapCell(_) | Addr::StackCell(..) =>
Err(self.error_form(MachineError::instantiation_error(), caller)),
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
- if self.flags.double_quotes.is_chars() =>
+ if !self.flags.double_quotes.is_atom() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
Addr::Lis(offset) => offset + 1,
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
- if self.flags.double_quotes.is_chars() =>
+ if !self.flags.double_quotes.is_atom() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
};
match search_result {
- CycleSearchResult::String(n, s) =>
+ CycleSearchResult::String(n, s) =>
if max_steps == -1 {
self.finalize_skip_max_list(n + s.len(),
Addr::Con(Constant::EmptyList))
}
}
+ fn parse_number_from_string(&mut self, mut string: String, indices: &IndexStore, stub: MachineStub)
+ -> CallResult
+ {
+ let nx = self[temp_v!(2)].clone();
+
+ if let Some(c) = string.chars().last() {
+ if layout_char!(c) {
+ let err = ParserError::UnexpectedChar(c);
+
+ let h = self.heap.h;
+ let err = MachineError::syntax_error(h, err);
+
+ return Err(self.error_form(err, stub));
+ }
+ }
+
+ string.push('.');
+
+ let mut stream = parsing_stream(std::io::Cursor::new(string));
+ let mut parser = Parser::new(&mut stream, indices.atom_tbl.clone(),
+ self.machine_flags());
+
+ match parser.read_term(composite_op!(&indices.op_dir)) {
+ Err(err) => {
+ let h = self.heap.h;
+ let err = MachineError::syntax_error(h, err);
+
+ return Err(self.error_form(err, stub));
+ },
+ Ok(Term::Constant(_, Constant::Number(n))) =>
+ self.unify(nx, Addr::Con(Constant::Number(n))),
+ Ok(Term::Constant(_, Constant::CharCode(c))) =>
+ self.unify(nx, Addr::Con(Constant::CharCode(c))),
+ _ => {
+ let err = ParserError::ParseBigInt;
+
+ let h = self.heap.h;
+ let err = MachineError::syntax_error(h, err);
+
+ return Err(self.error_form(err, stub));
+ }
+ }
+
+ Ok(())
+ }
+
pub(super) fn system_call(&mut self,
ct: &SystemClauseType,
indices: &mut IndexStore,
self.unify(a2, Addr::Con(Constant::Number(len)));
},
- &SystemClauseType::CharsToNumber => {
- let nx = self[temp_v!(2)].clone();
+ &SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
match self.try_from_list(temp_v!(1), stub.clone()) {
Err(e) => return Err(e),
Ok(addrs) =>
match self.try_char_list(addrs) {
- Ok(mut string) => {
- if let Some(c) = string.chars().last() {
- if layout_char!(c) {
- let err = ParserError::UnexpectedChar(c);
-
- let h = self.heap.h;
- let err = MachineError::syntax_error(h, err);
-
- return Err(self.error_form(err, stub));
- }
- }
-
- string.push('.');
-
- let mut stream = parsing_stream(std::io::Cursor::new(string));
- let mut parser = Parser::new(&mut stream, indices.atom_tbl.clone(),
- self.machine_flags());
-
- match parser.read_term(composite_op!(&indices.op_dir)) {
- Err(err) => {
- let h = self.heap.h;
- let err = MachineError::syntax_error(h, err);
-
- return Err(self.error_form(err, stub));
- },
- Ok(Term::Constant(_, Constant::Number(n))) =>
- self.unify(nx, Addr::Con(Constant::Number(n))),
- Ok(Term::Constant(_, Constant::CharCode(c))) =>
- self.unify(nx, Addr::Con(Constant::CharCode(c))),
- _ => {
- let err = ParserError::ParseBigInt;
-
- let h = self.heap.h;
- let err = MachineError::syntax_error(h, err);
-
- return Err(self.error_form(err, stub));
- }
- }
- },
+ Ok(string) =>
+ self.parse_number_from_string(string, indices, stub)?,
Err(err) =>
return Err(self.error_form(err, stub))
}
let char_list = Addr::HeapCell(self.heap.to_list(chars));
self.unify(char_list, chs);
+ },
+ &SystemClauseType::NumberToCodes => {
+ let n = self[temp_v!(1)].clone();
+ let chs = self[temp_v!(2)].clone();
+
+ let string = match self.store(self.deref(n)) {
+ Addr::Con(Constant::Number(Number::Float(OrderedFloat(n)))) =>
+ format!("{0:<20?}", n),
+ Addr::Con(Constant::Number(Number::Integer(n))) =>
+ n.to_string(),
+ _ => unreachable!()
+ };
+
+ let codes = string.trim().chars().map(|c| Addr::Con(Constant::CharCode(c as u8)));
+ let codes_list = Addr::HeapCell(self.heap.to_list(codes));
+
+ self.unify(codes_list, chs);
+ },
+ &SystemClauseType::CodesToNumber => {
+ let stub = MachineError::functor_stub(clause_name!("number_codes"), 2);
+
+ match self.try_from_list(temp_v!(1), stub.clone()) {
+ Err(e) => return Err(e),
+ Ok(addrs) =>
+ match self.try_code_list(addrs) {
+ Ok(codes) => {
+ let string = codes.iter().map(|c| *c as char).collect();
+ self.parse_number_from_string(string, indices, stub)?
+ },
+ Err(err) =>
+ return Err(self.error_form(err, stub))
+ }
+ }
},
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
let p = self.cp;
self.unify_with_occurs_check(a1, a2);
},
- &SystemClauseType::UnwindStack => self.unwind_stack(),
+ &SystemClauseType::UnwindStack =>
+ self.unwind_stack(),
+ &SystemClauseType::Variant =>
+ self.fail = self.structural_eq_test(),
&SystemClauseType::WriteTerm => {
let addr = self[temp_v!(1)].clone();
&CompareTermQT::GreaterThanOrEqual => write!(f, "@>="),
&CompareTermQT::LessThan => write!(f, "@<"),
&CompareTermQT::LessThanOrEqual => write!(f, "@<="),
- &CompareTermQT::NotEqual => write!(f, "\\=@="),
- &CompareTermQT::Equal => write!(f, "=@="),
}
}
}
assert_prolog_success!(&mut wam, "1.0 @=< 1.");
assert_prolog_success!(&mut wam, "1 @=< 1.0."); //TODO: currently this succeeds. make it fail.
- assert_prolog_success!(&mut wam, "X =@= Y.");
- assert_prolog_failure!(&mut wam, "f(X) =@= f(x).");
- assert_prolog_failure!(&mut wam, "X \\=@= X.");
- assert_prolog_success!(&mut wam, "f(x) =@= f(x).");
- assert_prolog_failure!(&mut wam, "[X,Y,Z] =@= [V,W,V].");
- assert_prolog_success!(&mut wam, "[X,Y,Z] =@= [V,W,Z].");
- assert_prolog_success!(&mut wam, "[X,Y,X] =@= [V,W,V].");
- assert_prolog_success!(&mut wam, "g(B) = B,g(A) = A,A =@= B.");
+ submit(&mut wam, ":- use_module(library(non_iso)).");
+
+ assert_prolog_success!(&mut wam, "variant(X, Y).");
+ assert_prolog_failure!(&mut wam, "variant(f(X), f(x)).");
+ assert_prolog_success!(&mut wam, "variant(X, X).");
+ assert_prolog_success!(&mut wam, "variant(f(x), f(x)).");
+ assert_prolog_failure!(&mut wam, "variant([X,Y,Z], [V,W,V]).");
+ assert_prolog_success!(&mut wam, "variant([X,Y,Z], [V,W,Z]).");
+ assert_prolog_success!(&mut wam, "variant([X,Y,X], [V,W,V]).");
+ assert_prolog_success!(&mut wam, "g(B) = B, g(A) = A, variant(A, B).");
assert_prolog_success!(&mut wam, "keysort([1-1,1-1],Sorted).",
[["Sorted = [1-1,1-1]"]]);
{
let mut wam = Machine::new(readline::input_stream());
+ submit(&mut wam, ":- use_module(library(non_iso)).");
+
// double_quotes is chars by default.
- assert_prolog_success!(&mut wam, "\"\" =@= [].");
+ assert_prolog_success!(&mut wam, "variant(\"\", []).");
assert_prolog_failure!(&mut wam, "\"\" == [].");
assert_prolog_failure!(&mut wam, "\"abc\" == [].");
- assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', 'b', 'c'].");
- assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', 'b', c].");
- assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', b, 'c'].");
- assert_prolog_success!(&mut wam, "\"abc\" =@= [a, 'b', 'c'].");
- assert_prolog_success!(&mut wam, "\"abc\" =@= [a, 'b', c].");
+ assert_prolog_success!(&mut wam, "variant(\"abc\", ['a', 'b', 'c']).");
+ assert_prolog_success!(&mut wam, "variant(\"abc\", ['a', 'b', c]).");
+ assert_prolog_success!(&mut wam, "variant(\"abc\", ['a', b, 'c']).");
+ assert_prolog_success!(&mut wam, "variant(\"abc\", [a, 'b', 'c']).");
+ assert_prolog_success!(&mut wam, "variant(\"abc\", [a, 'b', c]).");
assert_prolog_failure!(&mut wam, "\"abc\" == ['a', 'b', 'c'].");
assert_prolog_failure!(&mut wam, "\"abc\" == ['a', 'b', c].");
assert_prolog_failure!(&mut wam, "\"abc\" == ['a', b, 'c'].");
assert_prolog_failure!(&mut wam, "\"abc\" == [a, 'b', c].");
assert_prolog_failure!(&mut wam, "\"koen\" == [k, o, e, n].");
assert_prolog_success!(&mut wam, "\"koen\" = [k, o, e, n].");
- assert_prolog_success!(&mut wam, "\"koen\" =@= [k, o, e, n].");
- assert_prolog_success!(&mut wam, "\"koen\" =@= \"koen\".");
+ assert_prolog_success!(&mut wam, "variant(\"koen\", [k, o, e, n]).");
+ assert_prolog_success!(&mut wam, "variant(\"koen\", \"koen\").");
assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X].",
[["X = [e,n]"]]);
assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X], X = \"en\".",
[["X = [e,n]"]]);
assert_prolog_failure!(&mut wam, "\"koen\" = [k, o | X], X == \"en\".");
- assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X], X =@= \"en\".",
+ assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X], variant(X, \"en\").",
[["X = [e,n]"]]);
assert_prolog_failure!(&mut wam, "X = \"abc\", Y = \"abc\", X == Y.");
assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), X == Y.");
- assert_prolog_success!(&mut wam, "X = \"abc\", Y = \"abc\", X =@= Y.");
- assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), X =@= Y.");
+ assert_prolog_success!(&mut wam, "X = \"abc\", Y = \"abc\", variant(X, Y).");
+ assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), variant(X, Y).");
submit(&mut wam, "matcher([a,b,c|X], ['d','e','f'|X]).");
submit(&mut wam, "matcher([a,b,c|X], X).");
- assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X = \"def\".",
+ assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], variant(Y, []), X = \"def\".",
[["X = [d,e,f]", "Y = []"]]);
- assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X =@= \"def\".",
+ assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], variant(Y, []), variant(X, \"def\").",
[["X = [d,e,f]", "Y = []"]]);
assert_prolog_success!(&mut wam, "X = ['a', 'b', 'c' | \"def\"].",
[["X = [a,b,c,d,e,f]"]]);
is_partial_string(Y),is_partial_string(G),G = \"ghi\".",
[["X = [a,b,c,d,e,f,g,h,i]","Y = [d,e,f,g,h,i]","G = [g,h,i]"]]);
assert_prolog_success!(&mut wam, "partial_string(\"abc\",X),partial_string(\"ababc\",Y),Y = [a,b|Z],
- X =@= Z.",
+ variant(X, Z).",
[["X = [a,b,c|_]","Y = [a,b,a,b,c|_]","Z = [a,b,c|_]"]]);
assert_prolog_failure!(&mut wam, "partial_string(\"abc\",X),partial_string(\"ababc\",Y),Y = [a,b|Z],
- X == Z.");
+ X == Z.");
- assert_prolog_success!(&mut wam, "partial_string(\"abc\",X),X @> \"abc\".");
- assert_prolog_failure!(&mut wam, "partial_string(\"abc\",X),X \\=@= \"abc\".");
- assert_prolog_failure!(&mut wam, "partial_string(\"abc\",X),X @< \"abc\".");
+ assert_prolog_success!(&mut wam, "partial_string(\"abc\",X), X @> \"abc\".");
+ assert_prolog_failure!(&mut wam, "partial_string(\"abc\",X), \\+ variant(X, \"abc\").");
+ assert_prolog_failure!(&mut wam, "partial_string(\"abc\",X), X @< \"abc\".");
assert_prolog_success!(&mut wam, "partial_string(\"ab\",X),matcher(X,Y),Y = [a,b|V],
matcher(Y,Z),is_partial_string(Y).",