Skip to content
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

Implement typed PathPart parsing #96

Merged
merged 13 commits into from
Aug 17, 2022

Conversation

darichey
Copy link
Contributor

Summary & Motivation

A quick attempt at fixing #95.

Backwards-incompatible changes

PathWithInterpol is no longer a Wrapper node.

Further context

This might not be exactly the direction we want to go, but it seemed the most straightforward. We might consider combining StrPart and PathPart considering their overlap (InterpolationPart maybe?).

@darichey
Copy link
Contributor Author

It's also worth mentioning that, assuming a parse with no errors, the first part is always going to be a valid path which we could parse into a Value::Path. I think it would be nice to expose that, but that would require some bigger refactoring.

@Ma27 Ma27 self-requested a review July 11, 2022 10:10
@Ma27 Ma27 added the bug Something isn't working label Jul 11, 2022
@Ma27 Ma27 added this to the 0.11.0 milestone Jul 11, 2022
@fogti
Copy link
Contributor

fogti commented Jul 11, 2022

It might be a good idea to expose/return an impl Iterator instead of always allocating a vector, given that this internally already just wraps an iterator in a relatively simple way.

@darichey
Copy link
Contributor Author

I would agree, but I wanted to be consistent with Str::parts. I'd be happy to change them both.

@darichey
Copy link
Contributor Author

It's also worth mentioning that, assuming a parse with no errors, the first part is always going to be a valid path which we could parse into a Value::Path. I think it would be nice to expose that, but that would require some bigger refactoring.

61c0789 (#96) implements this with some breaking changes. Again, not sure if this is definitely the right way to go, but just trying things out. I'll wait for some feedback before doing more! :)

@fogti
Copy link
Contributor

fogti commented Jul 11, 2022

I would agree, but I wanted to be consistent with Str::parts. I'd be happy to change them both.

If you're able to do that, please do it (lately, I was working on extracting some changes from @oberblastmeister's more-typed-stuff PR, which involved reducing unnecessary memory allocations, and it would be nice to "keep this spirit", because it might also improve downstream performance, and reduce peak memory usage)

NodeOrToken::Node(node) => {
assert_eq!(node.kind(), NODE_STRING_INTERPOL);
parts.push(PathPart::Interpolation(
ast::StrInterpol::cast(node.clone()).unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this cast should mean that the assert directly above it is unnecessary, right?

@darichey
Copy link
Contributor Author

darichey commented Jul 30, 2022

Reworked based on @oberblastmeister Path changes in 9df0b11. I noticed that commit makes ast::Path ambiguous (it could either be the token Path or the node Path). Should I try to fix that here?

I also combined StrPart and PathPart into InterpolPart and return an impl Iterator instead of Vec.

@zseri I'm going to hold off on changing Str::parts in this PR since I believe @Ma27 is making changes there rn.

@oberblastmeister
Copy link
Contributor

@darichey You can fix that here. What name should we use?

@darichey
Copy link
Contributor Author

darichey commented Aug 7, 2022

Sorry, I've been away. I see the rename was done in #134. Is there anything else that needs to be done here?

@oberblastmeister
Copy link
Contributor

@darichey I think InterpolPart should be generic over T. We should have a new node called StrContent or something and Str::parts should return InterpolPart<StrContent>. I think the existing Str::parts methods should be refactored to take an iterator over InterpolPart<StrContent> and return a vector of InterpolPart<String>, or maybe a tuple.

@darichey
Copy link
Contributor Author

Sorry, I don't understand. Is this what you mean?

node! { #[from(NODE_STRING_CONTENT)] struct StrContent; }

impl StrContent {
    tg! { content, TOKEN_STRING_CONTENT }
}
enum InterpolPart<T> {
  Literal(T)
  Interpolation(super::Interpol)
}
impl ast::Str {
  pub fn parts(&self) -> impl Iterator<Item = InterpolPart<StrContent>> { /* ... */ }
}
// name and location tbd
pub fn parse_parts(impl Iterator<Item = InterpolPart<StrContent>>) -> impl Iterator<Item = InterpolPart<String>> { /* ... */ }

It's not clear to me what is gained here since we have to examine the contents of the inner TOKEN_STRING_CONTENT in ast::Str::parts anyways.

Also, how should we apply the same ideas to paths?

@fogti
Copy link
Contributor

fogti commented Aug 16, 2022

Why do we need the NODE_STRING_CONTENT indirection, when it just contains a token, or is this necessary because of some rowan limitation?

@oberblastmeister
Copy link
Contributor

ast::Path::Parts should return impl Iterator<Item = InterpolPart<PathContent>>

@oberblastmeister
Copy link
Contributor

@darichey @zseri StrContent should probably be a token

@oberblastmeister
Copy link
Contributor

Sorry, I don't understand. Is this what you mean?

Yes. The idea of returning InterpolPart<StrContent> and then converting it to InterpolPart<String> is that the former abstracts the manual casting we have currently in ast::Str::Parts. In addition, we should have an api for accessing the nodes without further parsing just like we have for other nodes.

@darichey
Copy link
Contributor Author

Got it, I tried implementing that.

It might be a good idea to expose/return an impl Iterator instead of always allocating a vector, given that this internally already just wraps an iterator in a relatively simple way.

@zseri going way back to this, I just realized that I don't think this is possible for string parts, because we need to iterate over all the children first to calculate the common indent. Do you agree?

}
InterpolPart::Interpolation(interpol) => InterpolPart::Interpolation(interpol),
})
.collect()
Copy link
Contributor

@fogti fogti Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please omit the .collect(), what the user intends with the iterator shouldn't be a business of the library, if avoidable. (although I understand if we keep it that way to stay symmetric to ast::Str, even tho I don't think that's important, because their function is also different)

@oberblastmeister
Copy link
Contributor

@darichey parts_parsed should be removed, it doesn't add any value unlike the Str variant

@oberblastmeister
Copy link
Contributor

I think normalized_parts is a better name than parts_parsed

@fogti
Copy link
Contributor

fogti commented Aug 16, 2022

@darichey

I just realized that I don't think this is possible for string parts, because we need to iterate over all the children first to calculate the common indent.

yes, correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants