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

Visitor generation #4

Open
LPeter1997 opened this issue Jul 31, 2022 · 0 comments
Open

Visitor generation #4

LPeter1997 opened this issue Jul 31, 2022 · 0 comments
Labels
enhancement New feature or request text generation Relating to text generation and Scriban templates

Comments

@LPeter1997
Copy link
Collaborator

One of the key features of the Nanopass framework is automating the "boring-parts" of transformation between passes. I think our equivalent could be a generated visitor base class for each pass. By default, it would do a catamorphic transformation on unchanged nodes - that you can still override, if you need -, and would require the user to write the ones that were affected.

For example, let's say we have this AST:

// Pass 1
record Expr
{
    record Unit : Expr;
    record IfElse(Expr Cond, Expr Then, Expr Else) : Expr;
    record If(Expr Cond, Expr Then) : Expr;
    record Name(string Id) : Expr;
}

And then we do the following modifications:

Remove the 'If' node
Add the member 'ISymbol Symbol' to 'Name'
Remove the member 'Id' from 'Name'

Then the next generated AST would look like:

// Pass 2
record Expr
{
    record Unit : Expr;
    record IfElse(Expr Cond, Expr Then, Expr Else) : Expr;
    record Name(ISymbol Symbol) : Expr;
}

And the generated visitor base could be:

abstract class Pass1ToPass2Base
{
    // Generate dispatch functionality
    public Pass2.Expr Apply(Pass1.Expr expr) => expr switch
    {
        Pass1.Expr.Unit e => Apply(e),
        Pass1.Expr.IfElse e => Apply(e),
        Pass1.Expr.If e => Apply(e),
        Pass1.Expr.Name e => Apply(e),
        _ => throw new InvalidOperationException(),
    };

    // Unchanged nodes are just translated trivially
    // The user can still override them, if needed

    public virtual Pass2.Expr Apply(Pass1.Expr.Unit e) => new Pass2.Expr.Unit();

    public virtual Pass2.Expr Apply(Pass1.Expr.IfElse e) => new Pass2.Expr.IfElse(
        Apply(e..Cond),
        Apply(e.Then),
        Apply(e.Else));

    // Changed or removed nodes are required to be handled by the user

    public abstract Pass2.Expr Apply(Pass1.Expr.If e);

    public abstract Pass2.Expr Apply(Pass1.Expr.Name e);
}

Then all the user needs to implement is:

class Pass1ToPass2 : Pass1ToPass2Base
{
    public override Pass2.Expr Apply(Pass1.Expr.If e) => new Pass1.Expr.IfElse(
        Apply(e..Cond),
        Apply(e.Then),
        new Pass2.Expr.Unit());

    public override Pass2.Expr Apply(Pass1.Expr.Name e) => /* ... */;
}
@thinker227 thinker227 added enhancement New feature or request text generation Relating to text generation and Scriban templates labels Jul 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request text generation Relating to text generation and Scriban templates
Projects
None yet
Development

No branches or pull requests

2 participants