276 lines
7.8 KiB
C++
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;
|
|
}
|