-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathOperator.cpp
More file actions
176 lines (150 loc) · 5.91 KB
/
Copy pathOperator.cpp
File metadata and controls
176 lines (150 loc) · 5.91 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include "Operator.h"
#include "FetlangException.h"
std::string Operator::makeCodeKeyFrom(FetType lho, FetType rho) {
lho = decayFetType(lho);
rho = decayFetType(rho);
std::string return_value;
switch (lho) {
case FRACTION_TYPE:
return_value += "fraction";
break;
case CHAIN_TYPE:
return_value += "chain";
break;
default:
throw FetlangException("Can't make code key out of this type");
}
switch (rho) {
case FRACTION_TYPE:
return return_value + "/fraction";
case CHAIN_TYPE:
return return_value + "/chain";
default:
throw FetlangException("Can't make code key out of this type");
}
}
FetType makeSingleTypeFrom(const std::string& s) {
if (s == "reference") {
return REFERENCE_TYPE;
} else if (s == "stream") {
return STREAM_TYPE;
} else if (s == "fraction") {
return FRACTION_TYPE;
} else if (s == "chain") {
return CHAIN_TYPE;
}
throw FetlangException("No such type '" + s + "'");
}
std::pair<FetType, FetType> Operator::makeTypePairFrom(const std::string& s) {
if (s.find("/") == std::string::npos) {
throw FetlangException("No slash in code key '" + s + "'");
}
FetType first = makeSingleTypeFrom(s.substr(0, s.find("/")));
FetType second = makeSingleTypeFrom(s.substr(s.find("/") + 1));
return std::pair<FetType, FetType>(first, second);
}
bool Operator::hasCodeForExactly(FetType lho, FetType rho) const {
if (code_map.find(lho) != code_map.end()) {
if (code_map.at(lho).find(rho) != code_map.at(lho).end()) {
return true;
}
}
return false;
}
std::string Operator::getCodeForExactly(FetType lho, FetType rho) const {
if (!hasCodeForExactly(lho, rho)) {
throw("Operator " + name + " does not have code for exact types given");
}
return code_map.at(lho).at(rho);
}
bool Operator::hasCodeFor(FetType lho, FetType rho) const {
if (hasCodeForExactly(lho, rho) || hasCodeForExactly(lho, decayFetType(rho)) ||
hasCodeForExactly(decayFetType(lho), rho) ||
hasCodeForExactly(decayFetType(lho), decayFetType(rho))) {
return true;
}
return false;
}
std::string Operator::getCodeFor(FetType lho, FetType rho) const {
if (hasCodeForExactly(lho, rho)) return getCodeForExactly(lho, rho);
if (hasCodeForExactly(lho, decayFetType(rho))) return getCodeForExactly(lho, decayFetType(rho));
if (hasCodeForExactly(decayFetType(lho), rho)) return getCodeForExactly(decayFetType(lho), rho);
if (hasCodeForExactly(decayFetType(lho), decayFetType(rho)))
return getCodeForExactly(decayFetType(lho), decayFetType(rho));
throw FetlangException("Operator `" + name + "` does not have code for types given");
}
bool Operator::hasCodeFor(const std::string& ck) const {
auto type_pair = makeTypePairFrom(ck);
return hasCodeFor(type_pair.first, type_pair.second);
}
void Operator::addCode(const std::string& code_key, const std::string& code) {
auto type_pair = makeTypePairFrom(code_key);
if (hasCodeFor(type_pair.first, type_pair.second)) {
throw FetlangException("Can't add code, code already exists for code key in operator " +
getName());
}
code_map[type_pair.first][type_pair.second] = code;
}
// Get the exact LHO without decaying
bool Operator::hasExactLHO(FetType t) const { return code_map.find(t) != code_map.end(); }
bool Operator::hasExactRHO(FetType t) const {
const int number_of_types = 4;
const FetType types[number_of_types] = {FRACTION_TYPE, CHAIN_TYPE, REFERENCE_TYPE, STREAM_TYPE};
for (int i = 0; i < number_of_types; i++) {
if (hasCodeForExactly(types[i], t)) {
return true;
}
}
return false;
}
FetType Operator::inferLeftWithoutContext() const {
if (hasExactLHO(CHAIN_TYPE)) return CHAIN_TYPE;
if (hasExactLHO(FRACTION_TYPE)) return FRACTION_TYPE;
if (hasExactLHO(STREAM_TYPE)) return STREAM_TYPE;
if (hasExactLHO(REFERENCE_TYPE)) return REFERENCE_TYPE;
throw FetlangException("Can't infer lho type - apparently no LHO types exists in operator `" +
getName() + "`");
}
FetType Operator::inferRightWithoutContext() const {
if (hasExactRHO(CHAIN_TYPE)) return CHAIN_TYPE;
if (hasExactRHO(FRACTION_TYPE)) return FRACTION_TYPE;
if (hasExactRHO(STREAM_TYPE)) return STREAM_TYPE;
if (hasExactRHO(REFERENCE_TYPE)) return REFERENCE_TYPE;
throw FetlangException("Can't infer rho type - apparently no RHO types exists in operator `" +
getName() + "`");
}
FetType Operator::inferLeftByRight(FetType rho) const {
if (hasCodeFor(CHAIN_TYPE, rho)) return CHAIN_TYPE;
if (hasCodeFor(FRACTION_TYPE, rho)) return FRACTION_TYPE;
if (hasCodeFor(STREAM_TYPE, rho)) return STREAM_TYPE;
if (hasCodeFor(REFERENCE_TYPE, rho)) return REFERENCE_TYPE;
throw FetlangException("Can't infer left type in operator `" + getName() +
"`(no overloaded form of the operator exists for these types)");
}
FetType Operator::inferRightByLeft(FetType lho) const {
if (hasCodeFor(lho, CHAIN_TYPE)) return CHAIN_TYPE;
if (hasCodeFor(lho, FRACTION_TYPE)) return FRACTION_TYPE;
if (hasCodeFor(lho, STREAM_TYPE)) return STREAM_TYPE;
if (hasCodeFor(lho, REFERENCE_TYPE)) return REFERENCE_TYPE;
throw FetlangException("Can't infer the right type in operator `" + getName() +
"`(no overloaded form of the operator exists for these types)");
}
void Operator::verifyGrammar(const std::string& grammar) const {
if (!(grammar == "have" || grammar == "make" || grammar == "plain" || grammar == "bind")) {
throw FetlangException("Grammar must be have, make, or plain(given " + grammar + ")");
}
}
Operator::Operator(const std::string& name) { setName(name); }
void Operator::addGrammar(const std::string& grammar) {
verifyGrammar(grammar);
grammars.emplace(grammar);
}
bool Operator::hasGrammar(const std::string& grammar) const {
verifyGrammar(grammar);
return grammars.find(grammar) != grammars.end();
}
ComparisonOperator::ComparisonOperator(const std::string& name) { setName(name); }
bool ComparisonOperator::hasGrammar(const std::string& s) const { return s == "comparison"; }
void ComparisonOperator::addGrammar(const std::string&) {
throw FetlangException("ComparisonOperator can't add grammar");
}