Pre: Accept EDN vectors in FnArg arguments.

Datomic accepts mostly-arbitrary EDN, and it is actually used: for
example, the following are all valid, and all mean different things:
* `(ground 1 ?x)`
* `(ground [1 2 3] [?x ?y ?z])`
* `(ground [[1 2 3] [4 5 6]] [[?x ?y ?z]])`

We could probably introduce new syntax that expresses these patterns
while avoiding collection arguments, but I don't see one right now.
I've elected to support only vectors for simplicity; I'm hoping to
avoid parsing edn::Value in the query-algebrizer.
This commit is contained in:
Nick Alexander 2017-04-19 11:10:24 -07:00 committed by Richard Newman
parent 08534a1a3a
commit 9fe31d443d
3 changed files with 21 additions and 2 deletions

View file

@ -56,7 +56,8 @@ impl ConjoiningClauses {
Constant(NonIntegerConstant::Text(_)) |
Constant(NonIntegerConstant::Uuid(_)) |
Constant(NonIntegerConstant::Instant(_)) | // Instants are covered elsewhere.
Constant(NonIntegerConstant::BigInteger(_)) => {
Constant(NonIntegerConstant::BigInteger(_)) |
Vector(_) => {
self.mark_known_empty(EmptyBecause::NonNumericArgument);
bail!(ErrorKind::NonNumericArgument(function.clone(), position));
},
@ -86,6 +87,7 @@ impl ConjoiningClauses {
Constant(NonIntegerConstant::Instant(u)) => Ok(QueryValue::TypedValue(TypedValue::Instant(u))),
Constant(NonIntegerConstant::BigInteger(_)) => unimplemented!(),
SrcVar(_) => unimplemented!(),
Vector(_) => unimplemented!(), // TODO
}
}
}

View file

@ -134,7 +134,7 @@ def_parser!(Query, predicate_fn, PredicateFn, {
});
def_parser!(Query, fn_arg, FnArg, {
satisfy_map(FnArg::from_value)
satisfy_map(FnArg::from_value).or(vector().of_exactly(many::<Vec<FnArg>, _>(Query::fn_arg())).map(FnArg::Vector))
});
def_parser!(Query, arguments, Vec<FnArg>, {
@ -777,4 +777,18 @@ mod test {
let mut par = Query::natural_number();
assert_eq!(None, par.parse(input.atom_stream()).err());
}
#[test]
fn test_fn_arg_collections() {
let vx = edn::PlainSymbol::new("?x");
let vy = edn::PlainSymbol::new("?y");
let input = edn::Value::Vector(vec![edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()),
edn::Value::PlainSymbol(vy.clone())])]);
assert_parses_to!(|| vector().of_exactly(Query::fn_arg()),
input,
FnArg::Vector(vec![FnArg::Variable(variable(vx)),
FnArg::Variable(variable(vy)),
]));
}
}

View file

@ -216,6 +216,9 @@ pub enum FnArg {
EntidOrInteger(i64),
IdentOrKeyword(NamespacedKeyword),
Constant(NonIntegerConstant),
// The collection values representable in EDN. There's no advantage to destructuring up front,
// since consumers will need to handle arbitrarily nested EDN themselves anyway.
Vector(Vec<FnArg>),
}
impl FromValue<FnArg> for FnArg {