#ifndef STMT_HH #define STMT_HH #include "expr.hh" #include #include #include struct Stmt; struct _Expression; struct _Print; struct _Var; struct _Block; enum class StmtType { EXPRESSION, PRINT, VAR, BLOCK, }; using StmtVariant = std::variant< std::shared_ptr<_Expression>, std::shared_ptr<_Print>, std::shared_ptr<_Var>, std::shared_ptr<_Block> >; #define Expression(EXPR) (Stmt{StmtType::EXPRESSION, std::make_shared<_Expression>(EXPR)}) #define Print(EXPR) (Stmt{StmtType::PRINT, std::make_shared<_Print>(EXPR)}) #define Var(NAME, EXPR) (Stmt{StmtType::VAR, std::make_shared<_Var>(NAME, EXPR)}) #define Block(STATEMENTS) (Stmt{StmtType::BLOCK, std::make_shared<_Block>(STATEMENTS)}) struct Stmt { Stmt(StmtType type, StmtVariant value); // Copy constructor Stmt(const Stmt &other); // Move constructor Stmt(Stmt &&other) noexcept; // Copy assignment Stmt &operator=(const Stmt &other); // Move assignment Stmt &operator=(Stmt &&other) noexcept; ~Stmt() = default; StmtType type; StmtVariant value; }; struct _Expression { _Expression(const Expr &expr) : expr{expr} {} Expr expr; }; struct _Print { _Print(const Expr &expr) : expr{expr} {} Expr expr; }; struct _Var { _Var(const Token &name, const Expr &expr) : name{name}, expr{expr} {} Token name; Expr expr; }; struct _Block { _Block(const std::vector &statements) : statements{statements} {} std::vector statements; }; #endif