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

web-tree-sitter should allow custom predicates #2904

Open
savetheclocktower opened this issue Feb 3, 2024 · 0 comments
Open

web-tree-sitter should allow custom predicates #2904

savetheclocktower opened this issue Feb 3, 2024 · 0 comments
Labels
enhancement Feature request wasm
Milestone

Comments

@savetheclocktower
Copy link
Contributor

I’ve had this in my head for a while, but it’s time to write it down.

I’ve worked almost entirely with web-tree-sitter. But I’ve seen how other bindings have a larger variety of query predicates, and I’ve also noticed that Nova has written a whole bunch of custom predicates. I’m jealous.

If Pulsar could define our own predicates for web-tree-sitter, the main wins for us would be

  1. the ability to restrict a custom predicate to one and only one capture; and
  2. the ability to define predicates that take several arguments.

In Pulsar we’ve managed to implement our custom predicates via #is?, #is-not? and #set!. Those three predicates set keys and values on a capture object so that, while inspecting query results, we can use that metadata to make decisions. That’s the whole point of those predicates, as I gather, and we’re largely satisfied with this functionality.

But none of the three accepts a capture as an argument — unlike #match?, #eq?, and most others — which means they’re tested against each capture in a query, whether or not that’s what the user wants.

Likewise, since these three predicates are locked into two arguments — key and value — we’ve had to overload the value argument in cases where we’d much rather keep separate arguments.

; Test if a boolean setting is enabled (no second argument needed)
(#is? test.config "some-package.indentation.enabled")

; Test if a setting has a specific string value
; (split the argument after the first space and interpret the rest as the value)
(#is? test.config "some-package.braceStyle 1tbs")

If we felt there were absolutely no possibility of custom predicates in web-tree-sitter, we’d reluctantly overload one of these two arguments even more just to gain the ability to apply a predicate to only one capture:

; Test that the node captured by `@punctuation` is descended from a `string`
; node (automatically passing the test when inspecting captures with other
; names)
(#is? test.descendantOfNode "@punctuation/string")

; Or maybe this would be slightly better? Still icky, though:
(#is? "test.descendantOfNode/@punctuation" "string")

But we’re holding off on that sort of thing because we have no interest in introducing a convention that unusual if we don’t have to.

Also, as you can see, the fact that these predicates are accessed via #is? and #set! — both of which can be used for more general purposes — means that we’ve felt compelled to introduce a “namespace” for each kind of predicate so as to separate them from arbitrary data that could be set for other purposes. That wouldn’t be necessary if we could define custom predicates.

A theoretical upside here would be the ability to filter the capture results before they’re returned. After all, if a capture failes a #match? predicate, it’s omitted from the capture results — whereas inspecting assertedProperties and refutedProperties involves a second phase of winnowing.

In Pulsar’s case, that’s barely even a consideration — we’d have to do “post-processing” of a query even if we didn’t have to filture the returned captures. (In fact, at first I imagine that our custom predicates would simply store data on the capture objects to be inspected later — just with more contextual information.) But I imagine some other possible applications would get value from this.

If we were willing to fork web-tree-sitter altogether, we could “fix” this tomorrow. But I’m more interested in doing something truly modular instead of hard-coding a few more cases into a switch statement.

As I have time, I’ll revisit this issue and perhaps make some suggestions about what this API could look like. But right now I’m just interested in getting the idea out there on folks’ radars.

@ObserverOfTime ObserverOfTime added enhancement Feature request wasm labels Apr 12, 2024
@ObserverOfTime ObserverOfTime added this to the 1.0 milestone Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature request wasm
Projects
None yet
Development

No branches or pull requests

2 participants