]> Repositorios git - scryer-prolog.git/commitdiff
perform singleton variable scans on top level terms only
authorMark Thom <[email protected]>
Fri, 4 Oct 2019 16:38:45 +0000 (10:38 -0600)
committerMark Thom <[email protected]>
Fri, 4 Oct 2019 16:38:45 +0000 (10:38 -0600)
Cargo.toml
src/prolog/forms.rs
src/prolog/machine/compile.rs
src/prolog/machine/term_expansion.rs

index 8a31692a6bbcec14edc8e343c7dc34a9f9a78767..936e91ea0fea2c2f742d8209030a1642eee2fc34 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.99"
+version = "0.8.100"
 authors = ["Mark Thom <[email protected]>"]
 build = "build.rs"
 repository = "https://github.com/mthom/scryer-prolog"
index f6b9e25f58932675e46f73ed141bb2a233b6c9c2..38904435f017cb6865699d3d07db0d681855209c 100644 (file)
@@ -3,7 +3,6 @@ use prolog_parser::parser::OpDesc;
 use prolog_parser::tabled_rc::*;
 
 use prolog::clause_types::*;
-use prolog::iterators::*;
 use prolog::machine::machine_errors::*;
 use prolog::machine::machine_indices::*;
 use prolog::ordered_float::OrderedFloat;
@@ -59,40 +58,6 @@ impl TopLevel {
             _ => false,
         }
     }
-
-    pub fn location(&self) -> Option<(usize, usize)> {
-        match self {
-            &TopLevel::Fact(_, line_num, col_num) | &TopLevel::Rule(_, line_num, col_num) =>
-                Some((line_num, col_num)),
-            &TopLevel::Predicate(Predicate(ref clauses)) =>
-                clauses.first().map(|clause| (clause.line_num(), clause.col_num())),
-            _ =>
-                None
-        }
-    }
-    
-    pub fn var_count(&self) -> Option<Vec<IndexMap<Rc<Var>, usize>>> {
-        match self {
-            &TopLevel::Fact(ref term, ..) => {
-                let mut var_count = IndexMap::new();
-                
-                for term_ref in breadth_first_iter(term, true) {
-                    if let TermRef::Var(_, _, var) = term_ref {
-                        let entry = var_count.entry(var).or_insert(0);
-                        *entry += 1;
-                    }
-                }
-
-                Some(vec![var_count])
-            }
-            &TopLevel::Rule(ref rule, ..) =>
-                Some(vec![rule.var_count()]),
-            &TopLevel::Predicate(ref predicate) =>
-                Some(predicate.var_count()),
-            _ =>
-                None
-        }
-    }
 }
 
 #[derive(Clone, Copy)]
@@ -145,40 +110,6 @@ pub struct Rule {
     pub clauses: Vec<QueryTerm>,
 }
 
-impl Rule {
-    pub fn var_count(&self) -> IndexMap<Rc<Var>, usize> {
-        let mut var_count = IndexMap::new();
-
-        for root_term in &self.head.1 {
-            // true because the root term is iterable.
-            for term_ref in breadth_first_iter(root_term, true) {
-                if let TermRef::Var(_, _, var) = term_ref {
-                    let entry = var_count.entry(var).or_insert(0);
-                    *entry += 1;
-                }
-            }
-        }
-        
-        for term_ref in query_term_post_order_iter(&self.head.2) {
-            if let TermRef::Var(_, _, var) = term_ref {
-                let entry = var_count.entry(var).or_insert(0);
-                *entry += 1;
-            }
-        }
-
-        for clause in &self.clauses {
-            for term_ref in query_term_post_order_iter(clause) {
-                if let TermRef::Var(_, _, var) = term_ref {
-                    let entry = var_count.entry(var).or_insert(0);
-                    *entry += 1;
-                }
-            }
-        }
-
-        var_count
-    }
-}
-
 #[derive(Clone)]
 pub struct Predicate(pub Vec<PredicateClause>);
 
@@ -199,10 +130,6 @@ impl Predicate {
             .first()
             .and_then(|clause| clause.name().map(|name| (name, clause.arity())))
     }
-
-    pub fn var_count(&self) -> Vec<IndexMap<Rc<Var>, usize>> {
-        self.0.iter().map(|clause| clause.var_count()).collect()
-    }
 }
 
 pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
@@ -234,39 +161,6 @@ impl PredicateClause {
             &PredicateClause::Rule(ref rule, ..) => Some(rule.head.0.clone()),
         }
     }
-
-    pub fn line_num(&self) -> usize {
-        match self {
-            &PredicateClause::Fact(_, line_num, _) => line_num,
-            &PredicateClause::Rule(_, line_num, _) => line_num
-        }
-    }
-
-    pub fn col_num(&self) -> usize {
-        match self {
-            &PredicateClause::Fact(_, _, col_num) => col_num,
-            &PredicateClause::Rule(_, _, col_num) => col_num
-        }
-    }
-
-    pub fn var_count(&self) -> IndexMap<Rc<Var>, usize> {
-        match self {
-            &PredicateClause::Fact(ref term, ..) => {
-                let mut var_count = IndexMap::new();
-                
-                for term_ref in breadth_first_iter(term, true) {
-                    if let TermRef::Var(_, _, var) = term_ref {
-                        let entry = var_count.entry(var).or_insert(0);
-                        *entry += 1;
-                    }
-                }
-
-                var_count
-            }
-            &PredicateClause::Rule(ref rule, ..) =>
-                rule.var_count()
-        }
-    }
 }
 
 #[derive(Clone)]
