diff --git a/Makefile b/Makefile index d6ea18e..fe803f5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ -CC=g++ -CFLAGS=-g -Wall +CC=clang++ +CXXFLAGS=-g -Wall +LDFLAGS=$(shell llvm-config --cxxflags --ldflags --system-libs --libs core) SRC=$(wildcard *.cc) HEADERS=$(wildcard *.h) OBJS=$(SRC:.cc=.o) @@ -15,10 +16,10 @@ token_convert.h: token.h token.cc: token_convert.h %.o: %.cc $(HEADERS) - $(CC) -c $(CFLAGS) $< -o $@ + $(CC) -c $(CXXFLAGS) $< -o $@ $(OBJNAME): $(OBJS) $(BUILD_DIR) - $(CC) $(CFLAGS) $(OBJS) -o $(OBJNAME) + $(CC) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(OBJNAME) clean: rm -rf $(OBJS) $(OBJNAME) diff --git a/ast.cc b/ast.cc index b8da608..05eab22 100644 --- a/ast.cc +++ b/ast.cc @@ -32,251 +32,6 @@ Double::operator std::string() { String::operator std::string() { return "\"" + value + "\""; } -void PrintVisitor::visit(Expr* expr) { std::cout << (string)*expr; } -void PrintVisitor::visit(Literal* expr) { std::cout << (string)*expr; } -void PrintVisitor::visit(Unary* expr) { std::cout << (string)*expr; } -void PrintVisitor::visit(Binary* expr) { std::cout << (string)*expr; } -void PrintVisitor::visit(Variable* expr) { std::cout << (string)*expr; } - -void EvalVisitor::visit(Expr* expr) { expr->accept(this); } -void EvalVisitor::visit(Literal* expr) { value = expr; } -void EvalVisitor::visit(Unary* expr) { - EvalVisitor v(context); - v.visit(expr->child); - Expr* e = v.value; - Integer* n = dynamic_cast(e); - Boolean* b = dynamic_cast(e); - Variable* var = dynamic_cast(expr->child); - switch (expr->op.tokenType) { - case MINUS: - value = new Integer(-n->value); - break; - case BANG: - value = new Boolean(!b->isTruthy()); - break; - case PLUSPLUS: - assert(var); - value = new Integer(n->value + 1); - context.set(var->name, value); - break; - case MINUSMINUS: - assert(var); - value = new Integer(n->value - 1); - context.set(var->name, value); - break; - default: - throw RuntimeError(); - break; - } -} - -void EvalVisitor::visit(Postfix* expr) { - EvalVisitor v(context); - v.visit(expr->child); - Expr* e = v.value; - Integer* n = dynamic_cast(e); - Variable* var = dynamic_cast(expr->child); - assert(n); - assert(var); - switch (expr->op.tokenType) { - case PLUSPLUS: - value = new Integer(n->value); - context.set(var->name, new Integer(n->value + 1)); - break; - case MINUSMINUS: - value = new Integer(n->value); - context.set(var->name, new Integer(n->value - 1)); - break; - default: - throw RuntimeError(); - break; - } -} - -void EvalVisitor::visit(Call* call) { - EvalVisitor v(context); - v.visit(call->callee); - Function* fun = dynamic_cast(v.getValue()); - if (fun == nullptr) { - std::cerr << "call on non-callable object"; - exit(-1); - } - FunDecl* d = fun->fun; - auto formal = d->getArgs(); - auto real = call->args; - if (formal.size() != real.size()) { - std::cerr << "call with wrong arugments, expected " << formal.size() - << " , got " << real.size(); - exit(-1); - } - - ExecContext ctx = context.wrapWithReason(new ReturnResult()); - ExecVisitor ev(ctx); - - for (size_t i = 0; i < formal.size(); i++) { - v.visit(real[i]); - auto value = v.getValue(); - ctx.define(formal[i].token.lexeme, value); - } - ev.visit(d->getBody()); - - auto r = ctx.getReason(); - assert(r.reason == ReturnReason::RETURN || r.reason == ReturnReason::NORMAL); - value = r.value; -} - -void EvalVisitor::visit(Binary* expr) { - EvalVisitor v1(context), v2(context); - v1.visit(expr->left); - v2.visit(expr->right); - Integer* n1 = dynamic_cast(v1.value); - Integer* n2 = dynamic_cast(v2.value); - Double* d1 = dynamic_cast(v1.value); - Double* d2 = dynamic_cast(v2.value); - String* s1 = dynamic_cast(v1.value); - String* s2 = dynamic_cast(v2.value); - Boolean* b1 = dynamic_cast(v1.value); - Boolean* b2 = dynamic_cast(v2.value); - Variable* lv = dynamic_cast(expr->left); - Literal* rv = v2.value; - - if ((d1 || d2) && !(d1 && d2)) { - if (!d1) { - if (n1) { - d1 = Converter::converToDouble(n1); - n1 = nullptr; - } else - throw TypeError(); - } - if (!d2) { - if (n2) { - d2 = Converter::converToDouble(n2); - n2 = nullptr; - } else - throw TypeError(); - } - } - - switch (expr->op.tokenType) { - case PLUS: - if (n1 && n2) { - value = new Integer(n1->value + n2->value); - } else if (d1 && d2) { - value = new Double(d1->value + d2->value); - } else if (s1 && s2) { - value = new String(s1->value + s2->value); - } else { - throw TypeError(); - } - break; - case MINUS: - if (n1 && n2) { - value = new Integer(n1->value - n2->value); - } else if (d1 && d2) { - value = new Double(d1->value - d2->value); - } else { - throw TypeError(); - } - break; - case STAR: - if (n1 && n2) { - value = new Integer(n1->value * n2->value); - } else if (d1 && d2) { - value = new Double(d1->value * d2->value); - } else { - throw TypeError(); - } - break; - case SLASH: - if (n1 && n2) { - value = new Integer(n1->value / n2->value); - } else if (d1 && d2) { - value = new Double(d1->value / d2->value); - } else { - throw TypeError(); - } - break; - case EQUAL: - if (lv->isLval() && !rv->isLval()) { - context.set(lv->name, rv); - } else { - throw BindError(); - } - break; - case EQUAL_EQUAL: - if (n1 && n2) { - value = new Boolean(n1->value == n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value == d2->value); - } else if (b1 && b2) { - value = new Boolean(b1->value == b2->value); - } else { - throw TypeError(); - } - break; - case BANG_EQUAL: - if (n1 && n2) { - value = new Boolean(n1->value != n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value != d2->value); - } else if (b1 && b2) { - value = new Boolean(b1->value != b2->value); - } else { - throw TypeError(); - } - break; - case LESS: - if (n1 && n2) { - value = new Boolean(n1->value < n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value < d2->value); - } else { - throw TypeError(); - } - break; - case LESS_EQUAL: - if (n1 && n2) { - value = new Boolean(n1->value <= n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value <= d2->value); - } else { - throw TypeError(); - } - break; - case GREATER: - if (n1 && n2) { - value = new Boolean(n1->value > n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value > d2->value); - } else { - throw TypeError(); - } - break; - case GREATER_EQUAL: - if (n1 && n2) { - value = new Boolean(n1->value >= n2->value); - } else if (d1 && d2) { - value = new Boolean(d1->value >= d2->value); - } else { - throw TypeError(); - } - break; - default: - std::cerr << "Unexpected binary operator " << expr->op.lexeme; - throw RuntimeError(); - break; - } -} - -void EvalVisitor::visit(Variable* expr) { - if (!context.count(expr->name)) { - std::cerr << "Cannot find var " << expr->name << " in the context\n"; - exit(-1); - } - value = dynamic_cast(context.get(expr->name)); - assert(value); -} - Integer::Integer(Token token) { std::stringstream ss(token.lexeme); ss >> value; @@ -288,110 +43,3 @@ Double::Double(Token token) { } Boolean::operator std::string() { return value ? "true" : "false"; } - -bool String::isTruthy() { return value.size(); } - -bool Integer::isTruthy() { return value; } - -bool Double::isTruthy() { - static const double EPS = 1e-6; - return abs(value) < EPS; -} - -ExecVisitor ExecVisitor::wrap() { return ExecVisitor(context.wrap()); } -ExecVisitor ExecVisitor::wrapWithReason() { - return ExecVisitor(context.wrapWithReason(new ReturnResult())); -} - -void ExecVisitor::visit(Declaration* s) { s->accept(this); } -void ExecVisitor::visit(PrintStmt* s) { - EvalVisitor v(context); - v.visit(s->expr); - Expr* e = v.getValue(); - - std::cout << std::string(*e) << std::endl; -} -void ExecVisitor::visit(AssertStmt* s) { - EvalVisitor v(context); - v.visit(s->expr); - Literal* e = v.getValue(); - if (!e->isTruthy()) { - std::cerr - << "Lox builtin assert failed! The following expression is not true:\n"; - std::cerr << std::string(*s->expr) << std::endl; - exit(-1); - } -} -void ExecVisitor::visit(ExprStmt* s) { - EvalVisitor v(context); - v.visit(s->expr); -} -void ExecVisitor::visit(VarDecl* s) { - EvalVisitor v(context); - v.visit(s->init); - assert(v.getValue() != nullptr); - Literal* l = v.getValue(); - if (s->type.base == Type::Base::INT) { - l = dynamic_cast(v.getValue()); - if (!l) abortMsg("type mismatched when initialize. requires int"); - } else if (s->type.base == Type::Base::DOUBLE) { - l = Converter::converToDouble(v.getValue()); - } - assert(l); - context.define(s->identifier, l); -} - -void ExecVisitor::visit(FunDecl* s) { - if (context.count(s->identifier)) { - std::cerr << "redefine function " << s->identifier; - exit(-1); - } - context.define(s->identifier, new Function(s)); -} - -void ExecVisitor::visit(BlockStmt* s) { - ExecVisitor v = wrap(); - for (auto d : s->decls) { - v.visit(d); - if (v.context.getReason().reason != ReturnReason::NORMAL) break; - } -} - -void ExecVisitor::visit(IfStmt* s) { - EvalVisitor ev(context); - ev.visit(s->condition); - Literal* l = ev.getValue(); - assert(l); - - ExecVisitor v = wrap(); - if (l->isTruthy()) { - v.visit(s->true_branch); - } else if (s->false_branch) { - v.visit(s->false_branch); - } -} - -void ExecVisitor::visit(WhileStmt* s) { - ExecVisitor v = wrapWithReason(); - EvalVisitor ev(context); - while (1) { - ev.visit(s->condition); - Literal* l = ev.getValue(); - assert(l); - if (!l->isTruthy()) break; - v.visit(s->body); - auto r = v.context.getReason().reason; - if (r == ReturnReason::BREAK || r == ReturnReason::RETURN) break; - } -} - -void ExecVisitor::visit(BreakStmt* s) { - context.setReason({ReturnReason::BREAK}); -} - -void ExecVisitor::visit(ReturnStmt* s) { - if (!s->expr) return; - EvalVisitor ev(context); - ev.visit(s->expr); - context.setReason({ReturnReason::RETURN, ev.getValue()}); -} diff --git a/ast.h b/ast.h index e9e672c..81c6d61 100644 --- a/ast.h +++ b/ast.h @@ -3,109 +3,11 @@ #include #include -#include "context.h" #include "token.h" #include "type.h" - -class Expr; -class Literal; -class Binary; -class Unary; -class Postfix; -class Variable; -class Call; - -class Declaration; -class VarDecl; -class FunDecl; - -class Statement; -class AssertStmt; -class PrintStmt; -class ExprStmt; -class BlockStmt; -class IfStmt; -class ForStmt; -class WhileStmt; -class BreakStmt; -class ReturnStmt; +#include "visitor.h" class Converter; - -class DeclVisitor { - public: - virtual void visit(Declaration* d) = 0; - - virtual void visit(ExprStmt* st) = 0; - virtual void visit(AssertStmt* st) = 0; - virtual void visit(PrintStmt* st) = 0; - virtual void visit(VarDecl* d) = 0; - virtual void visit(FunDecl* d) = 0; - virtual void visit(BlockStmt* d) = 0; - virtual void visit(IfStmt* d) = 0; - virtual void visit(WhileStmt* d) = 0; - virtual void visit(BreakStmt* d) = 0; - virtual void visit(ReturnStmt* d) = 0; -}; - -class ExecVisitor : public DeclVisitor { - ExecContext context; - - public: - ExecVisitor(ExecContext context) : context(context){}; - // Return a ExecVisitor with an inner block scopping - ExecVisitor wrap(); - ExecVisitor wrapWithReason(); - virtual void visit(Declaration* d) override; - - virtual void visit(ExprStmt* st) override; - virtual void visit(AssertStmt* st) override; - virtual void visit(PrintStmt* st) override; - virtual void visit(VarDecl* d) override; - virtual void visit(FunDecl* d) override; - virtual void visit(BlockStmt* d) override; - virtual void visit(IfStmt* d) override; - virtual void visit(WhileStmt* d) override; - virtual void visit(BreakStmt* d) override; - virtual void visit(ReturnStmt* d) override; -}; - -class ExprVisitor { - public: - virtual void visit(Expr* expr) = 0; - virtual void visit(Literal* expr) = 0; - virtual void visit(Binary* expr) = 0; - virtual void visit(Unary* expr) = 0; - virtual void visit(Postfix* expr) = 0; - virtual void visit(Variable* expr) = 0; - virtual void visit(Call* expr) = 0; -}; - -class PrintVisitor : public ExprVisitor { - public: - void visit(Expr* expr); - void visit(Literal* expr); - void visit(Binary* expr); - void visit(Unary* expr); - void visit(Variable* expr); -}; - -class EvalVisitor : public ExprVisitor { - ExecContext context; - Literal* value = nullptr; - - public: - EvalVisitor(ExecContext context) : context(context){}; - void visit(Expr* expr); - void visit(Literal* expr); - void visit(Binary* expr); - void visit(Unary* expr); - void visit(Postfix* expr); - void visit(Variable* expr); - void visit(Call* expr); - Literal* getValue() { return value; } -}; - class Expr { public: virtual operator std::string() = 0; @@ -128,8 +30,8 @@ class ExprStmt : public Statement { ExprStmt(Expr* expr) : expr(expr){}; operator std::string() override { return std::string(*expr); }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class PrintStmt : public Statement { @@ -140,8 +42,8 @@ class PrintStmt : public Statement { PrintStmt(Expr* expr) : expr(expr){}; operator std::string() override { return "print " + std::string(*expr); }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class AssertStmt : public Statement { @@ -152,8 +54,8 @@ class AssertStmt : public Statement { AssertStmt(Expr* expr) : expr(expr){}; operator std::string() override { return "assert " + std::string(*expr); }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; typedef std::vector Program; @@ -169,8 +71,8 @@ class BlockStmt : public Statement { return "{ " + content + " }"; } - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class IfStmt : public Statement { @@ -186,8 +88,8 @@ class IfStmt : public Statement { operator std::string() override { return "ifstmt"; }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class WhileStmt : public Statement { @@ -200,16 +102,16 @@ class WhileStmt : public Statement { : condition(condition), body(body){}; operator std::string() override { return "whilestmt"; }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class BreakStmt : public Statement { public: operator std::string() override { return "break"; }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class ReturnStmt : public Statement { @@ -220,8 +122,8 @@ class ReturnStmt : public Statement { operator std::string() override { return "return"; }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; class VarDecl : public Declaration { @@ -237,8 +139,8 @@ class VarDecl : public Declaration { return "var " + identifier + " = " + std::string(*init); }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; struct FormalArg { @@ -264,8 +166,8 @@ class FunDecl : public Declaration { Args getArgs() const { return args; }; BlockStmt* getBody() const { return body; }; - void accept(DeclVisitor* v) { v->visit(this); } - friend class ExecVisitor; + void accept(DeclVisitor* v) override { v->visit(this); } + friend class PrintVisitor; }; typedef std::vector RealArgs; @@ -275,10 +177,10 @@ class Call : public Expr { public: Call(Expr* callee, RealArgs args) : callee(callee), args(args){}; - operator std::string() { return "callable"; }; + operator std::string() override { return "callable"; }; bool isLval() const override { return false; } - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; }; @@ -291,10 +193,10 @@ class Binary : public Expr { public: Binary(Expr* left, Token op, Expr* right) : left(left), op(op), right(right){}; - operator std::string(); + operator std::string() override; bool isLval() const override { return false; } - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; }; @@ -305,10 +207,10 @@ class Unary : public Expr { public: Unary(Token op, Expr* child) : op(op), child(child){}; - operator std::string(); + operator std::string() override; bool isLval() const override { return false; } - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; }; @@ -319,16 +221,15 @@ class Postfix : public Expr { public: Postfix(Token op, Expr* child) : op(op), child(child){}; - operator std::string() { return "postfix " + op.lexeme; }; + operator std::string() override { return "postfix " + op.lexeme; }; bool isLval() const override { return false; } - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; }; class Literal : public Expr { public: - virtual bool isTruthy() = 0; bool isLval() const override { return false; } }; @@ -339,11 +240,9 @@ class Integer : public Literal { public: Integer(Token token); Integer(int value) : value(value){}; - operator std::string(); - - bool isTruthy(); + operator std::string() override; - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; friend class Converter; @@ -356,11 +255,9 @@ class Double : public Literal { public: Double(Token token); Double(double value) : value(value){}; - operator std::string(); - - bool isTruthy(); + operator std::string() override; - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; friend class Converter; @@ -373,11 +270,9 @@ class String : public Literal { public: String(Token token) { value = token.lexeme; } String(std::string value) : value(value){}; - operator std::string(); + operator std::string() override; - bool isTruthy(); - - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; friend class Converter; @@ -390,11 +285,9 @@ class Boolean : public Literal { public: Boolean(bool value) : value(value){}; Boolean(Token token) { value = token.tokenType == TRUE; } - operator std::string(); - - bool isTruthy() { return value; } + operator std::string() override; - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; friend class Converter; @@ -406,11 +299,9 @@ class Function : public Literal { public: Function(FunDecl* fun) : fun(fun){}; - operator std::string() { return std::string(*fun); }; - - bool isTruthy() { return fun != nullptr; } + operator std::string() override { return std::string(*fun); }; - void accept(ExprVisitor* v) { v->visit(this); } + void accept(ExprVisitor* v) override { v->visit(this); } friend class EvalVisitor; friend class Converter; @@ -425,9 +316,9 @@ class Variable : public Expr { Variable(Token token) { name = token.lexeme; }; bool isLval() const override { return true; } - operator std::string() { return name; }; + operator std::string() override { return name; }; - void accept(ExprVisitor* v) { v->visit(this); }; + void accept(ExprVisitor* v) override { v->visit(this); }; friend class EvalVisitor; }; #endif diff --git a/main.cc b/main.cc index a40589d..8074fa7 100644 --- a/main.cc +++ b/main.cc @@ -10,7 +10,6 @@ using namespace std; CmdArgs* options; -ExecContext context; // Let the repl use a single global context in one run int run(const string& s) { Scanner scanner(s); auto tokens = scanner.scanTokens(); @@ -18,10 +17,12 @@ int run(const string& s) { for (auto t : tokens) cerr << t << endl; Parser parser; auto stmts = parser.parse(tokens); - ExecVisitor v(context); + /* + PrintVisitor v; for (auto s : stmts) { v.visit(s); } + */ return 0; } diff --git a/visitor.cc b/visitor.cc new file mode 100644 index 0000000..0d6fb33 --- /dev/null +++ b/visitor.cc @@ -0,0 +1,12 @@ +#include "visitor.h" + +#include +#include + +#include "ast.h" +using std::string; +void PrintExprVisitor::visit(Expr* expr) { std::cout << (string)*expr; } +void PrintExprVisitor::visit(Literal* expr) { std::cout << (string)*expr; } +void PrintExprVisitor::visit(Unary* expr) { std::cout << (string)*expr; } +void PrintExprVisitor::visit(Binary* expr) { std::cout << (string)*expr; } +void PrintExprVisitor::visit(Variable* expr) { std::cout << (string)*expr; } diff --git a/visitor.h b/visitor.h new file mode 100644 index 0000000..47c4d8b --- /dev/null +++ b/visitor.h @@ -0,0 +1,93 @@ +#pragma once +#include "context.h" +class Expr; +class Literal; +class Binary; +class Unary; +class Postfix; +class Variable; +class Call; + +class Declaration; +class VarDecl; +class FunDecl; + +class Statement; +class AssertStmt; +class PrintStmt; +class ExprStmt; +class BlockStmt; +class IfStmt; +class ForStmt; +class WhileStmt; +class BreakStmt; +class ReturnStmt; + +class DeclVisitor { + public: + virtual void visit(Declaration* d) = 0; + + virtual void visit(ExprStmt* st) = 0; + virtual void visit(AssertStmt* st) = 0; + virtual void visit(PrintStmt* st) = 0; + virtual void visit(VarDecl* d) = 0; + virtual void visit(FunDecl* d) = 0; + virtual void visit(BlockStmt* d) = 0; + virtual void visit(IfStmt* d) = 0; + virtual void visit(WhileStmt* d) = 0; + virtual void visit(BreakStmt* d) = 0; + virtual void visit(ReturnStmt* d) = 0; +}; + +class PrintVisitor : public DeclVisitor { + public: + // Return a PrintVisitor with an inner block scopping + virtual void visit(Declaration* d) override; + + virtual void visit(ExprStmt* st) override; + virtual void visit(AssertStmt* st) override; + virtual void visit(PrintStmt* st) override; + virtual void visit(VarDecl* d) override; + virtual void visit(FunDecl* d) override; + virtual void visit(BlockStmt* d) override; + virtual void visit(IfStmt* d) override; + virtual void visit(WhileStmt* d) override; + virtual void visit(BreakStmt* d) override; + virtual void visit(ReturnStmt* d) override; +}; + +class ExprVisitor { + public: + virtual void visit(Expr* expr) = 0; + virtual void visit(Literal* expr) = 0; + virtual void visit(Binary* expr) = 0; + virtual void visit(Unary* expr) = 0; + virtual void visit(Postfix* expr) = 0; + virtual void visit(Variable* expr) = 0; + virtual void visit(Call* expr) = 0; +}; + +class PrintExprVisitor : public ExprVisitor { + public: + void visit(Expr* expr); + void visit(Literal* expr); + void visit(Binary* expr); + void visit(Unary* expr); + void visit(Variable* expr); +}; + +class EvalVisitor : public ExprVisitor { + ExecContext context; + Literal* value = nullptr; + + public: + EvalVisitor(ExecContext context) : context(context){}; + void visit(Expr* expr); + void visit(Literal* expr); + void visit(Binary* expr); + void visit(Unary* expr); + void visit(Postfix* expr); + void visit(Variable* expr); + void visit(Call* expr); + Literal* getValue() { return value; } +};