oxc-project / oxc-project/backlog

Visit GAT (Generic Associated Types) + Fold pattern

Open
#90 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
7
Forks
0
PR merge metrics
No merged PRs in 30d

Description

A bit of context before you read this: oxc-project/backlog#184

I'm working on the AST template macro, My current approach is something like this:

a. use oxc_ast_codegen to generate a visitor with support for every visitable AST type(placed at oxc_ast_quote/src/generated/{here}) that would:

  1. accept an interop resolver or map
  2. visit each node
  3. visit inner nodes to get their TokenStream
  4. produce a TokenStream to create that node at runtime
  5. short circuit on literals and enums that are either unit or wrapping literals

b. proc-macro

  1. substitute and map the interpolation spans to their inner value(which would support identifiers for now but it can be extended to accept rust expressions as well)
    i. In the initial implementation we use raw string manipulation here
    ii. as our next step we can add support for QuoteInterpolation in our parser with an ast_quote_parser feature to prevent multiple iterations on the source code(but with caching, we might not need this).
  2. parse the macro input with oxc_parser
  3. check for errors and retrieve the valid program
  4. use the visitor generated in step a to create something like Statement(BlockStatement { ... })
  5. add support for generating tracing boilerplate to mimic what ast_builder would've done before as our single point of construction(e.g. counting allocations in debug builds)

As you might already see it feels like a good place to introduce the Fold pattern to our arsenal, So I'm re-proposing one of my old suggestions which is adding a generic associated type Result to both Visit and VisitMut this way we won't need a new visiting paradigm while being able to selectively return from our visitor implementations.

It goes like this:

pub trait VisitResult: Default {
    fn extend(&mut self, next: Self);
}

impl VisitResult for () {
    fn extend(&mut self, next: Self) {}
}

pub trait Visit<'a>: Sized {
    type Result: VisitResult;

    fn visit_program(&mut self, it: &Program<'a>) -> Self::Result {
        walk_program(self, it)
    }
    // ...
}

pub fn walk_program<...>(visitor: V, it: &Program<'a>) -> V::Result {
    let mut result = V::Result::default();
    let kind = AstKind::Program(visitor.alloc(it));
    visitor.enter_node(kind);
    visitor.enter_scope(
        {
            let mut flags = ScopeFlags::Top;
            if it.source_type.is_strict() || it.directives.iter().any(Directive::is_use_strict)
            {
                flags |= ScopeFlags::StrictMode;
            }
            flags
        },
        &it.scope_id,
    );
    result.extend(visitor.visit_directives(&it.directives));
    if let Some(hashbang) = &it.hashbang {
        result.extend(visitor.visit_hashbang(hashbang));
    }
    result.extend(visitor.visit_statements(&it.body));
    visitor.leave_scope();
    visitor.leave_node(kind);
    result
}

Our current implementations would only need to add this one line:

impl<'a> Visit<'a> for X {
    type Result = ();
    // ...
}

A similar implementation in rustc.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the context in oxc-project/backlog#184 and compare the proposed VisitResult and GAT Result design with rustc's compiler/rustc_ast/src/visit.rs. Trace the existing Visit and VisitMut implementations before deciding whether the Fold pattern fits; done means a resolved design and corresponding visitor changes with current implementations preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.