index b226cb482418b6eb0f87be80e9d4f96021156f6d..b946951a40d7e7866e83b7b9b2de1dfd07bcce44 100644 (file)
@@ -6,6 +6,7 @@ use prolog::codegen::*;
 use prolog::debray_allocator::*;
 use prolog::forms::*;
 use prolog::instructions::*;
+use prolog::iterators::*;
 use prolog::machine::machine_errors::*;
 use prolog::machine::machine_indices::*;
 use prolog::machine::term_expansion::ExpansionAdditionResult;
@@ -114,31 +115,35 @@ fn compile_relation(
 }
 
 fn issue_singleton_warnings(
-    tl: &TopLevel,
     module_name: ClauseName,
+    terms_and_locs: Vec<(Term, usize, usize)>,
 ) {
-    if let Some((line_num, _)) = tl.location() {
-        if let Some(var_counts) = tl.var_count() {
-            for var_count in var_counts {
-                let mut singletons = vec![];
-
-                for (var, count) in var_count {
-                    if count == 1 && !var.starts_with("_") && var.as_str() != "!" {
-                        singletons.push(var);
-                    }
-                }
+    for (term, line_num, _col_num) in terms_and_locs {
+        let mut singletons = vec![];
+        let mut var_count = IndexMap::new();
+
+        for subterm in breadth_first_iter(&term, true) {
+            if let TermRef::Var(_, _, var) = subterm {
+                let entry = var_count.entry(var).or_insert(0);
+                *entry += 1;
+            }
+        }
+        
+        for (var, count) in var_count {
+            if count == 1 && !var.starts_with("_") && var.as_str() != "!" {
+                singletons.push(var);
+            }
+        }
 
-                if let Some(last_var) = singletons.pop() {
-                    print!("Warning: {}:{}: Singleton variables: [",
-                           module_name, line_num);
-                
-                    for var in singletons {
-                        print!("{}, ", var);
-                    }
-                    
-                    println!("{}]", last_var);
-                }
+        if let Some(last_var) = singletons.pop() {
+            print!("Warning: {}:{}: Singleton variables: [",
+                   module_name, line_num);
+            
+            for var in singletons {
+                print!("{}, ", var);
             }
+            
+            println!("{}]", last_var);
         }
     }
 }
@@ -375,6 +380,7 @@ pub struct GatherResult {
     toplevel_results: Vec<PredicateCompileQueue>,
     toplevel_indices: IndexStore,
     addition_results: ExpansionAdditionResult,
+    top_level_terms: Vec<(Term, usize, usize)>
 }
 
 pub struct ClauseCodeGenerator {
@@ -687,10 +693,6 @@ impl ListingCompiler {
 
             compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
 
-            if !self.suppress_warnings {
-                issue_singleton_warnings(&decl, self.get_module_name());
-            }
-
             let idx = code_dir
                 .entry((name.clone(), arity))
                 .or_insert(CodeIndex::default());
@@ -942,6 +944,7 @@ impl ListingCompiler {
             toplevel_results,
             toplevel_indices,
             addition_results,
+            top_level_terms: worker.term_stream.top_level_terms(),
         })
     }
 
@@ -1021,6 +1024,10 @@ fn compile_work_impl(
        wam.run_init_code(init_goal_code);
     }
 
+    if !compiler.suppress_warnings {
+        issue_singleton_warnings(compiler.get_module_name(), results.top_level_terms);
+    }
+    
     EvalSession::EntrySuccess
 }
 
index 931e6adceaa9a393c51d068fdaf11cf69b5371c9..acd71db64d03aac068d45150ebd806c7a5c9658e 100644 (file)
@@ -77,6 +77,7 @@ pub struct TermStream<'a, R: Read> {
     pub(crate) flags: MachineFlags,
     term_expansion_lens: (usize, usize),
     goal_expansion_lens: (usize, usize),
+    top_level_terms: Vec<(Term, usize, usize)> // term, line_num, col_num.
 }
 
 pub struct ExpansionAdditionResult {
@@ -127,9 +128,15 @@ impl<'a, R: Read> TermStream<'a, R> {
             parser: Parser::new(src, atom_tbl, flags),
             in_module: false,
             flags,
+            top_level_terms: vec![]
         }
     }
 
+    #[inline]
+    pub fn top_level_terms(&mut self) -> Vec<(Term, usize, usize)> {
+        mem::replace(&mut self.top_level_terms, vec![])
+    }
+    
     #[inline]
     pub fn add_to_top(&mut self, buf: &str) {
         self.parser.add_to_top(buf);
@@ -263,12 +270,18 @@ impl<'a, R: Read> TermStream<'a, R> {
 
             self.parser.reset();
 
+            let line_num = self.line_num();
+            let col_num = self.col_num();
+            
             let term = self.parser.read_term(composite_op!(
                 self.in_module,
                 &self.wam.indices.op_dir,
                 op_dir
             ))?;
 
+            // preserve a copy of the original unexpanded term for warning scans,
+            // if that stage is reached.
+            self.top_level_terms.push((term.clone(), line_num, col_num));
             self.stack.push(term);
         }
     }