]> Repositorios git - scryer-prolog.git/commitdiff
fix compile_seq, variable printing on standalone inlines.
authorMark Thom <[email protected]>
Sat, 17 Feb 2018 05:18:17 +0000 (22:18 -0700)
committerMark Thom <[email protected]>
Sat, 17 Feb 2018 05:18:17 +0000 (22:18 -0700)
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/io.rs
src/prolog/lib/lists.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/macros.rs
src/tests.rs

index a66245925a908dd4be4e89dc36a4df1f7e66d73c..6be24510d9a2937809f17e8ddf070669a530a3d5 100644 (file)
@@ -874,6 +874,8 @@ pub enum ArithmeticInstruction {
 
 pub enum BuiltInInstruction {
     CleanUpBlock,
+    CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
+    DynamicCompareNumber(CompareNumberQT),
     EraseBall,
     Fail,
     GetArgCall,
@@ -884,6 +886,14 @@ pub enum BuiltInInstruction {
     InstallCleaner,
     InstallNewBlock,
     InternalCallN,
+    IsAtomic(RegType),
+    IsCompound(RegType),
+    IsFloat(RegType),
+    IsInteger(RegType),
+    IsNonVar(RegType),
+    IsRational(RegType),
+    IsString(RegType),
+    IsVar(RegType),
     ResetBlock,
     RestoreCutPolicy,
     SetBall,
@@ -902,16 +912,14 @@ pub enum ControlInstruction {
     CallN(usize), // arity.
     CatchCall,
     CatchExecute,
-    CheckCpExecute,
-    CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
+    CheckCpExecute,    
     CompareTermCall(CompareTermQT),
     CompareTermExecute(CompareTermQT),
     DisplayCall,
     DisplayExecute,
     Deallocate,
     DuplicateTermCall,
-    DuplicateTermExecute,
-    DynamicCompareNumber(CompareNumberQT),
+    DuplicateTermExecute,    
     DynamicIs,
     EqCall,
     EqExecute,
@@ -926,15 +934,7 @@ pub enum ControlInstruction {
     GroundExecute,
     JmpByCall(usize, usize),    // arity, global_offset.
     JmpByExecute(usize, usize),
-    IsCall(RegType, ArithmeticTerm),
-    IsAtomic(RegType),
-    IsCompound(RegType),
-    IsFloat(RegType),
-    IsInteger(RegType),
-    IsNonVar(RegType),
-    IsRational(RegType),
-    IsString(RegType),
-    IsVar(RegType),
+    IsCall(RegType, ArithmeticTerm),    
     IsExecute(RegType, ArithmeticTerm),
     NotEqCall,
     NotEqExecute,
@@ -950,15 +950,13 @@ impl ControlInstruction {
             &ControlInstruction::ArgExecute => true,
             &ControlInstruction::Call(_, _, _)  => true,
             &ControlInstruction::CatchCall => true,
-            &ControlInstruction::CatchExecute => true,
-            &ControlInstruction::CompareNumber(..) => true,
+            &ControlInstruction::CatchExecute => true,            
             &ControlInstruction::CompareTermCall(..) => true,
             &ControlInstruction::CompareTermExecute(..) => true,
             &ControlInstruction::DisplayCall => true,
             &ControlInstruction::DisplayExecute => true,
             &ControlInstruction::DuplicateTermCall => true,
             &ControlInstruction::DuplicateTermExecute => true,
-            &ControlInstruction::DynamicCompareNumber(_) => true,
             &ControlInstruction::DynamicIs => true,
             &ControlInstruction::EqCall => true,
             &ControlInstruction::EqExecute => true,
@@ -976,14 +974,6 @@ impl ControlInstruction {
             &ControlInstruction::GotoExecute(..) => true,
             &ControlInstruction::GroundCall => true,
             &ControlInstruction::GroundExecute => true,
-            &ControlInstruction::IsAtomic(_) => true,
-            &ControlInstruction::IsCompound(_) => true,
-            &ControlInstruction::IsFloat(_) => true,
-            &ControlInstruction::IsInteger(_) => true,
-            &ControlInstruction::IsNonVar(_) => true,
-            &ControlInstruction::IsRational(_) => true,
-            &ControlInstruction::IsString(_) => true,
-            &ControlInstruction::IsVar(_) => true,
             &ControlInstruction::IsCall(..) => true,
             &ControlInstruction::IsExecute(..) => true,
             &ControlInstruction::JmpByCall(..) => true,
index a6c6b673f7a097d342b816d7229dcd57363dae35..3e365d868441d8038d89f5d635513d792f57654f 100644 (file)
@@ -483,13 +483,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                 };
 
                 match *term {
-                    &QueryTerm::Cut => {
+                    &QueryTerm::Cut =>
                         code.push(if chunk_num == 0 {
                             Line::Cut(CutInstruction::NeckCut)
                         } else {
                             Line::Cut(CutInstruction::Cut(perm_v!(1)))
-                        });
-                    },
+                        }),                    
                     &QueryTerm::Is(ref terms) => {
                         let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
                         code.append(&mut acode);
@@ -520,7 +519,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         }
                     },
                     &QueryTerm::Inlined(ref term) =>
-                        self.compile_inlined(term, term_loc, code)?,
+                        try!(self.compile_inlined(term, term_loc, code)),
                     _ => {
                         let num_perm_vars = if chunk_num == 0 {
                             conjunct_info.perm_vars()
@@ -530,10 +529,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
                         self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
                     },
-                };
-
-                self.marker.reset_contents();
+                };                
             }
+
+            self.marker.reset_contents();
         }
 
         Ok(())
index 43dbf582e10d7bfe8e469c4e6a6d59425aeced4c..741397b2213bf4233a8c6d1b5fbe78317c314f30 100644 (file)
@@ -168,25 +168,9 @@ impl fmt::Display for ControlInstruction {
             &ControlInstruction::IsCall(r, ref at) =>
                 write!(f, "is_call {}, {}", r, at),
             &ControlInstruction::IsExecute(r, ref at) =>
-                write!(f, "is_execute {}, {}", r, at),
-            &ControlInstruction::IsAtomic(r) =>
-                write!(f, "is_atomic {}", r),
-            &ControlInstruction::IsCompound(r) =>
-                write!(f, "is_compound {}", r),
-            &ControlInstruction::IsFloat(r) =>
-                write!(f, "is_float {}", r),
-            &ControlInstruction::IsRational(r) =>
-                write!(f, "is_rational {}", r),
-            &ControlInstruction::IsNonVar(r) =>
-                write!(f, "is_non_var {}", r),
-            &ControlInstruction::IsString(r) =>
-                write!(f, "is_string {}", r),
-            &ControlInstruction::IsInteger(r) =>
-                write!(f, "is_integer {}", r),
+                write!(f, "is_execute {}, {}", r, at),            
             &ControlInstruction::DynamicIs =>
-                write!(f, "call_is"),
-            &ControlInstruction::IsVar(r) =>
-                write!(f, "is_var {}", r),
+                write!(f, "call_is"),            
             &ControlInstruction::JmpByCall(arity, offset) =>
                 write!(f, "jmp_by_call {}/{}", offset, arity),
             &ControlInstruction::JmpByExecute(arity, offset) =>
@@ -200,11 +184,7 @@ impl fmt::Display for ControlInstruction {
             &ControlInstruction::ThrowCall =>
                 write!(f, "call_throw"),
             &ControlInstruction::ThrowExecute =>
-                write!(f, "execute_throw"),
-            &ControlInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
-                write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
-            &ControlInstruction::DynamicCompareNumber(cmp) =>
-                write!(f, "dynamic_number_test {}", cmp),
+                write!(f, "execute_throw"),            
         }
     }
 }
