And that's why I hate C++
This commit is contained in:
		@@ -18,15 +18,13 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
  // run_interpreter(argc, argv);
 | 
					  // run_interpreter(argc, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Token unary_op{TokenType::MINUS, "-", Object{}, 1};
 | 
					  Token unary_op{TokenType::MINUS, "-", Object{}, 1};
 | 
				
			||||||
  Expr left_literal = Literal(123);
 | 
					  Expr left{unary_op, Expr{123}};
 | 
				
			||||||
  Expr left = Unary(unary_op, left_literal.to_expr_ptr());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Token op{TokenType::STAR, "*", Object{}, 1};
 | 
					  Token op{TokenType::STAR, "*", Object{}, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Expr right_literal = Literal(45.67);
 | 
					  Expr right{Expr{45.67}, nullptr};
 | 
				
			||||||
  Expr right = Grouping(right_literal.to_expr_ptr());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Expr expr = Binary(left.to_expr_ptr(), op, right.to_expr_ptr());
 | 
					  Expr expr{left, op, right};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  AstPrinter printer{};
 | 
					  AstPrinter printer{};
 | 
				
			||||||
  std::cout << printer.print(expr) << '\n';
 | 
					  std::cout << printer.print(expr) << '\n';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,42 +1,90 @@
 | 
				
			|||||||
#include "expr.hh"
 | 
					#include "expr.hh"
 | 
				
			||||||
#include "../tokenizer.hh"
 | 
					#include "../tokenizer.hh"
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Expr::Expr(const Expr &other) : type{other.type} {
 | 
				
			||||||
 | 
					  switch(type) {
 | 
				
			||||||
 | 
					    case ExprType::BINARY: {
 | 
				
			||||||
 | 
					      std::shared_ptr<Binary> ptr = std::get<std::shared_ptr<Binary>>(other.value);
 | 
				
			||||||
 | 
					      value = std::make_shared<Binary>(*ptr);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case ExprType::GROUPING: {
 | 
				
			||||||
 | 
					      std::shared_ptr<Grouping> ptr = std::get<std::shared_ptr<Grouping>>(other.value);
 | 
				
			||||||
 | 
					      value = std::make_shared<Grouping>(*ptr);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case ExprType::LITERAL: {
 | 
				
			||||||
 | 
					      std::shared_ptr<Literal> ptr = std::get<std::shared_ptr<Literal>>(other.value);
 | 
				
			||||||
 | 
					      value = std::make_shared<Literal>(*ptr);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case ExprType::UNARY: {
 | 
				
			||||||
 | 
					      std::shared_ptr<Unary> ptr = std::get<std::shared_ptr<Unary>>(other.value);
 | 
				
			||||||
 | 
					      value = std::make_shared<Unary>(*ptr);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Move constructor
 | 
				
			||||||
 | 
					Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Binary expressoin
 | 
				
			||||||
 | 
					Expr::Expr(Expr left, Token op, Expr right)
 | 
				
			||||||
 | 
					  : type{ExprType::BINARY}, value{std::make_shared<Binary>(left, op, right)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Literal expression
 | 
				
			||||||
 | 
					Expr::Expr(Object value)
 | 
				
			||||||
 | 
					  : type{ExprType::LITERAL}, value{std::make_shared<Literal>(value)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unary expressoin
 | 
				
			||||||
 | 
					Expr::Expr(Token op, Expr right)
 | 
				
			||||||
 | 
					  : type{ExprType::UNARY}, value{std::make_shared<Unary>(op, right)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Group expression
 | 
				
			||||||
 | 
					// Has to take an extra parameter to avoid conflicting with copy constructor
 | 
				
			||||||
 | 
					Expr::Expr(Expr expr, void *ptr)
 | 
				
			||||||
 | 
					  : type{ExprType::GROUPING}, value{std::make_shared<Grouping>(expr)} { (void)ptr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string AstPrinter::print(const Expr &expr) {
 | 
					std::string AstPrinter::print(const Expr &expr) {
 | 
				
			||||||
  switch (expr.type) {
 | 
					  switch (expr.type) {
 | 
				
			||||||
    case ExprType::BINARY: {
 | 
					    case ExprType::BINARY: {
 | 
				
			||||||
      _Binary node = std::get<_Binary>(expr.value);
 | 
					      std::shared_ptr<Binary> binary = std::get<std::shared_ptr<Binary>>(expr.value);
 | 
				
			||||||
      assert(node.left != NULL && node.right != NULL);
 | 
					      assert(binary != nullptr);
 | 
				
			||||||
      return parenthesize(node.op.lexeme, {*node.left, *node.right});
 | 
					      return parenthesize(binary->op.lexeme, {binary->left, binary->right});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ExprType::GROUPING: {
 | 
					    case ExprType::GROUPING: {
 | 
				
			||||||
      _Grouping node = std::get<_Grouping>(expr.value);
 | 
					      std::shared_ptr<Grouping> group = std::get<std::shared_ptr<Grouping>>(expr.value);
 | 
				
			||||||
      assert(node.expression != NULL);
 | 
					      assert(group != nullptr);
 | 
				
			||||||
      return parenthesize("group", {*node.expression});
 | 
					      return parenthesize("group", {group->expr});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ExprType::LITERAL: {
 | 
					    case ExprType::LITERAL: {
 | 
				
			||||||
      _Literal node = std::get<_Literal>(expr.value);
 | 
					      std::shared_ptr<Literal> literal = std::get<std::shared_ptr<Literal>>(expr.value);
 | 
				
			||||||
      switch (node.value.type) {
 | 
					      assert(literal != nullptr);
 | 
				
			||||||
 | 
					      switch (literal->value.type) {
 | 
				
			||||||
        case ObjectType::NIL:
 | 
					        case ObjectType::NIL:
 | 
				
			||||||
          return "nil";
 | 
					          return "nil";
 | 
				
			||||||
        case ObjectType::IDENTIFIER:
 | 
					        case ObjectType::IDENTIFIER:
 | 
				
			||||||
        case ObjectType::STRING_LIT: {
 | 
					        case ObjectType::STRING_LIT: {
 | 
				
			||||||
          std::string value = std::get<std::string>(node.value.value);
 | 
					          std::string value = std::get<std::string>(literal->value.value);
 | 
				
			||||||
          return value;
 | 
					          return value;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case ObjectType::NUMBER: {
 | 
					        case ObjectType::NUMBER: {
 | 
				
			||||||
          double value = std::get<double>(node.value.value);
 | 
					          double value = std::get<double>(literal->value.value);
 | 
				
			||||||
          return std::to_string(value);
 | 
					          return std::to_string(value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ExprType::UNARY: {
 | 
					    case ExprType::UNARY: {
 | 
				
			||||||
      _Unary node = std::get<_Unary>(expr.value);
 | 
					      std::shared_ptr<Unary> unary = std::get<std::shared_ptr<Unary>>(expr.value);
 | 
				
			||||||
      assert(node.right != NULL);
 | 
					      assert(unary != nullptr);
 | 
				
			||||||
      return parenthesize(node.op.lexeme, {*node.right});
 | 
					      return parenthesize(unary->op.lexeme, {unary->right});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,27 +7,10 @@
 | 
				
			|||||||
#include <variant>
 | 
					#include <variant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Expr;
 | 
					struct Expr;
 | 
				
			||||||
 | 
					struct Binary;
 | 
				
			||||||
using ExprPtr = std::shared_ptr<Expr>;
 | 
					struct Grouping;
 | 
				
			||||||
 | 
					struct Literal;
 | 
				
			||||||
struct _Binary {
 | 
					struct Unary;
 | 
				
			||||||
  ExprPtr left;
 | 
					 | 
				
			||||||
  Token op;
 | 
					 | 
				
			||||||
  ExprPtr right;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _Grouping {
 | 
					 | 
				
			||||||
  ExprPtr expression;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _Literal {
 | 
					 | 
				
			||||||
  Object value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _Unary {
 | 
					 | 
				
			||||||
  Token op;
 | 
					 | 
				
			||||||
  ExprPtr right;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class ExprType {
 | 
					enum class ExprType {
 | 
				
			||||||
  BINARY,
 | 
					  BINARY,
 | 
				
			||||||
@@ -36,30 +19,59 @@ enum class ExprType {
 | 
				
			|||||||
  UNARY,
 | 
					  UNARY,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using ExprVariant = std::variant<_Binary, _Grouping, _Literal, _Unary>;
 | 
					using ExprVariant = std::variant<
 | 
				
			||||||
 | 
					  std::shared_ptr<Binary>,
 | 
				
			||||||
 | 
					  std::shared_ptr<Grouping>,
 | 
				
			||||||
 | 
					  std::shared_ptr<Literal>,
 | 
				
			||||||
 | 
					  std::shared_ptr<Unary>
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Expr {
 | 
					struct Expr {
 | 
				
			||||||
 | 
					  // Copy constructor
 | 
				
			||||||
 | 
					  Expr(const Expr &other);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Move constructor
 | 
				
			||||||
 | 
					  Expr(const Expr &&other);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Binary expressoin
 | 
				
			||||||
 | 
					  Expr(Expr left, Token op, Expr right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Literal expression
 | 
				
			||||||
 | 
					  Expr(Object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Unary expressoin
 | 
				
			||||||
 | 
					  Expr(Token op, Expr right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Group expression
 | 
				
			||||||
 | 
					  // Has to take an extra parameter to avoid conflicting with copy constructor
 | 
				
			||||||
 | 
					  Expr(Expr expr, void *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ExprType type;
 | 
					  ExprType type;
 | 
				
			||||||
  ExprVariant value;
 | 
					  ExprVariant value;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  ExprPtr to_expr_ptr() { return std::make_shared<Expr>(*this); }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline Expr Binary(ExprPtr left, Token op, ExprPtr right) {
 | 
					struct Binary {
 | 
				
			||||||
  return Expr{ExprType::BINARY, _Binary{left, op, right}};
 | 
					  Binary(Expr left, Token op, Expr right) : left{left}, op{op}, right{right} {}
 | 
				
			||||||
}
 | 
					  Expr left;
 | 
				
			||||||
 | 
					  Token op;
 | 
				
			||||||
 | 
					  Expr right;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline Expr Grouping(ExprPtr expr) {
 | 
					struct Grouping {
 | 
				
			||||||
  return Expr{ExprType::GROUPING, _Grouping{expr}};
 | 
					  Grouping(Expr expr) : expr{expr} {}
 | 
				
			||||||
}
 | 
					  Expr expr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline Expr Literal(Object value) {
 | 
					struct Literal {
 | 
				
			||||||
  return Expr{ExprType::LITERAL, _Literal{value}};
 | 
					  Literal(Object value) : value{value} {}
 | 
				
			||||||
}
 | 
					  Object value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline Expr Unary(Token op, ExprPtr right) {
 | 
					struct Unary {
 | 
				
			||||||
  return Expr{ExprType::UNARY, _Unary{op, right}};
 | 
					  Unary(Token op, Expr right) : op{op}, right{right} {}
 | 
				
			||||||
}
 | 
					  Token op;
 | 
				
			||||||
 | 
					  Expr right;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AstPrinter {
 | 
					class AstPrinter {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user