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

Track AST node between passes #30

Closed
Boshen opened this issue Jun 3, 2024 · 4 comments
Closed

Track AST node between passes #30

Boshen opened this issue Jun 3, 2024 · 4 comments

Comments

@Boshen
Copy link
Member

Boshen commented Jun 3, 2024

In Rolldown, ast node information needs to be tracked across scans and transforms.

It's currently using spans to track the nodes, but once transformation is in, newly inserted statements does not have a SPAN so information is lost, and Rolldown will not function anymore :-(


From hyf: how to identity the same ast node in different visit passes

There's workaround for rolldown to use faked span that out of orignal text's length.
But this require oxc could handle span that is out of original source's length

@Boshen Boshen changed the title AST node ID / Track AST node between passes Track AST node between passes Jun 3, 2024
@overlookmotel
Copy link

overlookmotel commented Jun 3, 2024

As discussed in meet just now, I can see solutions to this which doesn't require AST node IDs.

1. Record "path" to node

e.g. body[3] or body[5].expression.left.

For import / export statements, recording the "path" is simple as they're always top-level statements. So all you need is the statement index. For import.meta or dynamic import(), it's less good as these expressions can be anywhere in the AST so the path can be deep. But still probably faster than searching the entire AST for a Span.

NB: "path" would not be stored as a string, but as a Vec<PathSegment> where PathSegment is an enum. Something like:

struct Path(Vec<PathSegment>);

enum PathSegment {
  ProgramBody(u32),
  ProgramDirective(u32),
  ProgramHashtag,
  ExpressionStatementExpression,
  BinaryExpressionLeft,
  BinaryExpressionRight,
  /* ... lots more ... */
}

fn statement_from_path_mut<'a, 'p>(program: &'p mut Program<'a>, path: &Path) -> &'p mut Statement<'a> {
  todo!();
}

fn expression_from_path_mut<'a, 'p>(program: &'p mut Program<'a>, path: &Path) -> &'p mut Expression<'a> {
  todo!();
}

2. Record *mut pointer to node

This would be faster as you can jump direct to the node without any searching/traversing the AST. But would need quite a bit of thought to make a safe API.

@Boshen
Copy link
Member Author

Boshen commented Jun 3, 2024

Our semantic pass already generates an ast node id in AstNode 🤔

@overlookmotel
Copy link

Yes, but that part of semantic is not usable when the AST is mutable, due to aliasing restrictions. This is why Traverse runs semantic, but then throws away the part of Semantic which contains AstNodes - borrow checker won't allow keeping it.

@Boshen
Copy link
Member Author

Boshen commented Jul 11, 2024

Tracking in oxc-project/oxc#4188 for research on AST Node ID.

@Boshen Boshen closed this as completed Jul 11, 2024
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

No branches or pull requests

2 participants