Part 1 - Parse not and not-join

This commit is contained in:
Emily Toop 2017-04-06 13:46:27 +01:00
parent 4b45827be7
commit 76d0223c2a
2 changed files with 151 additions and 15 deletions

View file

@ -43,6 +43,8 @@ use self::mentat_query::{
FromValue,
OrJoin,
OrWhereClause,
NotJoin,
WhereNotClause,
Pattern,
PatternNonValuePlace,
PatternValuePlace,
@ -163,6 +165,10 @@ def_parser!(Where, or_join, edn::ValueAndSpan, {
})
});
def_matches_plain_symbol!(Where, or_join, "not");
def_matches_plain_symbol!(Where, or_join, "not-join");
def_parser!(Where, rule_vars, Vec<Variable>, {
seq()
.of_exactly(many1(Query::variable()))
@ -210,6 +216,53 @@ def_parser!(Where, or_join_clause, WhereClause, {
}))
});
def_value_parser_fn!(Where, not_pattern_clause, WhereNotClause, input, {
Where::clause().map(|clause| WhereNotClause::Clause(clause)).parse_stream(input)
});
def_value_parser_fn!(Where, where_not_clause, WhereNotClause, input, {
choice([Where::not_pattern_clause()]).parse_stream(input)
});
def_value_parser_fn!(Where, not_clause, WhereClause, input, {
satisfy_map(|x: edn::Value| {
seq(x).and_then(|items| {
let mut p = Where::not()
.with(many1(Where::where_not_clause()))
.skip(eof())
.map(|clauses| {
WhereClause::NotJoin(
NotJoin {
unify_vars: UnifyVars::Implicit,
clauses: clauses,
})
});
let r: ParseResult<WhereClause, _> = p.parse_lazy(&items[..]).into();
Query::to_parsed_value(r)
})
}).parse_stream(input)
});
def_value_parser_fn!(Where, not_join_clause, WhereClause, input, {
satisfy_map(|x: edn::Value| {
seq(x).and_then(|items| {
let mut p = Where::not_join()
.with(Where::rule_vars())
.and(many1(Where::where_not_clause()))
.skip(eof())
.map(|(vars, clauses)| {
WhereClause::NotJoin(
NotJoin {
unify_vars: UnifyVars::Explicit(vars),
clauses: clauses,
})
});
let r: ParseResult<WhereClause, _> = p.parse_lazy(&items[..]).into();
Query::to_parsed_value(r)
})
}).parse_stream(input)
});
/// A vector containing just a parenthesized filter expression.
def_parser!(Where, pred, WhereClause, {
// Accept either a nested list or a nested vector here:
@ -293,6 +346,8 @@ def_parser!(Where, clause, WhereClause, {
// We don't yet handle source vars.
try(Where::or_join_clause()),
try(Where::or_clause()),
try(Where::not_join_clause()),
try(Where::not_clause()),
try(Where::pred()),
try(Where::where_fn()),
@ -641,6 +696,59 @@ mod test {
}));
}
#[test]
fn test_not() {
let oj = edn::PlainSymbol::new("not");
let e = edn::PlainSymbol::new("?e");
let a = edn::PlainSymbol::new("?a");
let v = edn::PlainSymbol::new("?v");
let input = [edn::Value::List(
vec![edn::Value::PlainSymbol(oj),
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
edn::Value::PlainSymbol(a.clone()),
edn::Value::PlainSymbol(v.clone())])].into_iter().collect())];
assert_parses_to!(Where::not_clause, input,
WhereClause::NotJoin(
NotJoin {
unify_vars: UnifyVars::Implicit,
clauses: vec![WhereNotClause::Clause(
WhereClause::Pattern(Pattern {
source: None,
entity: PatternNonValuePlace::Variable(variable(e)),
attribute: PatternNonValuePlace::Variable(variable(a)),
value: PatternValuePlace::Variable(variable(v)),
tx: PatternNonValuePlace::Placeholder,
}))],
}));
}
#[test]
fn test_not_join() {
let oj = edn::PlainSymbol::new("not-join");
let e = edn::PlainSymbol::new("?e");
let a = edn::PlainSymbol::new("?a");
let v = edn::PlainSymbol::new("?v");
let input = [edn::Value::List(
vec![edn::Value::PlainSymbol(oj),
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]),
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
edn::Value::PlainSymbol(a.clone()),
edn::Value::PlainSymbol(v.clone())])].into_iter().collect())];
assert_parses_to!(Where::not_join_clause, input,
WhereClause::NotJoin(
NotJoin {
unify_vars: UnifyVars::Explicit(vec![variable(e.clone())]),
clauses: vec![WhereNotClause::Clause(
WhereClause::Pattern(Pattern {
source: None,
entity: PatternNonValuePlace::Variable(variable(e)),
attribute: PatternNonValuePlace::Variable(variable(a)),
value: PatternValuePlace::Variable(variable(v)),
tx: PatternNonValuePlace::Placeholder,
}))],
}));
}
#[test]
fn test_find_sp_variable() {
let sym = edn::PlainSymbol::new("?x");

View file

@ -189,18 +189,6 @@ pub enum FnArg {
impl FromValue<FnArg> for FnArg {
fn from_value(v: edn::ValueAndSpan) -> Option<FnArg> {
<<<<<<< HEAD
// TODO: support SrcVars.
Variable::from_value(v.clone()) // TODO: don't clone!
.and_then(|v| Some(FnArg::Variable(v)))
.or_else(|| {
println!("from_value {}", v.inner);
match v.inner {
edn::SpannedValue::Integer(i) => Some(FnArg::EntidOrInteger(i)),
edn::SpannedValue::Float(f) => Some(FnArg::Constant(NonIntegerConstant::Float(f))),
_ => unimplemented!(),
}})
=======
use edn::SpannedValue::*;
match v.inner {
Integer(x) =>
@ -229,7 +217,6 @@ impl FromValue<FnArg> for FnArg {
Set(_) |
Map(_) => None,
}
>>>>>>> 71d3aa29ed3b383f030e9b3d13eeef5a12820be1
}
}
@ -631,11 +618,30 @@ pub struct OrJoin {
pub clauses: Vec<OrWhereClause>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WhereNotClause {
Clause(WhereClause),
}
impl WhereNotClause {
pub fn is_pattern_or_patterns(&self) -> bool {
match self {
&WhereNotClause::Clause(WhereClause::Pattern(_)) => true,
_ => false,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NotJoin {
pub unify_vars: UnifyVars,
pub clauses: Vec<WhereNotClause>,
}
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WhereClause {
Not,
NotJoin,
NotJoin(NotJoin),
OrJoin(OrJoin),
Pred(Predicate),
WhereFn(WhereFn),
@ -689,9 +695,14 @@ impl ContainsVariables for WhereClause {
&OrJoin(ref o) => o.accumulate_mentioned_variables(acc),
&Pred(ref p) => p.accumulate_mentioned_variables(acc),
&Pattern(ref p) => p.accumulate_mentioned_variables(acc),
<<<<<<< HEAD
&Not => (),
&NotJoin => (),
&WhereFn(_) => (),
=======
&NotJoin(ref n) => n.accumulate_mentioned_variables(acc),
&WhereFn => (),
>>>>>>> Part 1 - Parse `not` and `not-join`
&RuleExpr => (),
}
}
@ -715,6 +726,23 @@ impl ContainsVariables for OrJoin {
}
}
impl ContainsVariables for NotJoin {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
for clause in &self.clauses {
clause.accumulate_mentioned_variables(acc);
}
}
}
impl ContainsVariables for WhereNotClause {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
use WhereNotClause::*;
match self {
&Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
}
}
}
impl ContainsVariables for Predicate {
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
for arg in &self.args {