]> Repositorios git - scryer-prolog.git/commitdiff
add remaining atomic term processing builtins, rename (=@=)/2 to variant/2, address...
authorMark Thom <[email protected]>
Wed, 1 May 2019 02:55:53 +0000 (20:55 -0600)
committerMark Thom <[email protected]>
Wed, 1 May 2019 02:55:53 +0000 (20:55 -0600)
Cargo.toml
README.md
src/prolog/clause_types.rs
src/prolog/indexing.rs
src/prolog/lib/builtins.pl
src/prolog/lib/non_iso.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/system_calls.rs
src/prolog/write.rs
src/tests.rs

index baafadc63b1d2e0b0f3cf79eb90d423f2eb09e0d..7d570da416a5e25c0192f98cba16e1f6453ac051 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.76"
+version = "0.8.77"
 authors = ["Mark Thom <[email protected]>"]
 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.24"
+prolog_parser = "0.8.26"
 readline_rs_compat = { version = "0.1.9", optional = true }
 ref_thread_local = "0.0.0"
 
index 7c607860700cb64cf477fbc7296862aa66012946..0faa4411db239072fc126c40a003cb0f995f31c4 100644 (file)
--- a/README.md
+++ b/README.md
@@ -141,8 +141,6 @@ The following predicates are built-in to Scryer.
 * `(@>=)/2`
 * `(@=<)/2`
 * `(@<)/2`
-* `(=@=)/2`
-* `(\=@=)/2`
 * `(\+)/1`
 * `(==)/2`
 * `(\==)/2`
@@ -232,6 +230,7 @@ The following predicates are built-in to Scryer.
 * `user:goal_expansion/2`
 * `user:term_expansion/2`
 * `var/1`
+* `variant/2`
 * `write/1`
 * `write_canonical/1`
 * `writeq/1`
index 5a88745ef2f1ff108d65f71ee9361ef26d929f31..f5c504df1279d37f210daa189f928367ae6060e8 100644 (file)
@@ -33,10 +33,8 @@ impl CompareNumberQT {
 pub enum CompareTermQT {
     LessThan,
     LessThanOrEqual,
-    Equal,
     GreaterThanOrEqual,
     GreaterThan,
-    NotEqual,
 }
 
 impl CompareTermQT {
@@ -46,8 +44,6 @@ impl CompareTermQT {
             CompareTermQT::LessThan => "@<",
             CompareTermQT::GreaterThanOrEqual => "@>=",
             CompareTermQT::LessThanOrEqual => "@=<",
-            CompareTermQT::NotEqual => "\\=@=",
-            CompareTermQT::Equal => "=@="
         }
     }
 }
@@ -116,8 +112,6 @@ ref_thread_local! {
         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));
@@ -166,6 +160,7 @@ pub enum SystemClauseType {
     ModuleAssertDynamicPredicateToBack,
     CharCode,
     CharsToNumber,
+    CodesToNumber,
     CheckCutPoint,
     CopyToLiftedHeap,
     DeleteAttribute,
@@ -202,6 +197,7 @@ pub enum SystemClauseType {
     ModuleRetractClause,
     NoSuchPredicate,
     NumberToChars,
+    NumberToCodes,
     OpDeclaration,
     REPL(REPLCodePtr),
     ReadTerm,
@@ -233,7 +229,8 @@ pub enum SystemClauseType {
     TermVariables,
     TruncateLiftedHeapTo,
     UnifyWithOccursCheck,
-    UnwindStack,    
+    UnwindStack,
+    Variant,
     WriteTerm
 }
 
@@ -251,6 +248,7 @@ impl SystemClauseType {
             &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) =>
@@ -291,6 +289,7 @@ impl SystemClauseType {
             &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"),
@@ -321,6 +320,7 @@ impl SystemClauseType {
             &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"),
         }
     }
@@ -338,6 +338,7 @@ impl SystemClauseType {
             ("$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),
@@ -374,6 +375,7 @@ impl SystemClauseType {
             ("$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),
@@ -407,6 +409,7 @@ impl SystemClauseType {
             ("$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
         }
index 128b40d695a0cb1b14857a6599557a182c771ff4..4cba9d1353f787f48d54b1cdc3f9d3387af883ba 100644 (file)
@@ -59,7 +59,7 @@ impl CodeOffsets {
                 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));
                 },
index c9b89016b0d4a1d8a1cc0c42c57417b904df199b..f1f986bf6bc54339a238b08309d3912d6877d7ba 100644 (file)
        (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, :).
@@ -45,7 +45,7 @@ expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResu
 :- 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).
@@ -356,7 +356,7 @@ set_difference([], _, []) :- !.
 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]) :-
@@ -762,6 +762,48 @@ atom_codes(Atom, List) :-
     ;  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))