@@ -226,7 +206,7 @@ impl fmt::Display for BuiltInInstruction {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             &BuiltInInstruction::CleanUpBlock =>
-                write!(f, "clean_up_block"),            
+                write!(f, "clean_up_block"),
             &BuiltInInstruction::EraseBall =>
                 write!(f, "erase_ball"),
             &BuiltInInstruction::Fail =>
@@ -246,7 +226,7 @@ impl fmt::Display for BuiltInInstruction {
             &BuiltInInstruction::InstallNewBlock =>
                 write!(f, "install_new_block"),
             &BuiltInInstruction::InternalCallN =>
-                write!(f, "internal_call_N"),            
+                write!(f, "internal_call_N"),
             &BuiltInInstruction::ResetBlock =>
                 write!(f, "reset_block"),
             &BuiltInInstruction::RestoreCutPolicy =>
@@ -261,6 +241,26 @@ impl fmt::Display for BuiltInInstruction {
                 write!(f, "unwind_stack"),
             &BuiltInInstruction::Unify =>
                 write!(f, "unify"),
+            &BuiltInInstruction::IsAtomic(r) =>
+                write!(f, "is_atomic {}", r),
+            &BuiltInInstruction::IsCompound(r) =>
+                write!(f, "is_compound {}", r),
+            &BuiltInInstruction::IsFloat(r) =>
+                write!(f, "is_float {}", r),
+            &BuiltInInstruction::IsRational(r) =>
+                write!(f, "is_rational {}", r),
+            &BuiltInInstruction::IsNonVar(r) =>
+                write!(f, "is_non_var {}", r),
+            &BuiltInInstruction::IsString(r) =>
+                write!(f, "is_string {}", r),
+            &BuiltInInstruction::IsInteger(r) =>
+                write!(f, "is_integer {}", r),
+            &BuiltInInstruction::IsVar(r) =>
+                write!(f, "is_var {}", r),
+            &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
+                write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
+            &BuiltInInstruction::DynamicCompareNumber(cmp) =>
+                write!(f, "dynamic_number_test {}", cmp),
         }
     }
 }
