module jlox.expr; import std.conv; import std.stdio; import std.meta : AliasSeq; import taggedalgebraic; import jlox.token; import jlox.tokentype; import jlox.util; abstract class Expr{ interface Visitor(R){ R visit(Assign expr); R visit(Binary expr); R visit(Grouping expr); R visit(Literal expr); R visit(Logical expr); R visit(Unary expr); R visit(Variable expr); } private alias rTypes = AliasSeq!(string, TValue); static foreach(T; rTypes) abstract T accept(Visitor!T visitor); private template defCtorAndAccept(){ mixin defaultCtor; static foreach(T; rTypes) override T accept(Visitor!T visitor) => visitor.visit(this); } static class Assign : typeof(this){ Token name; Expr value; mixin defCtorAndAccept; } static class Binary : typeof(this){ Expr left; Token operator; Expr right; mixin defCtorAndAccept; } static class Grouping : typeof(this){ Expr expression; mixin defCtorAndAccept; } static class Literal : typeof(this){ TValue value; mixin defCtorAndAccept; } static class Logical : typeof(this){ Expr left; Token operator; Expr right; mixin defCtorAndAccept; } static class Unary : typeof(this){ Token operator; Expr right; mixin defCtorAndAccept; } static class Variable : typeof(this){ Token name; mixin defCtorAndAccept; } } /* class AstPrinter : Expr.Visitor!string{ */ /* string print(Expr expr){ */ /* return expr.accept(this); */ /* } */ /* string parenthesize(Args...)(string name, Args args){ */ /* string s = "(" ~ name; */ /* static foreach(expr; args){ */ /* s ~= " "; */ /* s ~= expr.accept(this); */ /* } */ /* return s ~ ")"; */ /* } */ /* string visit(Expr.Binary expr){ */ /* return parenthesize(expr.operator.lexeme, expr.left, expr.right); */ /* } */ /* string visit(Expr.Grouping expr){ */ /* return parenthesize("group", expr.expression); */ /* } */ /* string visit(Expr.Literal expr){ */ /* if(expr.value.isNil) */ /* return "nil"; */ /* return expr.value.to!string; */ /* } */ /* string visit(Expr.Unary expr){ */ /* return parenthesize(expr.operator.lexeme, expr.right); */ /* } */ /* } */