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:
parent
08534a1a3a
commit
9fe31d443d
3 changed files with 21 additions and 2 deletions
|
@ -56,7 +56,8 @@ impl ConjoiningClauses {
|
||||||
Constant(NonIntegerConstant::Text(_)) |
|
Constant(NonIntegerConstant::Text(_)) |
|
||||||
Constant(NonIntegerConstant::Uuid(_)) |
|
Constant(NonIntegerConstant::Uuid(_)) |
|
||||||
Constant(NonIntegerConstant::Instant(_)) | // Instants are covered elsewhere.
|
Constant(NonIntegerConstant::Instant(_)) | // Instants are covered elsewhere.
|
||||||
Constant(NonIntegerConstant::BigInteger(_)) => {
|
Constant(NonIntegerConstant::BigInteger(_)) |
|
||||||
|
Vector(_) => {
|
||||||
self.mark_known_empty(EmptyBecause::NonNumericArgument);
|
self.mark_known_empty(EmptyBecause::NonNumericArgument);
|
||||||
bail!(ErrorKind::NonNumericArgument(function.clone(), position));
|
bail!(ErrorKind::NonNumericArgument(function.clone(), position));
|
||||||
},
|
},
|
||||||
|
@ -86,6 +87,7 @@ impl ConjoiningClauses {
|
||||||
Constant(NonIntegerConstant::Instant(u)) => Ok(QueryValue::TypedValue(TypedValue::Instant(u))),
|
Constant(NonIntegerConstant::Instant(u)) => Ok(QueryValue::TypedValue(TypedValue::Instant(u))),
|
||||||
Constant(NonIntegerConstant::BigInteger(_)) => unimplemented!(),
|
Constant(NonIntegerConstant::BigInteger(_)) => unimplemented!(),
|
||||||
SrcVar(_) => unimplemented!(),
|
SrcVar(_) => unimplemented!(),
|
||||||
|
Vector(_) => unimplemented!(), // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ def_parser!(Query, predicate_fn, PredicateFn, {
|
||||||
});
|
});
|
||||||
|
|
||||||
def_parser!(Query, fn_arg, FnArg, {
|
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>, {
|
def_parser!(Query, arguments, Vec<FnArg>, {
|
||||||
|
@ -777,4 +777,18 @@ mod test {
|
||||||
let mut par = Query::natural_number();
|
let mut par = Query::natural_number();
|
||||||
assert_eq!(None, par.parse(input.atom_stream()).err());
|
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)),
|
||||||
|
]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,6 +216,9 @@ pub enum FnArg {
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(NamespacedKeyword),
|
IdentOrKeyword(NamespacedKeyword),
|
||||||
Constant(NonIntegerConstant),
|
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 {
|
impl FromValue<FnArg> for FnArg {
|
||||||
|
|
Loading…
Reference in a new issue