index a584848ab8ebbabdc28d185298f6b4aef0f922d3..0e0df5f0e14bb5242e9a7566abcc683ae7145a6d 100644 (file)
@@ -9,7 +9,8 @@ pub static LISTS: &str = "member(X, [X|_]).
 
                           memberchk(X, Xs) :- member(X, Xs), !.
 
-                          reverse(Xs, Ys) :- reverse(Xs, [], Ys).
+                          reverse(Xs, Ys) :- var(Ys), !, reverse(Xs, [], Ys).
+                          reverse(Ys, Xs) :- var(Ys), reverse(Xs, [], Ys).
 
                           reverse([], Ys, Ys).
                           reverse([H|T], Ps, Rs) :-
index 0e797f4c8ce0f9c2302f1cb7912a11c4e1bdb90e..d1985494f58378d55d13a1604f831d816aba17da 100644 (file)
@@ -1270,6 +1270,18 @@ impl MachineState {
                                          instr: &BuiltInInstruction)
     {
         match instr {
+            &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => {
+                let n1 = try_or_fail!(self, self.get_number(at_1));
+                let n2 = try_or_fail!(self, self.get_number(at_2));
+
+                self.compare_numbers(cmp, n1, n2);
+            },
+            &BuiltInInstruction::DynamicCompareNumber(cmp) => {
+                let n1 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(1)));
+                let n2 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2)));
+
+                self.compare_numbers(cmp, n1, n2);
+            },
             &BuiltInInstruction::GetArgCall =>
                 try_or_fail!(self, {
                     let val = self.try_get_arg();
@@ -1339,6 +1351,70 @@ SetupCallCleanupCutPolicy.")
 
                 self.p += 1;
             },
+            &BuiltInInstruction::IsAtomic(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Con(_) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsInteger(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Con(Constant::Number(Number::Integer(_))) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsCompound(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Str(_) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsFloat(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Con(Constant::Number(Number::Float(_))) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsRational(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Con(Constant::Number(Number::Rational(_))) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsString(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::Con(Constant::String(_)) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
+            &BuiltInInstruction::IsNonVar(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::HeapCell(_) | Addr::StackCell(..) => self.fail = true,
+                    _ => self.p += 1
+                };
+            },
+            &BuiltInInstruction::IsVar(r) => {
+                let d = self.store(self.deref(self[r].clone()));
+
+                match d {
+                    Addr::HeapCell(_) | Addr::StackCell(_,_) => self.p += 1,
+                    _ => self.fail = true
+                };
+            },
             &BuiltInInstruction::RestoreCutPolicy => {
                 let restore_default =
                     if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() {
@@ -1737,19 +1813,7 @@ SetupCallCleanupCutPolicy.")
             &ControlInstruction::DuplicateTermExecute => {
                 self.duplicate_term();
                 self.p = self.cp;
-            },
-            &ControlInstruction::CompareNumber(cmp, ref at_1, ref at_2) => {
-                let n1 = try_or_fail!(self, self.get_number(at_1));
-                let n2 = try_or_fail!(self, self.get_number(at_2));
-
-                self.compare_numbers(cmp, n1, n2);
-            },
-            &ControlInstruction::DynamicCompareNumber(cmp) => {
-                let n1 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(1)));
-                let n2 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2)));
-
-                self.compare_numbers(cmp, n1, n2);
-            },
+            },            
             &ControlInstruction::DynamicIs => {
                 let a = self[temp_v!(1)].clone();
                 let result = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2)));
