-
-
Notifications
You must be signed in to change notification settings - Fork 226
Addition of step in export_range #484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addition of step in export_range #484
Conversation
For the future, you can just (force-)push to the same branch again. As long as there is at least one commit on that branch, you should be able to reopen the PR 🙂 |
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-484 |
@Bromeon It seems I've botched something big time on my fork and lost all work. Remade it from memory, as most of the time was spend of figuring out how all this interacts with each other. As it was such a big mess, it seemed |
With git, it's rather hard to permanently lose work, as soon as things are committed. You could look into Furthermore, GitHub also retains commits, see the timeline in the old PR. |
Yeah, it seems like I urgently need to step up my git flow knowledge :P |
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.
Thanks!
The is_next_ident
is very specific to only this one use case. If somehow possible, I'd like to avoid the proc-macro parsers to become huge patchworks of special cases; it's bad enough that we had to duplicate KvParser
and ListParser
.
We already have try_next_ident
, can you not use that to check whether the next expression is an ident
?
Using I am not sure that this is the only place where it will be ever needed - didn't look through all other export annotations to check if there are optional literal arguments in there that could be omitted in the past. Moreover - if there is not one now, Godot development is still ongoing and who knows if there wouldn't be one in the future. It seemed more reasonable to do it that way than refactoring the following retrieval of the options identifiers |
I see. Maybe it should then be named
This argument can be used to justify any possible feature. There's no concrete indication that Godot plans to add more range parameters, so I'd rather follow YAGNI. (This as a general note, not regarding the feature here in particular).
Yeah, I think it's fine for now 🙂 I will try to refactor these parsers a bit in the future, maybe we can also share some logic between KV and list parsers. |
godot-macros/src/util/list_parser.rs
Outdated
/// Check if the next element of the list is an identifier | ||
/// | ||
/// Returns `None` if there are no more elements left, `Some(true)` if the | ||
/// next element is identifier and `Some(false)` if it is not | ||
pub fn is_next_ident(&mut self) -> Option<bool> { | ||
let Some(kv) = self.peek() else { | ||
return None; | ||
}; | ||
|
||
let res = kv.as_ident(); | ||
|
||
Some(res.is_ok()) | ||
} |
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.
To have all change requests as suggestions:
- Could be named
peek_next_ident
and return theIdent
directly. - Full stops and line lengths in docs 😉
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 don't really think that peek_next_ident
will actually work.
The thing is in the #[export_range(min, max, step, options..)]
the min
and max
are the only required elements. Next comes step
, which (I think?) need to be retrieved using parser.next_expr()?
. If there were one of the options (which are idents) it will be retrieved as expression - so parser.next_expr()?
won't throw error, the error would be from general compiler if symbol of the same name as option identifier won't be present in current scope.
I wanted to introduce parser.try_next_expr()
there, but it wouldn't work because of the above. Instead I needed to do reverse check - if there is identifier, we can omit getting the step
, and we can move to option parsing.
Later, at the other hand the options are parsed using loop with parser.next_any_ident(&ALLOWED_OPTIONS[..])?
which is very clear and clean, but unfortunately needs the parser to have all the option identifiers not consumed. If I would retrieve the identifier beforehand, it wouldn't be there.
MID-WRITING IDEA
So, during writing this comment I begin to think in some other way, and came up with an alternative skipping the need for is_next_ident
:
let step = match parser.next_any_ident(&ALLOWED_OPTIONS[..]) {
Ok(maybe_option) => {
if let Some(option) = maybe_option {
options.insert(option.to_string());
}
quote! { None }
},
Err(_) => {
let value = parser.next_expr()?;
quote!{ Some(#value) }
}
};
But I'm not completely sure that it will work in all scenarios, seems to pass the tests though...
Edit: Yeah, it makes in the scenario if the first option given after #[export_range(min, max, my_option)]
isn't one of ALLOWED_OPTIONS the error message wouldn't be clear.
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 what do you suggest?
As mentioned, let's just get this working for now, we can refactor the parsers later... Important is that the cases are covered by tests so that any future changes don't break things.
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.
Currently the only idea I have is the explicit check for the identifier, as in initial commit with is_next_ident
, without consuming or retrieving it in any way. It has some overhead and adds next method, needed exclusively for this functionality, but keeps the parsing with explicit and clean error messages.
Alternatively could just expose peek()
method in ListParser
and move the whole is_next_ident
method implementation into new_range_list()
. It should be safe, I think, as peek()
doesn't mutate the ListParser
.
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.
Currently the only idea I have is the explicit check for the identifier, as in initial commit with is_next_ident, without consuming or retrieving it in any way. It has some overhead and adds next method, needed exclusively for this functionality, but keeps the parsing with explicit and clean error messages.
That's fine for me 🙂 I'm not too worried about the small overhead at this point, but eventually would like to consolidate the implementation a bit (not in this PR).
So if once you address the other suggestions in the code, it should be ready to merge from my point 👍
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.
@Bromeon I think I've adressed all other issues mentioned, it seems to be ready to merge?
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.
Almost good, please squash the commits to one. And let me know if you need help with it!
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.
@Bromeon I think I've done it correctly this time! I found this strategy: https://stackoverflow.com/a/69827502 to be much clearer to me than venturing into a rebase hellish circle :)
e787094
to
9085aa1
Compare
235b99f
to
e397653
Compare
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.
Thanks a lot!
Duplicate of #483
Resolves #413