276 lines
7.8 KiB
C++

#include "expr.hh"
#include "../tokenizer.hh"
#include <cassert>
#include <memory>
#include <utility>
Expr::Expr(ExprType type, ExprVariant value) : type{type}, value{value} {}
// Copy constructor
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);
assert(ptr != nullptr);
value = std::make_shared<_Binary>(*ptr);
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Grouping>(*ptr);
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Literal>(*ptr);
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Unary>(*ptr);
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Variable>(*ptr);
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Assign>(*ptr);
break;
}
}
}
// Move constructor
Expr::Expr(Expr &&other) : type{other.type}, value{std::move(other.value)} {
switch(type) {
case ExprType::BINARY: {
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(other.value);
assert(ptr != nullptr);
ptr.reset();
break;
}
}
}
// Copy assignment
Expr &Expr::operator=(const Expr &other) {
if (this == &other) {
return *this;
}
switch(type) {
case ExprType::BINARY: {
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
}
type = other.type;
switch(type) {
case ExprType::BINARY: {
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Binary>(*ptr);
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Grouping>(*ptr);
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Literal>(*ptr);
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Unary>(*ptr);
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Variable>(*ptr);
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(other.value);
assert(ptr != nullptr);
value = std::make_shared<_Assign>(*ptr);
break;
}
}
return *this;
}
// Move assignment
Expr &Expr::operator=(Expr &&other) {
if (this == &other) {
return *this;
}
switch(type) {
case ExprType::BINARY: {
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(value);
assert(ptr != nullptr);
ptr.reset();
break;
}
}
type = other.type;
switch(type) {
case ExprType::BINARY: {
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
case ExprType::GROUPING: {
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
case ExprType::LITERAL: {
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
case ExprType::UNARY: {
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
case ExprType::VARIABLE: {
std::shared_ptr<_Variable> ptr = std::get<std::shared_ptr<_Variable>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
case ExprType::ASSIGN: {
std::shared_ptr<_Assign> ptr = std::get<std::shared_ptr<_Assign>>(other.value);
assert(ptr != nullptr);
value = std::move(other.value);
ptr.reset();
break;
}
}
return *this;
}