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

Add Node::unparse and tweak the cursor creation API #666

Merged
merged 14 commits into from
Nov 22, 2023

Conversation

Xanewok
Copy link
Member

@Xanewok Xanewok commented Nov 20, 2023

Closes #583
Ref #628 for the modified cursor/offset API

Changes are best reviewed commit-by-commit.

@Xanewok Xanewok requested a review from a team as a code owner November 20, 2023 16:17
Copy link

changeset-bot bot commented Nov 20, 2023

🦋 Changeset detected

Latest commit: 1007589

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@nomicfoundation/slang Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Collaborator

@OmarTawfik OmarTawfik left a comment

Choose a reason for hiding this comment

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

Left a few questions.

crates/codegen/parser/runtime/src/cst.rs Show resolved Hide resolved
crates/codegen/parser/runtime/src/cst.rs Show resolved Hide resolved
}
return None;
}

pub fn as_rule_with_kind(&self, kinds: &[RuleKind]) -> Option<&Rc<RuleNode>> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Possibly unrelated to this PR, but asking since it is addressing API feedback:

For as_rule_matching(...) .. I wonder how is that different from .as_rule().filter(...), given it is the same characters/effort to type?

Are we duplicating Rust std:: methods? what new scenarios does it enable?

Same question for as_token_matching().

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right that this is merely a convenience/"combined" method.

This API is from when, as I understand it, we wanted to have parity in the Rust/TS API. Since we decided against that recently, we can start thinking whether we want it or not on Rust side (AIUI it's more performant to keep that on TS side).

My first reaction was the same as yours, i.e as_{rule,token}_matching is probably redundant on the Rust side, now that we have introduced convenience as_{rule,token} at some point.

I do see some point in the convenience _with_kind functions, as as_{rule,token}_with_kind reads and formats better than the as_{rule,token}().filter(|node| &[some,kinds].contains(node.kind)) chain. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

I like these semantically rich apis that match common use cases. I'm also happy to have them in a separate trait, such as RichXXXAPI or EnhancedXXX etc, simply for the sake of having a 'core' minimal API and then a layered convenience API.

Copy link
Contributor

Choose a reason for hiding this comment

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

Specifically because it reads well in the code to express clearly the higher-level intent. And I like descriptive precise names, with no concern at all about the length of names.

Copy link
Contributor

Choose a reason for hiding this comment

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

For as_rule_matching(...) .. I wonder how is that different from .as_rule().filter(...), given it is the same characters/effort to type?

Same to type, but less to understand.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I do see some point in the convenience _with_kind functions, as as_{rule,token}_with_kind reads and formats better than the as_{rule,token}().filter(|node| &[some,kinds].contains(node.kind)) chain. WDYT?

Same to type, but less to understand.

@Xanewok @AntonyBlakey

with_kind() makes sense. The alternative doesn't have a good Rust standard library alternative, and I imagine it is a common use case, enough to have a helper for.

But on the other hand, as_rule_matching() here is longer than the Rust standard library alternative (.as_rule().filter()), which most Rust users are already familiar with, and is used extensively in all projects, so I feel we are only replacing the language built-in API with a longer/less idiomatic one, that is not really easier to use (both accept the same kind of callback).

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree, I'm not so sure about the _matching variant, especially since as(...).filter(...) does the same and filter is bread-and-butter idiomatic Rust.

I can understand the readability context a bit but then again, if it's not using the std impls then that might imply something non-standard, actually.

I'm fine either way, to be honest!

crates/codegen/parser/runtime/src/cst.rs Show resolved Hide resolved
crates/codegen/parser/runtime/src/cst.rs Show resolved Hide resolved
crates/codegen/parser/runtime/src/support/parser_result.rs Outdated Show resolved Hide resolved
@Xanewok Xanewok changed the title Add Node::reconstruct and tweak the cursor creation API Add Node::unparse and tweak the cursor creation API Nov 21, 2023
Copy link
Collaborator

@OmarTawfik OmarTawfik left a comment

Choose a reason for hiding this comment

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

Left one suggestion about removing as_XXX_matching(), but otherwise, LGTM!

This is more vanilla and we didn't really use those internally
ourselves, so I'm not sure if there's much benefit for those.

We can reintroduce a `NodeHelpers` trait in the future that has that
convenience API.
@Xanewok
Copy link
Member Author

Xanewok commented Nov 22, 2023

I think it makes sense to drop the individual as_*matching() for the tokens/rules, as as_*() followed by filter() should be equally readable for a Rust reader and this means there are less surprises (we're using std combinators) comparing to, let's say, Cursor's find_*_matching that does not consume the first item, unlike std::iter::Iterator::find.

@Xanewok Xanewok added this pull request to the merge queue Nov 22, 2023
Merged via the queue into NomicFoundation:main with commit 0434b68 Nov 22, 2023
1 check passed
@Xanewok Xanewok deleted the cursor-tweaks branch November 22, 2023 11:47
@github-actions github-actions bot mentioned this pull request Nov 22, 2023
github-merge-queue bot pushed a commit that referenced this pull request Dec 14, 2023
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @nomicfoundation/slang@0.12.0

### Minor Changes

- [#699](#699)
[`ddfebfe9`](ddfebfe)
Thanks [@Xanewok](https://github.com/Xanewok)! - Remove `ProductionKind`
in favor of `RuleKind`

- [#699](#699)
[`ddfebfe9`](ddfebfe)
Thanks [@Xanewok](https://github.com/Xanewok)! - Allow parsing
individual precedence expressions, like `ShiftExpression`

- [#665](#665)
[`4b5f8b46`](4b5f8b4)
Thanks [@Xanewok](https://github.com/Xanewok)! - Remove the CST Visitor
API in favor of the Cursor API

- [#666](#666)
[`0434b68c`](0434b68)
Thanks [@Xanewok](https://github.com/Xanewok)! - Add `Node::unparse()`
that allows to reconstruct the source code from the CST node

- [#675](#675)
[`daea4b7f`](daea4b7)
Thanks [@OmarTawfik](https://github.com/OmarTawfik)! - rename `Cursor`'s
`pathRuleNodes()` to `ancestors()` in the NodeJS API.

- [#676](#676)
[`b496d361`](b496d36)
Thanks [@OmarTawfik](https://github.com/OmarTawfik)! - Fix NAPI `cursor`
types and expose `cursor.depth`.

### Patch Changes

- [#685](#685)
[`b5fca94a`](b5fca94)
Thanks [@Xanewok](https://github.com/Xanewok)! - `bytes` is now properly
recognized as a reserved word

- [#660](#660)
[`97028991`](9702899)
Thanks [@Xanewok](https://github.com/Xanewok)! - Drop List suffix from
collection grammar rule names

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cursor/Node API suggestions
3 participants