From d6c148d5e924764c0d82778245d212cfa8b69c81 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 7 Apr 2018 16:44:51 -0600 Subject: [PATCH] fix cut expansions. --- src/prolog/ast.rs | 38 ++++++++++++++++++++++++++++---------- src/prolog/codegen.rs | 6 +++--- src/prolog/fixtures.rs | 3 ++- src/prolog/io.rs | 4 ++-- src/prolog/iterators.rs | 13 +++++++++---- src/prolog/parser | 2 +- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index f3064465..113084c1 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -101,7 +101,25 @@ impl GenContext { } } -pub type Predicate = Vec; +pub struct Predicate(pub Vec); + +impl Predicate { + pub fn name(&self) -> Option { + self.0.first().and_then(|t| t.name()) + } + + pub fn arity(&self) -> usize { + if let Some(ref clause) = self.0.first() { + clause.arity() + } else { + 0 + } + } + + pub fn clauses(self) -> Vec { + self.0 + } +} pub enum PredicateClause { Fact(Term), @@ -260,7 +278,7 @@ impl TopLevel { &TopLevel::Declaration(_) => None, &TopLevel::Fact(ref term) => term.name(), &TopLevel::Predicate(ref clauses) => - clauses.first().and_then(|ref term| term.name()), + clauses.0.first().and_then(|ref term| term.name()), &TopLevel::Query(_) => None, &TopLevel::Rule(Rule { ref head, .. }) => Some(head.0.clone()) @@ -272,18 +290,18 @@ impl TopLevel { &TopLevel::Declaration(_) => 0, &TopLevel::Fact(ref term) => term.arity(), &TopLevel::Predicate(ref clauses) => - clauses.first().map(|t| t.arity()).unwrap_or(0), + clauses.0.first().map(|t| t.arity()).unwrap_or(0), &TopLevel::Query(_) => 0, &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() } } - pub fn as_predicate(self) -> Option { + pub fn as_predicate(self) -> Result { match self { - TopLevel::Fact(term) => Some(vec![PredicateClause::Fact(term)]), - TopLevel::Rule(rule) => Some(vec![PredicateClause::Rule(rule)]), - TopLevel::Predicate(pred) => Some(pred), - _ => None + TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])), + TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])), + TopLevel::Predicate(pred) => Ok(pred), + _ => Err(self) } } } @@ -669,7 +687,7 @@ pub type JumpStub = Vec; pub enum QueryTerm { Clause(Cell, ClauseType, Vec>), BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. - UnblockedCut, + UnblockedCut(Cell), Jump(JumpStub) } @@ -677,7 +695,7 @@ impl QueryTerm { pub fn arity(&self) -> usize { match self { &QueryTerm::Clause(_, _, ref subterms) => subterms.len(), - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => 0, + &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, &QueryTerm::Jump(ref vars) => vars.len() } } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 05b9bf2a..1b31f0ff 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -408,8 +408,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator }; match *term { - &QueryTerm::UnblockedCut => - code.push(set_cp!(self.marker.get(rc_atom!("!")))), + &QueryTerm::UnblockedCut(ref cell) => + code.push(set_cp!(cell.get().norm())), &QueryTerm::BlockedCut => code.push(if chunk_num == 0 { Line::Cut(CutInstruction::NeckCut) @@ -482,7 +482,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { // add a proceed to bookend any trailing cuts. match toc { - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()), + &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()), _ => {} }; diff --git a/src/prolog/fixtures.rs b/src/prolog/fixtures.rs index 34a70751..00590e54 100644 --- a/src/prolog/fixtures.rs +++ b/src/prolog/fixtures.rs @@ -159,7 +159,8 @@ impl<'a> VariableFixtures<'a> for term_ref in iter { if let &TermRef::Var(lvl, cell, ref var) = &term_ref { let mut status = self.0.remove(var) - .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), Vec::new())); + .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), + Vec::new())); status.1.push(cell); diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 89440174..4dbe7043 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -492,7 +492,7 @@ fn compile_relation(tl: &TopLevel) -> Result &TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(ParserError::ExpectedRel), &TopLevel::Predicate(ref clauses) => - cg.compile_predicate(clauses), + cg.compile_predicate(&clauses.0), &TopLevel::Fact(ref fact) => Ok(cg.compile_fact(fact)), &TopLevel::Rule(ref rule) => @@ -576,7 +576,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec) -> EvalSe print_code(&code); if !code.is_empty() { - wam.add_user_code(name, tl.arity(), code, tl.as_predicate().unwrap()) + wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap()) } else { EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated."))) } diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 8ed518e6..23c5aad4 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -2,6 +2,7 @@ use prolog::ast::*; use std::collections::VecDeque; use std::iter::*; +use std::rc::Rc; use std::vec::Vec; pub struct QueryIterator<'a> { @@ -50,8 +51,12 @@ impl<'a> QueryIterator<'a> { let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms); QueryIterator { state_stack: vec![state] } }, - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => + &QueryTerm::BlockedCut => QueryIterator { state_stack: vec![] }, + &QueryTerm::UnblockedCut(ref cell) => { + let state = TermIterState::Var(Level::Root, cell, rc_atom!("!")); + QueryIterator { state_stack: vec![state] } + }, &QueryTerm::Jump(ref vars) => { let state_stack = vars.iter().rev().map(|t| { TermIterState::subterm_to_state(Level::Shallow, t) @@ -322,7 +327,7 @@ impl<'a> ChunkedIterator<'a> if contains_cut_var(vars.iter()) && !self.cut_var_in_head { self.deep_cut_encountered = true; } - + break; }, ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => { @@ -332,8 +337,8 @@ impl<'a> ChunkedIterator<'a> self.deep_cut_encountered = true; } }, - ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut) => - result.push(term), + ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) => + result.push(term), ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) => result.push(term), ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => { diff --git a/src/prolog/parser b/src/prolog/parser index 737d6ba0..ba9bd009 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 737d6ba091bb5909b0af31c221f290debc95bf2d +Subproject commit ba9bd0098e66227006b799a6c5c2c583fa9d9009 -- 2.54.0