-
Notifications
You must be signed in to change notification settings - Fork 115
Use mentat-parser-utils in tx-parser. Initial stab at #235 #249
Conversation
tx-parser/src/lib.rs
Outdated
|
||
use combine::{any, eof, many, optional, parser, satisfy_map, token, Parser, ParseResult, Stream}; | ||
use combine::combinator::{Expected, FnParser}; | ||
use edn::symbols::NamespacedKeyword; | ||
use edn::types::Value; | ||
use mentat_tx::entities::*; | ||
use mentat_tx::entities::{Entid, EntidOrLookupRef, Entity, LookupRef, ValueOrLookupRef}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to import stuff explicitly instead of everything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good style. Using *
means that a simple addition in a different crate can cause this one to fail to compile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a clash of styles it would seem, as @ncalexan opted for *
in the first place. Have we settled on a single style for our codebase? My question was directed to the fact that I didn't see how it this change was related to the issue being fixed (it could've been for what I know, I still don't have a solid grasp on rust).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it because I misread an error message telling me it wasn't needed (it was actually the one down around line 274 in mod tests
).
I agree with @rnewman's logic, and I'd also add that some specificity about what's required and what isn't is a good thing from a purely visual POV to humans too
query-parser/src/parser_util.rs
Outdated
@@ -40,6 +40,7 @@ macro_rules! matches_plain_symbol { | |||
/// The provided `$body` will be evaluated with `$input` bound to the input stream. | |||
/// | |||
/// `$body`, when run, should return a `ParseResult` of the appropriate result type. | |||
#[macro_export] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably go ahead and export all of these macros.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing in query-parser
should be exported; if it's directly applicable to other crates, it should be moved to parser-utils
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought not putting these in the parser_utils crate in the first place was intentional. If moved there though, they should indeed be exported as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was: they're very EDN-specific, and I wasn't sure how reusable they would be.
It looks like @joewalker could directly use def_value_satisfy_parser_fn!
, though…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm moving all (?) the parser utils from parser_utils to parser-utils, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is: if it can be used in other places as well, then yes. However, indeed in this particular case def_value_satisfy_parser_fn
could be used instead of def_parser_fn
, so maybe don't move unless there's a really good reason to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The macros are built on each other, so you can't move and use d_v_s_p_f
without moving the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@victorporof You're saying we could use def_value_satisfy_parser_fn
here? I'm not sure how - what should the path be?
def_value_satisfy_parser_fn!(Tx, integer, i64, Value::Integer(x));
Doesn't work
tx-parser/src/lib.rs
Outdated
@@ -13,12 +13,17 @@ | |||
extern crate edn; | |||
extern crate combine; | |||
extern crate mentat_tx; | |||
extern crate mentat_parser_utils; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also likely to require a macro_use pragma if you plan on using the macros there. I'd be surprised if not.
tx-parser/src/lib.rs
Outdated
@@ -30,9 +35,19 @@ fn fn_parser<O, I>(f: fn(I) -> ParseResult<O, I>, err: &'static str) -> TxParser | |||
parser(f).expected(err) | |||
} | |||
|
|||
def_parser_fn!(Tx, integer, Value, i64, input, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably not have to define macros here. There's another def_parser_fn!
as well in the mentat query parser crate. Did you intend to redefine it here? I'm having a hard time understanding what this is for as well, since it's not used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def_parser_fn!
is a macro invocation, not a macro definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I misread this!
Yeah, I think this was a mistake. In some cases it makes sense -- for example, during development -- but in most cases it's best to just list them. Filed #251 to unify on the non- |
@joewalker Is this still WIP? |
Erm, maybe? Do we have any test coverage info anywhere? All the tests pass, but can I be sure we're testing it properly? |
Something that makes me think I'm not done yet - The pre-PR version of entities contains |
Elsewhere @rnewman said (of lib.rs:48)
Which sounds likely, except that I'm stuck on what
But nope. Any ideas? |
About to squash and rebase. Head was at 12f17c1 |
tx-parser/src/lib.rs
Outdated
.parse_stream(input); | ||
} | ||
// The above using a def_value_satisfy_parser_fn | ||
//def_value_satisfy_parser_fn!(Tx, integer, i64, if let Value::Integer(y) = x { Some(y) } else { None }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice this allows you to simply pass a function that accepts an
&edn::Value
and
returns anOption<$result_type>
: if a suitable value is at the front of the stream,
it will be converted and returned by the parser; otherwise, the parse will fail.
So if you define a function:
fn value_to_i64(val: &Value) -> Option<i64> {
if let &Value::Integer(i) = val { Some(i) } else { None }
}
you can use it here:
def_value_satisfy_parser_fn!(Tx, integer, i64, value_to_i64);
Now it turns out we already have that function: it's Value::as_integer
. So this should work:
def_value_satisfy_parser_fn!(Tx, integer, i64, Value::as_integer);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, except that the signature of as_integer is (&self) -> Option<&i64>
, and we want -> Option<i64>
. So maybe I just include the function as stated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i64
implements Copy
, so we should fix the definition of as_integer
(and as_float
, as_boolean
). No sense returning a reference type when the raw type is no larger than a machine address!
I can do that very quickly in a side PR. Momento…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tx-parser/src/lib.rs
Outdated
// Manually expanding the above: | ||
// def_value_parser_fn!(Tx, integer, i64, input, { | ||
// satisfy_map(|x: edn::Value| $transformer(&x) ).parse_stream(input) | ||
// satisfy_map(|x: edn::Value| if let Value::Integer(y) = x { Some(y) } else { None }).parse_stream(input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trick is that $transformer
is a path, not a block, so you can't pass an expression to this macro.
tx-parser/src/lib.rs
Outdated
.parse_stream(input); | ||
} | ||
def_parser_fn!(Tx, keyword, Value, NamespacedKeyword, input, { | ||
return satisfy_map(|x: Value| if let Value::NamespacedKeyword(y) = x { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, this would be Value::as_namespaced_keyword
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, and if this can't be done, because you get back a ref, then we perhaps want Value::to_namespaced_keyword
, which would simply be
pub fn to_namespaced_keyword(&self) -> Option<NamespacedKeyword> {
self.as_namespaced_keyword().map(|x| x.clone())
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't see this comment until I'd worked it out myself, except I wrote:
fn value_to_namespaced_keyword(val: &Value) -> Option<NamespacedKeyword> {
if let &Value::NamespacedKeyword(ref i) = val { Some(i.clone()) } else { None }
}
I think it makes sense to do this in Value though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this using macros: joewalker@a4ba10c
tx-parser/src/lib.rs
Outdated
match r { | ||
// TODO: abstract the "match Vector, parse internal stream" pattern to remove this boilerplate. | ||
def_parser_fn!(Tx, add, Value, Entity, input, { | ||
return satisfy_map(|x: Value| -> Option<Entity> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can omit the return
and the closing semicolon, saving yourself some space.
I think we can land this. OK? |
tx-parser/src/lib.rs
Outdated
return satisfy_map(|x: Value| if let Value::Integer(y) = x { | ||
Some(y) | ||
fn value_to_namespaced_keyword(val: &Value) -> Option<NamespacedKeyword> { | ||
if let &Value::NamespacedKeyword(ref i) = val { Some(i.clone()) } else { None } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can use val.as_namespaced_keyword().map(|x| x.clone())
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even:
def_value_satisfy_parser_fn!(Tx, keyword, NamespacedKeyword, Value::into_namespaced_keyword);
Since the landing of 49f91b0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sigh. Nope. I'll do it your way and land it, and work out the fancy thing later.
…ctorporof Move macros query-parser/…/parser_utils.rs → parser-utils/…/query.rs Signed-off-by: Joe Walker <jwalker@mozilla.com>
Work in progress patch just to see if I'm on the right lines.