-
Notifications
You must be signed in to change notification settings - Fork 1
/
expression.h
81 lines (79 loc) · 2.76 KB
/
expression.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#pragma once
#include "boolean_visitor.h"
#include "integer_visitor.h"
struct Expression {
ExpressionType expression;
template <typename... Ts>
Expression(Ts &&... xs) : expression(std::forward<Ts>(xs)...) {}
auto get() const -> const ExpressionType & { return expression; }
auto get() -> ExpressionType & { return expression; }
auto operator+(Expression &expr) -> Expression {
return std::visit(AddVisitor{}, get(), expr.expression);
}
auto operator+(Expression &&expr) -> Expression {
return std::visit(AddVisitor{}, get(), expr.expression);
}
auto operator-() -> Expression { return std::visit(MinusVisitor{}, get()); }
auto operator-(Expression &expr) -> Expression {
return std::visit(MinusVisitor{}, get(), expr.expression);
}
auto operator-(Expression &&expr) -> Expression {
return std::visit(MinusVisitor{}, get(), expr.expression);
}
auto operator*(Expression &expr) -> Expression {
return std::visit(MultiplyVisitor{}, get(), expr.expression);
}
auto operator*(Expression &&expr) -> Expression {
return std::visit(MultiplyVisitor{}, get(), expr.expression);
}
auto operator/(Expression &expr) -> Expression {
return std::visit(DivideVisitor{}, get(), expr.expression);
}
auto operator/(Expression &&expr) -> Expression {
return std::visit(DivideVisitor{}, get(), expr.expression);
}
auto operator!() -> Expression { return std::visit(NotVisitor{}, get()); }
auto operator&&(Expression &expr) -> Expression {
return std::visit(AndVisitor{}, get(), expr.expression);
}
auto operator&&(Expression &&expr) -> Expression {
return std::visit(AndVisitor{}, get(), expr.expression);
}
auto operator||(Expression &expr) -> Expression {
return std::visit(OrVisitor{}, get(), expr.expression);
}
auto operator||(Expression &&expr) -> Expression {
return std::visit(OrVisitor{}, get(), expr.expression);
}
auto operator==(Expression &expr) -> Expression {
return std::visit(EqualsVisitor{}, get(), expr.expression);
}
auto operator==(Expression &&expr) -> Expression {
return std::visit(EqualsVisitor{}, get(), expr.expression);
}
auto isBool() -> bool {
return std::visit(
[](ExpressionType &&arg) -> bool {
return std::holds_alternative<bool>(arg);
},
get());
}
auto isInt() -> bool {
return std::visit(
[](ExpressionType &&arg) -> bool {
return std::holds_alternative<int>(arg);
},
get());
}
auto typeCheck() -> bool { return isBool() || isInt(); }
template <typename T> auto evaluateT() {
return std::visit(
[](ExpressionType &&arg) -> T { return std::get<T>(arg); }, get());
}
auto evaluate() -> int {
if (isInt()) {
return evaluateT<int>();
}
return evaluateT<bool>();
}
};