@@ -840,6 +882,21 @@ number_chars(N, Chs) :-
       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),
index f23c2d8e6dea8cfadddfe12904b0a602f5583ecb..9d4367fbb674928dcf7274e3e2264e61c8581691 100644 (file)
@@ -5,7 +5,7 @@
 
 :- 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).
@@ -110,3 +110,5 @@ call_with_inference_limit(_, _, R, Bb, B) :-
     ; '$remove_call_policy_check'(B), '$fail' ),
     '$erase_ball',
     '$call_with_default_policy'(handle_ile(B, Ball, R)).
+
+variant(X, Y) :- '$variant'(X, Y).
index 3994787c90b565716cfa1f0025d15a4dc187dc75..50eb4c11f6481a999718c94c637c3e5abb3144a2 100644 (file)
@@ -11,7 +11,7 @@ use prolog::machine::machine_errors::*;
 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;
@@ -244,7 +244,7 @@ impl MachineState {
     {
         let mut chars = String::new();
         let mut iter = addrs.iter();
-        
+
         while let Some(addr) = iter.next() {
             match addr {
                 &Addr::Con(Constant::String(ref s))
@@ -269,6 +269,38 @@ impl MachineState {
         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);
@@ -596,14 +628,7 @@ pub(crate) trait CallPolicy: Any {
                 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 => {
index 1b206b1a7ec36577ee2a1d3bd66bb0b02c6d4754..bab156b4d1903a6e6ae186777d27975652869d2c 100644 (file)
@@ -1815,11 +1815,15 @@ impl MachineState {
                             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()))
                                 };
@@ -2228,7 +2232,7 @@ impl MachineState {
             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)
                 },
@@ -2362,7 +2366,7 @@ impl MachineState {
                                     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;
                                     },
@@ -2382,7 +2386,7 @@ impl MachineState {
 
                 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)),
index f52a15e5e3ce8427b9279caf42a6b8fb6a0db7c6..8230950c746efa534040b0e531dea641549d3ee1 100644 (file)
@@ -80,7 +80,7 @@ impl MachineState {
             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
         };
@@ -105,7 +105,7 @@ impl MachineState {
             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
         };
@@ -158,7 +158,7 @@ impl MachineState {
                                 };
 
                             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))
@@ -352,6 +352,52 @@ impl MachineState {
         }
     }
 
+    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,
@@ -509,53 +555,15 @@ impl MachineState {
 
                 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))
                         }
@@ -577,6 +585,39 @@ impl MachineState {
                 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;
@@ -1600,7 +1641,10 @@ impl MachineState {
 
                 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();
 
index 7a4f193c8ffbf9347deb21f7bc0537674daf711b..6a357ea37fb1287a57b9e2414daca78ed2371b72 100644 (file)
@@ -127,8 +127,6 @@ impl fmt::Display for CompareTermQT {
             &CompareTermQT::GreaterThanOrEqual => write!(f, "@>="),
             &CompareTermQT::LessThan => write!(f, "@<"),
             &CompareTermQT::LessThanOrEqual => write!(f, "@<="),
-            &CompareTermQT::NotEqual => write!(f, "\\=@="),
-            &CompareTermQT::Equal => write!(f, "=@="),
         }
     }
 }
index 03134dc550a758b2e26500583ee4c14164cd433a..338ff52850f7f84da61422af78a75b58b5093d1e 100644 (file)
@@ -1620,14 +1620,16 @@ fn test_queries_on_builtins()
     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]"]]);
@@ -2193,15 +2195,17 @@ fn test_queries_on_string_lists()
 {
     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'].");
@@ -2209,21 +2213,21 @@ fn test_queries_on_string_lists()
     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]).");
 
@@ -2236,9 +2240,9 @@ fn test_queries_on_string_lists()
 
     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]"]]);
@@ -2301,14 +2305,14 @@ fn test_queries_on_string_lists()
                                          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).",