@@ -1757,70 +1821,6 @@ SetupCallCleanupCutPolicy.")
                 self.unify(a, Addr::Con(Constant::Number(result)));
                 self.p += 1;
             },
-            &ControlInstruction::IsAtomic(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Con(_) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsInteger(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Con(Constant::Number(Number::Integer(_))) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsCompound(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Str(_) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsFloat(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Con(Constant::Number(Number::Float(_))) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsRational(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Con(Constant::Number(Number::Rational(_))) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsString(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::Con(Constant::String(_)) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
-            &ControlInstruction::IsNonVar(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::HeapCell(_) | Addr::StackCell(..) => self.fail = true,
-                    _ => self.p += 1
-                };
-            },
-            &ControlInstruction::IsVar(r) => {
-                let d = self.store(self.deref(self[r].clone()));
-
-                match d {
-                    Addr::HeapCell(_) | Addr::StackCell(_,_) => self.p += 1,
-                    _ => self.fail = true
-                };
-            },
             &ControlInstruction::EqCall => {
                 self.fail = self.eq_test();
                 self.p += 1;
index e3a44b808ead710c99e7cfb3da5c3a3c08eb8f41..9ac9d915a85b24cfbd0594f18fd939efee53f129 100644 (file)
@@ -46,8 +46,8 @@ impl Machine {
     pub fn new() -> Self {
         let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
         let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
-        
-        
+
+
         Machine {
             ms: MachineState::new(atom_tbl),
             cut_policy: Box::new(DefaultCutPolicy {}),
@@ -121,7 +121,7 @@ impl Machine {
 
                     self.ms.execute_fact_instr(&fact_instr);
                 }
+
                 self.ms.p += 1;
             },
             &Line::Indexing(ref indexing_instr) =>
@@ -194,9 +194,11 @@ impl Machine {
                 },
                 &VarData::Temp(cn, _, _) if cn == chunk_num => {
                     let r = var_data.as_reg_type();
-                    let addr = self.ms[r].clone();
-
-                    heap_locs.insert(var, addr);
+                    
+                    if r.reg_num() != 0 {
+                        let addr = self.ms[r].clone();
+                        heap_locs.insert(var, addr);
+                    }
                 },
                 _ => {}
             }
@@ -205,8 +207,8 @@ impl Machine {
 
     fn run_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
     {
-        let end_ptr = CodePtr::TopLevel(0, self.cached_query_size());
-
+        let end_ptr = CodePtr::TopLevel(0, self.cached_query_size());        
+        
         while self.ms.p < end_ptr {
             if let CodePtr::TopLevel(mut cn, p) = self.ms.p {
                 match &self[CodePtr::TopLevel(cn, p)] {
@@ -224,7 +226,13 @@ impl Machine {
 
             match self.ms.p {
                 CodePtr::TopLevel(_, p) if p > 0 => {},
-                _ => break
+                _ => {
+                    if heap_locs.is_empty() {
+                        self.record_var_places(0, alloc_locs, heap_locs);
+                    }
+                    
+                    break;
+                }
             };
         }
     }
index 2d892915a6befb555a75c03fcf6a3244b5d5b834..d4291667f98e89cdf28afc916c7ed4cc5b047de1 100644 (file)
@@ -30,7 +30,7 @@ macro_rules! deallocate {
 
 macro_rules! compare_number_instr {
     ($cmp: expr, $at_1: expr, $at_2: expr) => (
-        Line::Control(ControlInstruction::CompareNumber($cmp, $at_1, $at_2))
+        Line::BuiltIn(BuiltInInstruction::CompareNumber($cmp, $at_1, $at_2))
     )
 }
 
@@ -158,50 +158,50 @@ macro_rules! retry_me_else {
 
 macro_rules! is_atomic {
     ($reg:expr) => (
-        Line::Control(ControlInstruction::IsAtomic($reg))
+        Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
     )
 }
 
 macro_rules! is_integer {
     ($reg:expr) => (
-        Line::Control(ControlInstruction::IsInteger($reg))
+        Line::BuiltIn(BuiltInInstruction::IsInteger($reg))
     )
 }
 
 macro_rules! is_compound {
     ($r:expr) => (
-        Line::Control(ControlInstruction::IsCompound($r))
+        Line::BuiltIn(BuiltInInstruction::IsCompound($r))
     )
 }
 
 macro_rules! is_float {
     ($r:expr) => (
-        Line::Control(ControlInstruction::IsFloat($r))
+        Line::BuiltIn(BuiltInInstruction::IsFloat($r))
     )
 }
 
 macro_rules! is_rational {
     ($r:expr) => (
-        Line::Control(ControlInstruction::IsRational($r))
+        Line::BuiltIn(BuiltInInstruction::IsRational($r))
     )
 }
 
 
 macro_rules! is_nonvar {
     ($r:expr) => (
-        Line::Control(ControlInstruction::IsNonVar($r))
+        Line::BuiltIn(BuiltInInstruction::IsNonVar($r))
     )
 }
 
 macro_rules! is_string {
     ($r:expr) => (
-        Line::Control(ControlInstruction::IsString($r))
+        Line::BuiltIn(BuiltInInstruction::IsString($r))
     )
 }
 
 macro_rules! is_var {
     ($reg:expr) => (
-        Line::Control(ControlInstruction::IsVar($reg))
+        Line::BuiltIn(BuiltInInstruction::IsVar($reg))
     )
 }
 
@@ -475,7 +475,7 @@ macro_rules! dynamic_is {
 
 macro_rules! dynamic_num_test {
     ($cmp:expr) => (
-        Line::Control(ControlInstruction::DynamicCompareNumber($cmp))
+        Line::BuiltIn(BuiltInInstruction::DynamicCompareNumber($cmp))
     )
 }
 
index 9c1898c41309bb22bce92402eb34b7a1959b42b6..76a90ddd649b49d62f5e9a39d6967f8619e9ae12 100644 (file)
@@ -1302,6 +1302,7 @@ fn test_queries_on_builtins()
 
     assert_prolog_success!(&mut wam, "?- X is 3 rdiv 4, rational(X).");
     assert_prolog_failure!(&mut wam, "?- rational(3).");
+    assert_prolog_failure!(&mut wam, "?- rational(f(X)).");
     assert_prolog_failure!(&mut wam, "?- rational(\"sdfsa\").");
     assert_prolog_failure!(&mut wam, "?- rational(atom).");
     assert_prolog_failure!(&mut wam, "?- rational(structure(functor)).");
@@ -1309,6 +1310,7 @@ fn test_queries_on_builtins()
     assert_prolog_failure!(&mut wam, "?- rational([1,2,X]).");
 
     assert_prolog_success!(&mut wam, "?- compound(functor(compound)).");
+    assert_prolog_success!(&mut wam, "?- compound(f(X)).");
     assert_prolog_failure!(&mut wam, "?- compound(3.14159269).");
     assert_prolog_failure!(&mut wam, "?- compound(3).");
     assert_prolog_failure!(&mut wam, "?- compound(\"sdfsa\").");
@@ -1319,6 +1321,7 @@ fn test_queries_on_builtins()
     assert_prolog_failure!(&mut wam, "?- string(functor(string)).");
     assert_prolog_failure!(&mut wam, "?- string(3.14159269).");
     assert_prolog_failure!(&mut wam, "?- string(3).");
+    assert_prolog_failure!(&mut wam, "?- string(f(X)).");
     assert_prolog_success!(&mut wam, "?- string(\"sdfsa\").");
     assert_prolog_failure!(&mut wam, "?- string(atom).");
     assert_prolog_failure!(&mut wam, "?- string([1,2,3]).");
@@ -1326,6 +1329,7 @@ fn test_queries_on_builtins()
     
     assert_prolog_success!(&mut wam, "?- X = nonvar, nonvar(X).");
     assert_prolog_failure!(&mut wam, "?- nonvar(X).");
+    assert_prolog_success!(&mut wam, "?- nonvar(f(X)).");
     assert_prolog_success!(&mut wam, "?- nonvar(functor(nonvar)).");
     assert_prolog_success!(&mut wam, "?- nonvar(3.14159269).");
     assert_prolog_success!(&mut wam, "?- nonvar(3).");