Skip to content

Compile-time kind and field ids that are generated by binding generation.  #3276

@VonTum

Description

@VonTum

Problem

So while it's possible to use Language::id_for_node_kind and Language::field_id_for_name to request ids for kinds and fields, these are runtime functions. This means that it is not possible to use these in compile-time contexts, such as in match arms. It would be cleaner to provide some macros or compile time constants to allow getting these values for these contexts, and removes the need to write a mess like this. As an added benefit, compile time ids allow for more optimizations to code walking the tree 😄

I was able to build such proc_macros myself for my own language 'SUS', and they work wonderfully. Perhaps it would be a good idea to incorporate this into mainline tree-sitter?

Expected behavior

It should be possible to write code like this:

use mylang::{kind,kw,field};

fn test_fn(cursor : &TreeCursor) {
  if cursor.field() == field!("sub_expr") {
    let node = cursor.node();
    match node.kind_id() {
      kind!("array_expr") => {},
      kind!("binary_expr") => {},
      kind!("unary_expr") => {},
      // etc
    }
  }
}

So proc_macros such as these need to be part of a separate crate. During my discussion with @WillLillis on this issue, we found it difficult to find a good spot to place this new crate.

Sadly it cannot be part of the tree_sitter core crate. It has to be part of the generated code, since for the proc macros to work they need to have the user's Language as a dependency. Sadly again, we couldn't simply include such proc macros into the generated bindings crate itself, because rust makes a strict distinction between proc_macro and non-proc_macro crates. No other functions are allowed in non-proc_macro crates.

That leaves the issue of where to put it. Following the directory structure, we'd need to put them in tree-sitter-myLang/bindings/rust/proc/Cargo.toml, but this is ugly, and brittle. Not to mention it requires having a dependency that goes up the file tree instead of down.

We also discussed simply adding it on the root of the myLang folder, but that's cluttering up that folder further. If you can make a decision on where and how it should be placed, I'd be happy to create a PR to implement it.

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions