2
This file is part of TON Blockchain Library.
4
TON Blockchain Library is free software: you can redistribute it and/or modify
5
it under the terms of the GNU Lesser General Public License as published by
6
the Free Software Foundation, either version 2 of the License, or
7
(at your option) any later version.
9
TON Blockchain Library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
17
Copyright 2017-2020 Telegram Systems LLP
29
int TypeExpr::holes = 0, TypeExpr::type_vars = 0; // not thread safe, but it is ok for now
31
void TypeExpr::compute_width() {
39
for (TypeExpr* arg : args) {
52
for (TypeExpr* arg : args) {
67
bool TypeExpr::recompute_width() {
72
for (TypeExpr* arg : args) {
76
if (min > maxw || max < minw) {
94
for (TypeExpr* arg : args) {
95
if (arg->minw > 1 || arg->maxw < 1 || arg->minw > arg->maxw) {
106
int TypeExpr::extract_components(std::vector<TypeExpr*>& comp_list) {
107
if (constr != te_Indirect && constr != te_Tensor) {
108
comp_list.push_back(this);
112
for (TypeExpr* arg : args) {
113
res += arg->extract_components(comp_list);
118
TypeExpr* TypeExpr::new_map(TypeExpr* from, TypeExpr* to) {
119
return new TypeExpr{te_Map, std::vector<TypeExpr*>{from, to}};
122
void TypeExpr::replace_with(TypeExpr* te2) {
126
constr = te_Indirect;
134
bool TypeExpr::remove_indirect(TypeExpr*& te, TypeExpr* forbidden) {
136
while (te->constr == te_Indirect) {
139
if (te->constr == te_Unknown) {
140
return te != forbidden;
143
for (auto& x : te->args) {
144
res &= remove_indirect(x, forbidden);
149
std::vector<TypeExpr*> TypeExpr::remove_forall(TypeExpr*& te) {
150
func_assert(te && te->constr == te_ForAll);
151
func_assert(te->args.size() >= 1);
152
std::vector<TypeExpr*> new_vars;
153
for (std::size_t i = 1; i < te->args.size(); i++) {
154
new_vars.push_back(new_hole(1));
157
// std::cerr << "removing universal quantifier in " << te << std::endl;
159
remove_forall_in(te, te2, new_vars);
160
// std::cerr << "-> " << te << std::endl;
164
bool TypeExpr::remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector<TypeExpr*>& new_vars) {
166
func_assert(te2 && te2->constr == te_ForAll);
167
if (te->constr == te_Var) {
168
for (std::size_t i = 0; i < new_vars.size(); i++) {
169
if (te == te2->args[i + 1]) {
176
if (te->constr == te_ForAll) {
179
if (te->args.empty()) {
182
auto te1 = new TypeExpr(*te);
184
for (auto& arg : te1->args) {
185
res |= remove_forall_in(arg, te2, new_vars);
195
void TypeExpr::show_width(std::ostream& os) {
205
std::ostream& operator<<(std::ostream& os, TypeExpr* type_expr) {
207
return os << "(null-type-ptr)";
209
return type_expr->print(os);
212
std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
215
return os << "??" << value;
217
if (value >= -26 && value < 0) {
218
return os << "_" << (char)(91 + value);
219
} else if (value >= 0 && value < 26) {
220
return os << (char)(65 + value);
222
return os << "TVAR" << value;
225
return os << args[0];
233
return os << "slice";
235
return os << "builder";
239
return os << "tuple";
243
return os << "atomic-type-" << value;
247
if (lex_level > -127) {
250
auto c = args.size();
252
for (const auto& x : args) {
259
if (lex_level > -127) {
266
auto c = args.size();
267
if (c == 1 && args[0]->constr == te_Tensor) {
268
args[0]->print(os, -127);
270
for (const auto& x : args) {
280
func_assert(args.size() == 2);
284
args[0]->print(os, 1);
293
func_assert(args.size() >= 1);
298
for (std::size_t i = 1; i < args.size(); i++) {
299
os << (i > 1 ? ' ' : '(');
310
return os << "unknown-type-expr-" << constr;
314
void UnifyError::print_message(std::ostream& os) const {
315
os << "cannot unify type " << te1 << " with " << te2;
321
std::ostream& operator<<(std::ostream& os, const UnifyError& ue) {
322
ue.print_message(os);
326
std::string UnifyError::message() const {
327
std::ostringstream os;
328
UnifyError::print_message(os);
332
void check_width_compat(TypeExpr* te1, TypeExpr* te2) {
333
if (te1->minw > te2->maxw || te2->minw > te1->maxw) {
334
std::ostringstream os{"cannot unify types of widths ", std::ios_base::ate};
338
throw UnifyError{te1, te2, os.str()};
342
void check_update_widths(TypeExpr* te1, TypeExpr* te2) {
343
check_width_compat(te1, te2);
344
te1->minw = te2->minw = std::max(te1->minw, te2->minw);
345
te1->maxw = te2->maxw = std::min(te1->maxw, te2->maxw);
346
func_assert(te1->minw <= te1->maxw);
349
void unify(TypeExpr*& te1, TypeExpr*& te2) {
350
func_assert(te1 && te2);
351
// std::cerr << "unify( " << te1 << " , " << te2 << " )\n";
352
while (te1->constr == TypeExpr::te_Indirect) {
355
while (te2->constr == TypeExpr::te_Indirect) {
361
if (te1->constr == TypeExpr::te_ForAll) {
363
std::vector<TypeExpr*> new_vars = TypeExpr::remove_forall(te);
364
for (TypeExpr* t : new_vars) {
365
t->was_forall_var = true;
368
for (TypeExpr* t : new_vars) {
369
t->was_forall_var = false;
373
if (te2->constr == TypeExpr::te_ForAll) {
375
std::vector<TypeExpr*> new_vars = TypeExpr::remove_forall(te);
376
for (TypeExpr* t : new_vars) {
377
t->was_forall_var = true;
380
for (TypeExpr* t : new_vars) {
381
t->was_forall_var = false;
385
if (te1->was_forall_var && te2->constr == TypeExpr::te_Tensor) {
386
throw UnifyError{te1, te2, "cannot unify generic type and tensor"};
388
if (te2->was_forall_var && te1->constr == TypeExpr::te_Tensor) {
389
throw UnifyError{te2, te1, "cannot unify generic type and tensor"};
391
if (te1->constr == TypeExpr::te_Unknown) {
392
if (te2->constr == TypeExpr::te_Unknown) {
393
func_assert(te1->value != te2->value);
395
if (!TypeExpr::remove_indirect(te2, te1)) {
396
throw UnifyError{te1, te2, "type unification results in an infinite cyclic type"};
398
check_update_widths(te1, te2);
399
te1->replace_with(te2);
403
if (te2->constr == TypeExpr::te_Unknown) {
404
if (!TypeExpr::remove_indirect(te1, te2)) {
405
throw UnifyError{te2, te1, "type unification results in an infinite cyclic type"};
407
check_update_widths(te2, te1);
408
te2->replace_with(te1);
412
if (te1->constr != te2->constr || te1->value != te2->value || te1->args.size() != te2->args.size()) {
413
throw UnifyError{te1, te2};
415
for (std::size_t i = 0; i < te1->args.size(); i++) {
416
unify(te1->args[i], te2->args[i]);
418
if (te1->constr == TypeExpr::te_Tensor) {
419
if (!te1->recompute_width()) {
420
throw UnifyError{te1, te2, "type unification incompatible with known width of first type"};
422
if (!te2->recompute_width()) {
423
throw UnifyError{te2, te1, "type unification incompatible with known width of first type"};
425
check_update_widths(te1, te2);
427
te1->replace_with(te2);