Skip to content

Ghost4Man/VisitorPatternGenerator

 
 

Repository files navigation

VisitorPatternGenerator

GitHub Nuget Nuget

C# Roslyn (incremental) source generator to help implement the visitor design pattern.

Fork

This fork (of Rekkonnect's fork of hikarin522/VisitorPatternGenerator) adds support for record types.

Usage

Example of simple integer expressions:

partial interface IExpr;
[Acceptor<IExpr>] partial record NumberLiteral(int Value) : IExpr;
[Acceptor<IExpr>] partial record BinaryOperation(IExpr Left, char Operator, IExpr Right) : IExpr;
[Acceptor<IExpr>] partial record FunctionCall(string Function, IExpr[] Args) : IExpr;

[Visitor<IExpr>] partial interface IExprVisitor<out TResult>;
[Visitor<IExpr>] partial interface IExprVisitor<in TArg, out TResult>;
[Visitor<IExpr>(voidReturn: true)] partial interface IExprVoidVisitor;
[Visitor<IExpr>(voidReturn: true)] partial interface IExprVoidVisitor<in TArg>;

and a visitor that evaluates them:

class ExpressionEvaluator : IExprVisitor<int>
{
    public int Visit(NumberLiteral expr) => expr.Value;

    public int Visit(BinaryOperation expr) => expr.Operator switch {
        '+' => expr.Left.Accept(this) + expr.Right.Accept(this),
        '*' => expr.Left.Accept(this) * expr.Right.Accept(this),
    };

    public int Visit(FunctionCall expr) => expr switch {
        ("max", [IExpr a, IExpr b]) => Math.Max(a.Accept(this), b.Accept(this)),
    };
}

used like this:

IExpr expr = new FunctionCall("max", [
    new NumberLiteral(0),
    new BinaryOperation(new NumberLiteral(40), '+', new NumberLiteral(2))
]);
var visitor = new ExpressionEvaluator();
Console.WriteLine($"Result: {expr.Accept(visitor)}");

For more samples, see https://github.com/hikarin522/VisitorPatternGenerator/tree/master/Sample/

Packages

No packages published

Languages

  • C# 99.7%
  • Other 0.3%